1. 程式人生 > >C++資料結構---連結串列(連結串列建立)

C++資料結構---連結串列(連結串列建立)

連結串列

是比較重要的一種資料結構,它的有點在於:插入和刪除操作。
與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;
}

結果如圖所示:
程式碼執行結果圖