程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 單項鏈表的實現,項鏈表實現

單項鏈表的實現,項鏈表實現

編輯:C++入門知識

單項鏈表的實現,項鏈表實現


實現基於單向鏈表的list類。

struct node {

     int x;

     int y;

     node(int xx, int yy) {

         x = xx;

         y = yy;

        }

}

 1.構造函數時先設置一個head結點,其指向空。如下:

        

2.插入結點:

當position為0時,本來應該是這樣的: 

                                                                                                   

但是,這個函數在這裡插入結點時,如果count=0,則將圖中position位置看成NULL,那麼下面的插入方法仍然成立不受影響。所以這就是設置頭結點的優點是所在了,在position=0時插入結點就不需要通過條件判斷了(這種判斷很容易忘記漏寫,導致苦逼的debug),在這裡只要通過current找到插入的位置position前的結點,然後將新的結點插在current後面,新結點的next為current->next即可完成insert的工作。

 

3.remove結點:

 如圖所示的方法刪除position位置的結點,同樣是利用head來減少判斷步驟。

 

附代碼及注釋:

  1 #include <iostream>
  2 using namespace std;
  3 enum Error_code {
  4          success,
  5          underflow,
  6          overflow
  7 };
  8 template <class List_entry>
  9 struct Node {
 10          List_entry entry;
 11          Node<List_entry> *next;
 12 };
 13 template <class List_entry>
 14 class MyList {
 15 public:
 16          MyList() {
 17              head = new Node<List_entry>;//設置一個頭結點
 18              head->entry = 0;
 19              head->next = NULL;
 20              count = 0;//當前鏈表為空(頭部之後的結點才是我們存進去的,count指的是我們存進去的結點數)
 21              curPosition = -1;//頭部的位置為-1
 22              current = head;//當前位置指向鏈表的頭部
 23          }
 24          /*設置頭部的作用主要體現在insert(int position, const List_entry &entry),remove(...), retrieve(...),
 25          replay(...)這些函數裡面,詳見相關函數*/
 26          ~MyList() {
 27              current = NULL;
 28              curPosition = -1;
 29              Node<List_entry> *temp = head, *a;
 30              while (head != NULL) {
 31                  head = temp->next;
 32                  a = temp;
 33                  delete a;
 34                  temp = head;
 35              }
 36              count = 0;
 37          }
 38          // 拷貝構造函數和賦值運算符重載,注意深拷貝與淺拷貝的差異
 39          MyList(const MyList<List_entry> &copy) {
 40              head = new Node<List_entry>;//this start...
 41              head->entry = 0;
 42              head->next = NULL;
 43              count = 0;
 44              curPosition = -1;
 45              current = head;//this end...拷貝構造函數,相當於構造一個MyList()之後將copy這個鏈表的內容復制進去
 46              if (copy.count != 0) {//拷貝鏈表內容
 47                  count = copy.count;
 48                  Node<List_entry> *a, *b;
 49                  a = copy.head->next;
 50                  b = head;
 51                  for (int i = 0; i < copy.count; i++) {
 52                      b->next = new Node<List_entry>;
 53                      b = b->next;
 54                      b->entry = a->entry;
 55                      b->next = NULL;
 56                      a = a->next;
 57                  }
 58              }
 59          }
 60          //跟拷貝構造函數不一樣,這個函數實現的前提是已經MyList()例如MyList a,然後將copy復制到a
 61          void operator =(const MyList<List_entry> &copy) {
 62              if (!empty()) clear();//清空
 63              if (copy.count != 0) {//同上拷貝鏈表內容
 64                  count = copy.count;
 65                  Node<List_entry> *a, *b;
 66                  a = copy.head->next;
 67                  b = head;
 68                  for (int i = 0; i < copy.count; i++) {
 69                      b->next = new Node<List_entry>;
 70                      b = b->next;
 71                      b->entry = a->entry;
 72                      b->next = NULL;
 73                      a = a->next;
 74                  }
 75              }
 76          }
 77          // 清空list,清空時候保留頭結點,數據恢復到原始狀態
 78          void clear() {
 79              if (!empty()) {
 80                  Node<List_entry> *temp = head->next, *a;
 81                  while (temp != NULL) {
 82                      head->next = temp->next;
 83                      a = temp;
 84                      temp = head->next;
 85                      delete a;
 86                      count--;
 87                  }
 88                  current = head;
 89                  curPosition = -1;
 90              }
 91          }
 92          // 判斷list是否為空
 93          bool empty() const {
 94              if (count != 0) return false;
 95              return true;
 96          }
 97          // 判斷list是否已滿
 98          bool full() const {
 99              return false;
100          }
101          // 獲取list的元素數量
102          int size() const {
103              return count;
104          }
105          // 在第position個位置插入值為entry的元素,如果position為0則插入在head(head的position為-1)後面,依次類推
106          // 若position < 0 或者 position > count,則返回underflow
107          Error_code insert(int position, const List_entry &entry) {
108              if (position < 0 || position > count) return underflow;
109              Node<List_entry> *new_node, *pre, *follow;
110              //new一個新的結點
111              new_node = new Node<List_entry>;
112              new_node->entry = entry;
113              //setPosition的作用是設置當前的位置current指向position-1這個位置,在position-1後面插入new_node
114              //當position==0時,應該插在頭部後面的位置,pre指向頭部。若沒有head,則需要討論當position == 0時候的情況,容易漏判斷
115              setPosition(position - 1);
116              pre = current;
117              follow = current->next;
118              //新結點指向follow,pre前一個結點指向新結點new_node
119              new_node->next = follow;
120              pre->next = new_node;
121              count++;
122              return success;
123          }
124          // 刪除第position個位置的元素,並將該元素的值保存在entry中
125          // 若position < 0 或者 position >= count,則返回underflow
126          Error_code remove(int position, List_entry &entry) {
127              if (position < 0 || position >= count) return underflow;
128              Node<List_entry> *pre, *now, *follow;
129              //去掉position位置的結點,應該讓pre指向該位置的前一個,所以應該先找出position-1位置的結點
130              setPosition(position - 1);
131              pre = current;
132              now = current->next;
133              entry = now->entry;
134              follow = now->next;
135              pre->next = follow;
136              delete now;//刪掉position的結點
137              count--;
138              return success;
139          }
140          // 獲取第position個位置的元素,保存在entry中
141          // 若position < 0 或者 position >= count,則返回underflow
142          Error_code retrieve(int position, List_entry &entry) const {
143              if (position < 0 || position >= count) return underflow;
144              setPosition(position);
145              entry = current->entry;
146              return success;
147          }
148          // 將第position個位置的元素替換為entry
149          // 若position < 0 或者 position >= count,則返回underflow
150          Error_code replace(int position, const List_entry &entry) {
151              if (position < 0 || position >= count) return underflow;
152              setPosition(position);
153              current->entry = entry;
154              return success;
155          }
156          // 用visit函數遍歷list內所有的元素
157          void traverse(void (*visit)(List_entry &)) {
158              Node<List_entry> *a = head->next;
159              for (int i = 0; i < count; i++) {
160                  (*visit)(a->entry);
161                  a = a->next;
162              }
163          }
164 protected:
165          int count;                                                                          // 記錄list內元素數量
166          Node<List_entry> *head;                                         // 鏈表頭指針
167          mutable int curPosition;                                   // current指針的位置編號
168          mutable Node<List_entry> *current;                 // current指針
169         // 設置current指針的位置,指向第position個位置
170         void setPosition(int position) const {
171              if (position < curPosition) {
172                  curPosition = -1;
173                  current = head;
174              }
175              for (; curPosition < position; curPosition++) {
176                  current = current->next;
177              }
178          }
179 };

 

  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved