實現基於單向鏈表的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> ©) { 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> ©) { 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 };