1. 單鏈表的原理
鏈表是線性表的鏈式存儲方式,邏輯上相鄰的數據在計算機內的存儲位置不必須相鄰,那么怎么表示邏輯上的相鄰關系呢?可以給每個元素附加一個指針域,指向下一個元素的存儲位置。如圖所示:

從圖中可以看出,每個結點包含兩個域:數據域和指針域,指針域存儲下一個結點的地址,因此指針指向的類型也是結點類型鏈表的核心要素:Ø 每個節點由數據域和指針域組成 Ø 指針域指向下一個節點的內存地址。
1.1 結構體定義
1 Typedef struct LinkNode 2 { 3 ElemType data; //節點中存放數據的類型 4 struct LinkNode* next; //節點中存放下一節點的指針 5 }LinkList, LinkNode;
2. 單鏈表初始化
鏈表的節點均單向指向下一個節點,形成一條單向訪問的數據鏈


1 //單鏈表的初始化 2 typedef struct _LinkNode 3 { 4 int data; //結點的數據域 5 struct _LinkNode* next; //結點的指針域 6 }LinkNode, LinkList; //鏈表節點、鏈表 7 8 bool InitList(LinkList*& L) //構造一個空的單鏈表 L 9 { 10 L = new LinkNode; //生成新結點作為頭結點,用頭指針 L 指向頭結點 11 if(!L)return false; //生成結點失敗 12 L->next=NULL; //頭結點的指針域置空 13 return true; 14 }
3. 單鏈表增加元素 - 單鏈表前插法
插入節點的要素就是要找到要插入位置的前一個節點,將這個節點的Next賦值給新節點,然后將新節點的地址賦值給前一個節點的Next便可,任意位置插入和前插法均是如此。

1 //前插法 2 bool ListInsert_front(LinkList * &L, LinkNode * node) //參數1 鏈表指針 參數2 要插入的節點元素 3 { 4 if (!L || !node) return false; //如果列表或節點為空返回 false 5 node->next = L->next; //將頭節點指向節點1的地址 賦值給要插入節點的指針域,使要插入的節點先與后部相連 6 L->next = node; //將插入節點的地址賦值給頭結點的指針域,使要插入節點與頭結點相連 7 8 return true; 9 }
4. 單鏈表增加元素 - 單鏈表尾插法

1 //尾插法 2 bool ListInsert_back(LinkList*& L, LinkNode* node) 3 { 4 LinkNode* last = NULL; //創建空指針, 5 if (!L || !node) return false; //如果列表或節點為空返回 false 6 7 last = L; 8 while (last->next) last = last->next; //使用 last 找到最后一個節點 9 10 node->next = NULL; //要插入節點由於在尾部,指針域置為 NULL 11 last->next = node; //將要插入節點的地址賦值給之前的尾部節點的指針域,將要插入節點放置到尾部 12 return true; 13 }
5. 單鏈表增加元素 - 單鏈表任意位置插入
插入節點的要素就是要找到要插入位置的前一個節點,將這個節點的Next賦值給新節點,然后將新節點的地址賦值給前一個節點的Next便可,任意位置插入和前插法均是如此。
1 //任意位置插法 2 bool LinkInsert(LinkList*& L, int i, int& e) //參數1 鏈表指針 參數2 要插入的位置 參數3 要插入的節點元素 3 { 4 LinkList* p = L, * s; 5 int j = 0; 6 7 while (p && j < i - 1) //查找第i-1個結點(要插入位置的前一個節點),p指向該結點 8 { 9 p = p->next; 10 j++; 11 } 12 13 if (!p || j > i - 1) //驗證數據有效性 14 { 15 return false; 16 } 17 18 s = new LinkNode; //生成新結點 19 s->data = e; //將新結點的數據域置為 e 20 s->next = p->next; //將新結點的指針域指向結點 ai,使要插入的節點先與后部相連 21 p->next = s; //將結點 p 的指針域指向要插入的結點,使要插入節點與頭結點相連 22 23 return true; 24 }

6. 單鏈表遍歷
1 void LinkPrint(LinkList*& L) //單鏈表的輸出 2 { 3 LinkNode* p; 4 p = L->next; 5 6 while (p) //一直循環打印,直到 p->next == NULL 退出循環 7 { 8 cout << p->data << "\t"; 9 p = p->next; 10 } 11 cout << endl; 12 }
7. 單鏈表獲取元素
1 //單鏈表的取值 2 //在帶頭結點的單鏈表 L 中查找第 i 個元素,用 e 記錄 L 中第 i 個數據元素的值 3 bool Link_GetElem(LinkList*& L, int i, int& e) //參數1 要查找的鏈表指針 參數2 要查找的元素位置 參數3 要記錄存放元素的值 4 { 5 int j; 6 LinkList* p; 7 p = L->next; //p指向第一個結點 8 j=1; //j為計數器 9 10 while (j < i && p) //順鏈域向后掃描,直到p指向第i個元素或p為空 11 { 12 p = p->next; //p指向下一個結點 13 j++; //計數器j相應加1 14 } 15 16 if (!p || j > i) 17 { 18 return false; //i 值不合法 i>n 或 i<=0 19 } 20 21 e = p->data; //取第i個結點的數據域 22 return true; 23 }
8. 單鏈表查找元素
1 //按值查找 2 bool Link_FindElem(LinkList* L, int e) //在帶頭結點的單鏈表L中查找值為e的元素 3 { 4 LinkList* p; 5 p = L->next; 6 while (p && p->data != e) //順鏈域向后掃描,直到p為空或p所指結點的數據域等於e 7 { 8 p = p->next; //p指向下一個結點 9 } 10 if (!p)return false; //查找失敗p為NULL 11 12 return true; 13 }
9. 單鏈表刪除
1 //單鏈表的節點刪除 2 bool LinkDelete(LinkList*& L, int i) //在帶頭結點的單鏈表L中,刪除第i個位置 3 { 4 LinkList* p = L, * q; 5 int j = 0; 6 7 while (p->next && j < i - 1) //查找第i-1個結點,p指向該結點 8 { 9 p = p->next; 10 j++; 11 } 12 13 if (!(p->next) || j > i - 1) return false; //當 i > n 或 i < 1 時,刪除位置不合理 14 15 q = p->next; //臨時保存被刪結點的地址以備釋放空間,(刪除的是 P 的下一個節點) 16 p->next = q->next; //將要刪除的節點的下一個節點地址覆蓋要刪除節點的地址(就是把要刪除節點的下一個節點地址,賦值給被刪除節點的前一個節點的next) 17 delete q; //釋放被刪除結點的空間 18 19 return true; 20 }
10. 單鏈表銷毀
1 //單鏈表的銷毀 2 void LinkDestroy(LinkList*& L) 3 { 4 //定義臨時節點p指向頭節點 5 LinkList* p = L; 6 cout << "銷毀鏈表!" << endl; 7 8 while (p) //遍歷整個鏈表,逐個釋放直到 L->next == NULL 9 { 10 L = L->next; //L指向下一個節點 11 cout << "刪除元素: " << p->data << endl; 12 delete p; //刪除當前節點 13 p = L; //p 移向下一個節點 14 } 15 }
11. 完整實現
1 #include<iostream> 2 #include<string> 3 #include<stdlib.h> 4 5 using namespace std; 6 7 typedef struct _LinkNode 8 { 9 int data; //結點的數據域 10 struct _LinkNode* next; //結點的指針域 11 }LinkNode, LinkList; //LinkList 為指向結構體LNode 的指針類型 12 13 bool InitList(LinkList*& L) 14 { 15 L = new LinkNode; 16 if (!L) return false; //生成節點失敗 17 L->next = NULL; 18 L->data = -1; 19 return true; 8979438401111 20 } 21 22 //前插法 23 bool ListInsert_front(LinkList*& L, LinkNode* node) 24 { 25 if (!L || !node) return false; 26 node->next = L->next; 27 L->next = node; 28 return true; 29 } 30 31 //尾插法 32 bool ListInsert_back(LinkList*& L, LinkNode* node) 33 { 34 LinkNode* last = NULL; 35 if (!L || !node) return false; 36 last = L; 37 while (last->next) last = last->next; 38 node->next = NULL; 39 last->next = node; 40 return true; 41 } 42 43 //指定位置插入 44 bool LinkInsert(LinkList*& L, int i, int& e) 45 { 46 if (!L) return false; 47 int j = 0; 48 LinkList* p, * s; 49 p = L; 50 while (p && j < i - 1) //查找位置為i-1 的結點,p 指向該結點 51 { 52 p = p->next; 53 j++; 54 } 55 if (!p || j > i - 1) 56 { 57 return false; 58 } 59 s = new LinkNode; //生成新節點 60 s->data = e; 61 s->next = p->next; 62 p->next = s; 63 return true; 64 } 65 66 //遍歷 67 void LinkPrint(LinkList*& L) 68 { 69 LinkNode* p = NULL; 70 if (!L) { 71 cout << "鏈表為空." << endl; 72 return; 73 } 74 p = L->next; 75 while (p) { 76 cout << p->data << "\t"; 77 p = p->next; 78 } 79 cout << endl; 80 } 81 82 //單鏈表的取值 83 bool Link_GetElem(LinkList*& L, int i, int& e) 84 { 85 //在帶頭結點的單鏈表L 中查找第i 個元素 86 //用e 記錄L 中第i 個數據元素的值 87 int index; 88 LinkList* p; 89 if (!L || !L->next) return false; 90 p = L->next; 91 index = 1; 92 while (p && index < i) //順鏈表向后掃描,直到p 指向第i 個元素或p 為空 93 { 94 p = p->next; //p 指向下一個結點 95 index++; //計數器index 相應加1 96 } 97 if (!p || index > i) { 98 return false; //i 值不合法,i>n 或i<=0 99 } 100 e = p->data; 101 return true; 102 } 103 104 //按值查找 105 bool Link_FindElem(LinkList* L, int e, int& index) 106 { 107 //在帶頭結點的單鏈表L 中查找值為e 的元素 108 LinkList* p; 109 p = L->next; 110 index = 1; 111 if (!L || !L->next) 112 { 113 index = 0; 114 return false; 115 } 116 while (p && p->data != e) 117 { 118 p = p->next; 119 index++; 120 } 121 if (!p) 122 { 123 index = 0; 124 return false; //查無此值 125 } 126 return true; 127 } 128 129 //單鏈表的刪除 130 bool LinkDelete(LinkList*& L, int i) 131 { 132 LinkList* p, * q; 133 int index = 0; 134 p = L; 135 if (!L || !L->next) 136 { 137 return false; 138 } 139 140 while ((p->next) && (index < i - 1)) 141 { 142 p = p->next; 143 index++; 144 } 145 146 if (!p->next || (index > i - 1)) //當 i>n 或 i<1 時,刪89除7位94置38不40合1理111 147 { 148 return false; 149 } 150 q = p->next; //臨時保存被刪結點的地址以備釋放空間 151 p->next = q->next; //改變刪除結點前驅結點的指針域 152 delete q; //釋放被刪除結點的空間 153 return true; 154 } 155 156 //單鏈表的銷毀 157 void LinkDestroy(LinkList*& L) 158 { 159 //定義臨時節點p 指向頭節點 160 LinkList* p = L; 161 cout << "銷毀鏈表!" << endl; 162 while (p) { 163 L = L->next; //L 指向下一個節點 164 cout << "刪除元素: " << p->data << endl; 165 delete p; //刪除當前節點 166 p = L; //p 移向下一個節點 167 } 168 } 169 170 int main(void) 171 { 172 LinkList* L = NULL; 173 LinkNode* s = NULL; 174 175 //1. 初始化一個空的鏈表 176 InitList(L); 177 178 //2. 使用前插法插入數據 179 /*int n; 180 cout<<"前插法創建單鏈表"<<endl; 181 std::cout<<"請輸入元素個數n:"; 182 cin>>n; 183 cout<<"\n 請依次輸入n 個元素:" <<endl; 184 while(n>0){ 185 s = new LinkNode; //生成新節點s 186 cin>>s->data; 187 ListInsert_front(L, s); 188 n--; 189 }*/ 190 191 //3. 使用尾插法插入數據 192 /*int n; 193 cout<<"尾插法創建單鏈表"<<endl; 194 std::cout<<"請輸入元素個數n:"; 195 cin>>n; 196 cout<<"\n 請依次輸入n 個元素:" <<endl; 197 while(n>0){ 198 s = new LinkNode; //生成新節點s 199 cin>>s->data; 200 ListInsert_back(L, s); 201 n--; 202 }*/ 203 204 //4. 單鏈表的輸出 205 /* 206 LinkPrint(L); 207 */ 208 209 //5. 任意位置插入元素 210 for (int j = 0; j < 3; j++) { 211 int i, x; 212 cout << "請輸入插入的位置和元素(用空格隔開):"; 213 cin >> i; 214 cin >> x; 215 if (LinkInsert(L, i, x)) { 216 cout << "插入成功.\n\n"; 217 } 218 else { 219 cout << "插入失敗!\n\n"; 220 } 221 LinkPrint(L); 222 } 223 224 //6. 單鏈表根據位置獲取元素 225 int element = 0; 226 if (Link_GetElem(L, 2, element)) { 227 cout << "獲取第二個元素成功, 值:" << element << endl; 228 } 229 else { 230 cout << "獲取第二個元素失敗!" << endl; 231 } 232 233 //7. 單鏈表根據值查詢元素所在的位置 234 int index = 0; 235 if (Link_FindElem(L, 10, index)) { 236 cout << "查找元素10 存在,所在位置: " << index << endl; 237 } 238 else { 239 cout << "不存在元素10." << endl; 240 } 241 242 //8. 單鏈表刪除元素 243 if (LinkDelete(L, 2)) { 244 cout << "刪除第2 個元素成功!" << endl; 245 LinkPrint(L); 246 } 247 else { 248 cout << "刪除第2 個元素失敗!" << endl; 249 } 250 251 //9. 銷毀單鏈表 252 LinkDestroy(L); 253 system("pause"); 254 return 0; 255 }
======================================================================================================================
