釋出
2013 年 12 月 7 日 (最後更新: 2013 年 12 月 8 日)

連結串列

評分: 3.6/5 (1099 票)
*****
一組相同型別的資料項,其中每個資料項指向(“連結到”)列表中的下一個資料項。資料項的順序不是定義的一部分,因此我們不考慮順序。順序取決於用法。


注意: 由於元素序列不是連結串列定義的一部分,因此可以使用連結串列實現許多其他結構。
例如,如果資料項根據插入列表的順序進行排序,這對應於堆疊,其中頂層資料項由列表的頭指標指向。

頭指標

  • 列表頭是指向列表中第一個資料項的特殊指標。
  • 最後一個節點(尾部)指向一個NULL地址
  • 在處理列表時,任何節點只能在訪問了它之前的所有其他節點後才能訪問。此屬性也可以稱為嚴格順序訪問 (SSA)。

    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      // implementation of LinkedList
      // the Node class will be given later
      // Author: Ali Selcuk AKYUZ
      // Mail: selcuk@retinarobotics.com || e174043@metu.edu.tr
      // Electrical and Electronics Engineering Department
      // Middle East Technical University - ANKARA
      // If any questions please send me an email
      
      #include <iostream>
      #include "Node.cpp"
      using namespace std;
      int main ()
      {
        Node<char> *p,*q,*r;
        // Link the nodes with each other
        q = new Node<char>('B'); // here nxtptr is passed by a nullptr by default
        p = new Node<char>('A',q);
        r = new Node<char>('C');
      
        // modify the list
        q->InsertAfter(r);
        /*
        Call the InsertAfter method that belongs to the object pointed by q, as
        paramater, pass to it the address contained in r.
        */
      
        cout << "p:" << p->data << endl;                 // "A" will be printed out
        cout << "p_next:" << p->NextNode()->data << endl;  // "B" will be printed out
        cout << "q:" << q->data << endl;                 // "B" will be printed out
        cout << "q_next:" << q->NextNode()->data << endl;  // "C" will be printed out
        cout << "r:" << r->data << endl;                 // "C" will be printed out
      
        p = p->NextNode(); // p now points to the node coming after the node it was
                           // previously pointing to.
        cout << endl;
        cout << "p:" << p->data << endl;                 // "B" will be printed out
      
        r = q->DeleteAfter();        // copy to r the address of the node pointed by
        //the node pointed by the node pointed by q, and remove that node from the list
      
        Node<char> *head;
        head = GetNode('A',GetNode('B',GetNode('C')));
        /*
        Here above method, creates a list which has nodes having data A,B,C and each
        node pointing to the next one respectively.
        */
        delete q;
        delete p;
        delete r;
        return 0;
      }

      當我們編譯並執行此程式時,螢幕將顯示
      
      p:A
      P_next:B
      q:B
      q_next:C
      r:C
      
      p:B
      
      

      現在讓我們實現 Node 類,以便更好地理解此結構。

      我先從標頭檔案開始

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      // Node.h
      // Author: Ali Selcuk AKYUZ
      // Mail: selcuk@retinarobotics.com || e174043@metu.edu.tr
      // Electrical and Electronics Engineering Department
      // Middle East Technical University - ANKARA 
      // If any questions please send me an email
      
      #ifndef NODE_H
      #define NODE_H
      #include <iostream>
      
      using namespace std;
      
      template<class T>
      class Node
      {
          public:
              Node();
              Node(const T& item, Node<T>* ptrnext = NULL);
              T data;
              // access to the next node
              Node<T>* NextNode();
              // list modification methods
              void InsertAfter(Node<T>* p);
              Node<T>* DeleteAfter();
              Node<T> * GetNode(const T& item, Node<T>* nextptr = NULL);
          private:
      
              Node<T> * next;
      };
      
      #endif // NODE_H 


      這裡我們有一個預設建構函式,以及三個將在類實現的 cpp 部分稍後解釋的方法。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      // implementation of Node class
      // Author: Ali Selcuk AKYUZ
      // Mail: selcuk@retinarobotics.com || e174043@metu.edu.tr
      // Electrical and Electronics Engineering Department
      // Middle East Technical University - ANKARA 
      // If any questions please send me an email
      
      #include "Node.h"
      
      template<class T>
      Node<T>::Node()
      {
          // default constructor
          // this is to allow us to create an object without any initialization
      
      }
      
      
      //  This constructor is just to set next pointer of a node and the data contained.
      template<class T>
      Node<T>::Node(const T& item,Node<T>* ptrnext)
      {
          this->data = item;
          this->next = ptrnext;
      }
      
      template<class T>
      Node<T>*Node<T>::NextNode()
      {
          return this->next;
      }
      
      //  This methods inserts a node just after the node that the method belongs to 
      //  TO-DO: Consider a better implementation
      template<class T>
      void Node<T>::InsertAfter(Node<T> *p)
      {
          // not to lose the rest of the list, we ought to link the rest of the
          // list to the Node<T>* p first
          p->next = this->next;
      
          // now we should link the previous Node to Node<T> *p , i.e the Node that we are 
          //inserting after,
          this->next = p;
      }
      
      // Deletes the node from the list and returns the deleted node
      template<class T>
      Node<T>* Node<T>::DeleteAfter()
      {
          // store the next Node in a temporary Node
          Node<T>* tempNode = next;
          // check if there is a next node
          if(next != NULL)
              next = next->next;
      
          return tempNode;
      }
      template<class T>
      Node<T> * GetNode(const T& item, Node<T>* nextptr = NULL)
      {
          Node<T>* newnode; // Local ptr for new node
          newnode = new Node<T>(item,nextptr);
          if ( newnode == NULL)
          {
              cerr << "Memory allocation failed." << endl;
              exit(1);
          }
          return newnode;
      }


      在實現節點類之後,現在我們可以實現堆疊、佇列等。讓我透過使用連結串列邏輯來實現這些結構。

      堆疊、佇列屬性

      堆疊

      如果資料項根據插入列表的順序進行排序,這對應於堆疊。換句話說,先進後出 (FILO) 或後進先出 (LIFO)

      佇列

      佇列是一種資料結構,由一系列資料項以及指向列表“前端”和“後端”資料項的兩個指標組成。資料項只能在尾部插入,只能在頭部移除。即先進先出 (FIFO) 操作。

      我將在另一篇文章中實現這些類。

      盡情享受!!!!