# include <iostream> using namespace std; typedef struct LNode { int data; //結點的數據域 struct LNode* next; //結點的指針域 }LNode, * LinkList; //LinkList爲指向結構體LNode的指針類型 //typedef: struct LNode == LNode; struct LNode* == LinkList //鏈表的初始化 LinkList InitList() { LNode* L = new LNode; //生成新節點做爲頭結點,用頭指針L指向頭結點 L->next = NULL; //頭結點的指針域置空 return L; } //建立鏈表:頭插法 void CreateList_H(LinkList& L, int n) { //逆位序輸入n個元素的值,創建帶頭結點的單鏈表L L = new LNode; L->next = NULL; //先創建一個帶頭結點的單鏈表 for (int i = 0; i < n; i++) { LNode* p = new LNode; //生成新結點 cin >> p->data; //輸入元素值賦值給新結點的數據域 p->next = L->next; L->next = p; } } //建立鏈表:尾插法 void CreateList_R(LinkList& L, int n) { //正位序輸入n個元素的值,創建帶頭節點的單鏈表L L = new LNode; L->next = NULL; //先創建一個帶頭結點的空鏈表 LNode* r = L; //尾指針初始時指向頭結點 for (int i = 0; i < n; i++) { LNode* p = new LNode; //生成新結點 cin >> p->data; //輸入元素值賦值給新結點的數據域 p->next = NULL; //p是最後一個結點 r->next = p; r = p;//r指向新的尾結點p } } //按序號查找結點的值 bool GetElem(LinkList L, int i, int& e) { //在帶頭結點的單鏈表L中根據序號i獲取元素的值,用e返回L中第i個數據元素 LNode* p = L->next; //p指向首元結點 int j = 1; //j爲計數器 while (p && j < i) { //順鏈域向後掃描,直到p指向第i個元素或者掃描完p爲空 p = p->next; //p指向下一個結點 j++; //計數器j相應加1 } if (!p || j > i) return false; //p爲空 或者 i值不合法(例如:i > n 或者 i<= 0) e = p->data; //e保存第i個結點的數據域 return true; } //按值查找鏈表結點 bool LocateElem(LinkList L, int e) { //在帶頭結點的單鏈表L中查找值爲e的元素 LNode* p = L->next; while (p && p->data != e) {//順鏈域向後掃描,直到p爲空或者p所指結點的數據域等於e p = p->next; //p指向下一個結點 } if (!p) return false; return true; } //單鏈表的插入 /* 和順序表同樣,若是表中有n個結點, 則插入操做中的合法位置有n + 1個 即1<= i <= n+1. 當i = n + 1時,新節點則插在鏈表尾部 */ bool InsertList(LinkList& L, int i, int e) { //在點頭結點的單鏈表L中第i個位置插入值爲e的新結點 LNode* p = L; //爲啥不能是LNode* p = L->next; int j = 1 int j = 0; while (p && j < i - 1) { //查找第i-1個結點,p指向該結點 p = p->next; j++; } if (!p || j > i - 1) return false; //i值不合法(例如:i > n + 1 或 i < 1) LNode* s = new LNode; s->data = e; s->next = p->next; p->next = s; return true; } //單鏈表的刪除 /* 刪除算法中的循環條件(p->next && j < i - 1)和插入算法中的循環條件 (p && j < i - 1)是有所區別的。由於插入操做中合法的插入位置有n+1個,而 刪除操做中刪除的合法位置只有n個,若是使用與插入操做相同的循環條件,則 會出現引入空指針的狀況,使刪除操做失敗。 插入時p指針最多指向第n個結點,此時判斷條件爲while(p && j < i - 1) 刪除時p指針最多指向第n-1個結點,此時判斷條件爲while(p->next && j < i - 1) */ bool DeleteList(LinkList& L, int i) { //在帶頭結點的單鏈表L中,刪除第i個位置 LNode* p = L, * q; int j = 0; while (p->next && j < i - 1) { //查找第i-1個結點,p指向該結點 p = p->next; j++; } if (!(p->next) || j > i - 1)return false; //當i>n+1 或者i < 1時,刪除位置不合理 q = p->next; //臨時保存被刪結點的地址以備釋放空間 p->next = q->next; //改變刪除結點前驅結點的指針域 delete q; //釋放被刪除結點的空間 return true; } //單鏈表的遍歷輸出 void ListPrint(LinkList L) { //順序輸出單鏈表 LNode* p = L->next; while (p) { cout << p->data << "\t"; p = p->next; } cout << endl; } int main() { int i, n, e, choose; LinkList L = InitList(); cout << "1. 初始化\n"; cout << "2. 建立單鏈表(頭插法)\n"; cout << "3. 建立單鏈表(尾插法)\n"; cout << "4. 取值\n"; cout << "5. 查找\n"; cout << "6. 插入\n"; cout << "7. 刪除\n"; cout << "8. 輸出\n"; cout << "0. 退出\n"; choose = -1; while (choose != 0) { cout << "請輸入數字進行操做: "; cin >> choose; switch (choose) { case 1: //初始化一個空的單鏈表 L = InitList(); if (L) { cout << "成功初始化一個空的單鏈表" << endl; }else{ cout << "初始化一個空的單鏈表失敗" << endl; } break; case 2:// 建立單鏈表(頭插法) cout << "請輸入想要建立鏈表元素個數:"; cin >> n; cout << "請依次輸入" << n << "個元素:"; CreateList_H(L, n); cout << "頭插法建立單鏈表輸出結果:"; ListPrint(L); break; case 3:// 建立單鏈表(尾插法) cout << "請輸入想要建立鏈表元素個數:"; cin >> n; cout << "請依次輸入" << n << "個元素:"; CreateList_R(L, n); cout << "尾插法建立單鏈表輸出結果:"; ListPrint(L); break; case 4: //取值 cout << "請輸入想查找的鏈表元素序號:"; cin >> i; GetElem(L, i, e); cout << "第" << i << "個鏈表元素的數據域是:" << e << endl; break; case 5: //查找 cout << "請輸入想查找的鏈表元素的數據域:"; cin >> e; if (LocateElem(L, e)) { cout << "查找成功" << endl; } else { cout << "查找失敗" << endl; } break; case 6: //插入 cout << "請輸入插入的位置和數據(用空格隔開):"; cin >> i >> e; if (InsertList(L, i, e)) { cout << "插入成功" << endl; } else { cout << "插入失敗" << endl; } break; case 7: //刪除 cout << "請輸入刪除的位置:"; cin >> i; if (DeleteList(L, i)) { cout << "刪除成功" << endl; } else { cout << "刪除失敗" << endl; } break; case 8: //遍歷輸出單鏈表 ListPrint(L); break; case 0: //退出 exit(-1); } } return 0; }
有序鏈表的合併ios
題目:將兩個有序(非遞減)單鏈表La和Lb合併爲一個新的有序(非遞減)單鏈表。 解題思路:鏈表合併不須要再建立空間,只須要進行穿針引線,把兩個單鏈表中的結點,按非遞減的順序串聯起來便可。 注意:單鏈表的頭指針不能夠移動
# include <iostream> using namespace std; typedef struct LNode { int data; //結點的數據域 struct LNode* next; //結點的指針域 }LNode, * LinkList; //LinkList爲指向結構體LNode的指針類型 //尾插法建立單鏈表 void CreateList_R(LinkList& L, int n) { L = new LNode; L->next = NULL; //建立一個空的頭結點 LNode* r = L; //尾指針 for (int i = 0; i < n; i++) { LNode* p = new LNode; cin >> p->data; r->next = p; r = p; } r->next = NULL;//將最後一個結點的指針域置空 } LinkList MergeList(LinkList& L1, LinkList& L2) { LNode* L = L1; //L是合併的新鏈表頭指針,L指向L1的頭結點 LNode* r = L; //尾指針永遠指向鏈表尾部 LNode* p = L1->next, * q = L2->next;//p指針指向L1的第一個元素,q指針指向L2的第一個元素 while (p && q) { //p和q同時不指向空 if (p->data <= q->data) {//把p指向的結點串起來 r->next = p; r = p; p = p->next;//p後移到下一結點 } else {//把q指向的結點串起來 r->next = q; r = q; q = q->next; } } //退出循環的條件:一、p爲空; 二、q爲空 if (!p) r->next = q;//p爲空 if (!q) r->next = p;//q爲空 //或者r->next = p ? p : q; delete L2; return L; } void ListPrint(LinkList L) { //順序輸出單鏈表 LNode* p = L->next; while (p) { cout << p->data << " "; p = p->next; } cout << endl; } int main() { LinkList L1, L2, L; int S1, S2; cin >> S1; CreateList_R(L1, S1); cin >> S2; CreateList_R(L2, S2); L = MergeList(L1, L2); ListPrint(L); return 0; }
快慢指針c++
題目:帶有頭結點的單鏈表L,設計一個儘量高效的算法,求L中的中間結點。若是有兩個中間結點,則返回第一個中間結點 提示:給定鏈表的結點數介於 1 和 100 之間。 解題思路:這樣的題型須要使用快慢指針來解決。一個快指針,一個慢指針,快指針走兩步滿指針走一步,當快指針指向結尾的時候,慢指針恰好指向中間結點
/* 題目:帶有頭結點的單鏈表L, 頭結點的數據域不存儲數據。設計一個儘量高效的算法, 求L中的中間結點。 若是有兩個中間結點, 則返回第一個中間結點. */ # include <iostream> using namespace std; typedef struct LNode { int data; struct LNode* next; }LNode, * LinkList; //尾插法創建單鏈表 void CreateList_R(LinkList& L, int n) { L = new LNode; L->next = NULL; LNode* r = L; //尾指針 for (int i = 0; i < n; i++) { LNode* p = new LNode; cin >> p->data; r->next = p; r = p; } r->next = NULL; //鏈表最後一個結點的指針域置空 } LNode* FindMiddle(LinkList L) { LNode* fast = L; LNode* slow = L; while (fast && fast->next) { fast = fast->next->next; //快指針一次走兩步 slow = slow->next; //慢指針一次走一步 } return slow; //慢指針所指的位置就是中間結點的位置 } void PrintList(LinkList L) { LNode* p = L->next; while (p) { cout << p->data << " "; p = p->next; } cout << endl; } int main() { LinkList L; LNode* middle; int n; cout << "輸入鏈表結點個數:"; cin >> n; cout << "依次輸入" << n << "個元素:" ; CreateList_R(L, n); cout << "打印鏈表中的全部元素:"; PrintList(L); middle = FindMiddle(L); cout << "鏈表中間結點元素爲:"; cout << middle->data << endl; system("pause"); return 0; }
題目: 1.在單鏈表中查到倒數第k個結點 2.用單鏈表保存m個整數,結點的結構爲(data,next),且|data|<=n(n爲正整數)。如今要求設計一個時間複雜度儘量高效的算法,對於鏈表中data的絕對值相等的結點,僅保留第一次出現的結點而闡述其絕對值相等的結點。