C++資料結構---連結串列(連結串列建立)
阿新 • • 發佈:2019-02-17
連結串列
是比較重要的一種資料結構,它的有點在於:插入和刪除操作。
與vector不同,list插入和刪除不需要移動其餘元素,而vector在中間插入時,需要將後面的元素依次向後移動,時間複雜度與待移動的元素有關,可見,元素越多,消耗的時間越多。而list插入元素時,只需要將改變“連結線”,即pred和succ即可,不需要對元素進行移動。刪除操作同上。
但是,list的缺點也是很明顯的:不同於vector的按下標索引,list是一步一步的從頭到尾進行遍歷,直到找到該元素為止。
所以:
對於連結串列:適用於要經常插入與刪除,而對於隨機訪問操作較少的情況
對於vector:適用於隨機訪問操作較多的情況
本文附上鍊表建立的整個程式碼(過載了vector的按下標索引符號[]),包括自己寫的連結串列節點建立的標頭檔案(節點建立可以看C++資料結構—連結串列(連結串列節點建立))
連結串列建立程式碼如下:
#pragma once
#ifndef LIST_HH
#define LIST_HH
#include<iostream>
#include"ListNode.h"
using namespace std;
template <typename T> class List {
private:
int _size;
ListNodePosi(T) header;
ListNodePosi(T) trailer;
public :
List() { init(); }
~List();
void init();//初始化節點
void clear();//清除連結串列
int size() { return _size;}//連結串列的長度
T& operator[](int r)const;//[]操作符過載
T remove(ListNodePosi(T) p);//刪除結點
void deduplicate();//去重複結點(無序序列)
//**********排序操作**********//
void insertsort();//插入排序
void selectionSort(ListNodePosi(T) p, int n);//選擇排序
void sort(ListNodePosi(T) p, int n);
void sort() { sort(first(), _size); }
//***************************//
ListNodePosi(T) first() const { return header->succ; }//除了頭結點的首結點,這裡假設連結串列的第一個結點前面有個虛擬的head結點
ListNodePosi(T) last() const { return trailer->pred; }//同上
ListNodePosi(T) find(T const& _Val, int n, ListNodePosi(T) p);
//**********插入操作**********//
ListNodePosi(T) insertAsFirst(T const& _Val);
ListNodePosi(T) insertAsLast(T const& _Val);
ListNodePosi(T) insertAsBefore(ListNodePosi(T) p, T const& _Val);
ListNodePosi(T) insertAsAfter(ListNodePosi(T) p, T const& _Val);
ListNodePosi(T) insertAsSucc(T const& _Val);
ListNodePosi(T) insertAsPred(T const& _Val);
//***************************//
ListNodePosi(T) search(T const& _Val, int n, ListNodePosi(T) p); //搜尋操作
ListNodePosi(T) getNode(T const& _Val);//獲取當前值的節點位置
ListNodePosi(T) selectmax(ListNodePosi(T) p, int n);
int max_data() { return (selectmax(first(),_size)->data);}
};
template <typename T>
void List<T>::init()
{
header = new ListNode<T>;
trailer = new ListNode<T>;
header->succ = trailer;
header->pred = NULL;
trailer->succ = NULL;
trailer->pred = header;
_size = 0;
}
template <typename T>
T& List<T>::operator[](int r) const
{
ListNodePosi(T) p = first();
while (0 < r--) p = p->succ;
return p->data;
}
template <typename T>
ListNodePosi(T) List<T>::find(T const& _Val, int n, ListNodePosi(T) p)
{
while (0 < n--)
if (_Val == (p = p->pred)->data) return p;
return NULL;
}
template <typename T>
ListNodePosi(T) List<T>::getNode(T const& _Val)
{
ListNodePosi(T) p = find(_Val,_size,last());
return p;
}
template <typename T>
ListNodePosi(T) List<T>::insertAsFirst(T const& _Val)
{
_size++; return header->insertAsSucc(_Val);
}
template <typename T>
ListNodePosi(T) List<T>::insertAsLast(T const& _Val)
{
_size++; return trailer->insertAsPred(_Val);
}
template <typename T>
ListNodePosi(T) List<T>::insertAsBefore(ListNodePosi(T) p,T const& _Val)
{
_size++; return p->insertAsPred(_Val);
}
template <typename T>
ListNodePosi(T) List<T>::insertAsAfter(ListNodePosi(T) p,T const& _Val)
{
_size++; return p->insertAsSucc(_Val);
}
template <typename T>
ListNodePosi(T) ListNode<T>::insertAsPred(T const& _Val)
{
ListNodePosi(T) x = new ListNode(_Val, pred, this);
pred->succ = x; pred = x;
return x;
}
template <typename T>
ListNodePosi(T) ListNode<T>::insertAsSucc(T const& _Val)
{
ListNodePosi(T) y = new ListNode(_Val, this, succ);
succ->pred = y; succ= y;
return y;
}
template <typename T>
T List<T>::remove(ListNodePosi(T) p)
{
T _Val = p -> data;
p->pred->succ = p->succ;//待刪除節點p的前驅的後繼給p的後繼
p->succ->pred = p->pred;//p的後繼的前驅給p的p的前驅
delete p;
_size--;
return _Val;
}
template <typename T> List<T>::~List()
{
clear(); delete header; delete trailer;
}
template <typename T>
void List<T>::clear()
{
while (0 < _size)
remove(header->succ);
}
template <typename T>
void List<T>::deduplicate()
{
if (_size < 2) return;
ListNodePosi(T) p = first(); int r = 1;
while (trailer != (p = p->succ))
{
ListNodePosi(T) q = find(p->data, r, p);
q ? remove(q) : r++;
}
}
template <typename T>
ListNodePosi(T) List<T>::search(T const& _Val, int n, ListNodePosi(T) p)
{
while (0 <= n--)
{
if ((p = p->pred)->data <= _Val) break;
}
return p;
}
template <typename T>
ListNodePosi(T) List<T>::selectmax(ListNodePosi(T) p,int n)
{
ListNodePosi(T) max = p;
ListNodePosi(T) cur = p;
for (ListNodePosi(T) cur = p; n>0; n--)
{
if (max->data < cur->data) max = cur;
cur = cur->succ;
}
return max;
}
template <typename T>
void List<T>::insertsort()
{
printf("InsertSort ...\n");
ListNodePosi(T) q = first();
for (int i = 0; i < _size; i++)
{
insertAsAfter(search(q->data, i, q), q->data);
q = q->succ;
remove(q->pred);
}
}
template <typename T>
void List<T>::selectionSort(ListNodePosi(T) p, int n) {
printf("SelectionSort ...\n");
ListNodePosi(T) head = p->pred; ListNodePosi(T) tail = p;
for (int i = 0; i < n; i++) tail = tail->succ; //
while (1 < n) {
ListNodePosi(T) max = selectmax(head->succ, n); //
insertAsBefore(tail, remove(max)); //將其移至無序區間末尾(作為有序區間新的首元素)
tail = tail->pred; n--;
}
}
template <typename T> void List<T>::sort(ListNodePosi(T) p, int n) { //列表區間排序
switch (rand() % 2) { //隨機選取排序演算法
case 1: insertsort(); break;
case 2: selectionSort(p, n); break;
}
}
#endif // !LIST_HH
測試程式碼:
#include<iostream>
#include"ListNode.h"
#include"List.h"
using namespace std;
int main()
{
List<int> L;
printf("*****請輸入你要建立的結點(輸入完按回車繼續)*******\n");
int a;
while (cin>>a&&a!='q') {
L.insertAsLast(a);
}
printf("*******原陣列為*******\n");
for (int i = 0; i < L.size(); i++)
cout << L[i] << " ";
printf("\n");
printf("*******連結串列長度為***********\n");
cout << L.size() << endl;
printf("*******排序並去重複後的陣列為*******\n");
L.sort();
L.deduplicate();
for (int i = 0; i < L.size(); i++)
cout << L[i] << " ";
cout << endl;
printf("*******最大數為*******\n");
cout << L.max_data() << endl;
printf("*******連結串列清除後的連結串列長度為***********\n");
L.clear();
cout << L.size() << endl;
system("pause");
return 0;
}
結果如圖所示: