存放遊標和實際數據 數據的第1個元素和末尾元素存放元數據 **第1個元素** 遊標:存放(指向)備用下標,供下次使用,初始化爲1 數據:鏈表tail標識,(尾節點下標) **末尾元素:** 遊標:存放鏈表第1個有效節點下標, head標識,初始化爲1(根據len特殊處理) 數據:鏈表當前有效節點個數(長度len)
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <unistd.h> #define MAXSIZE 10 typedef struct Node{ int data; int cur; } NODE, LINKLIST[MAXSIZE]; void init(LINKLIST); bool is_full(LINKLIST); bool is_empty(LINKLIST); // 遍歷全部有效元素 void traverse(LINKLIST); // 遍歷全部元素,便於學習 void traverse_all(LINKLIST); // 追加節點(入棧) bool append(LINKLIST, int); // 獲取指定位置上一個節點的下標,注意先檢查再調用 int get_pre(LINKLIST, int); // 刪除指定節點,只返回成功失敗,不返回刪除成功的元素值 bool delete(LINKLIST, int); // 容許先後插入 bool insert(LINKLIST, int, int); /* * 清空鏈表, 如沒特殊要求, 也可用init函數代替 * 這裏調用delete函數,並從鏈表尾向前刪除節點(只清空不改變head指向) */ bool clear(LINKLIST); // 獲取指定節點, 假設數據範圍爲正整數,錯誤咱們返回-1 int get(LINKLIST, int); // 獲取並刪除尾節點(出棧), 假設數據範圍取正整數,錯誤咱們返回-1 int pop(LINKLIST); int pop(LINKLIST L) { if (is_empty(L)) { printf("pop error! linklist is empty.\n"); return -1; } int len = L[MAXSIZE-1].data; int val = get(L, len); delete(L, len); printf("pop success! val: %d\n", val); return val; } int get(LINKLIST L, int pos) { int len = L[MAXSIZE-1].data; if (pos < 1 || pos > len) { printf("get error! pos(%d) out of range.\n", pos); return -1; } if (pos == 1) { int head = L[MAXSIZE-1].cur; int val = L[head].data; printf("get success! val:%d\n", val); return val; } int pre = get_pre(L, pos); int pos_index = L[pre].cur; int val = L[pos_index].data; printf("get success! val:%d\n", val); return val; } bool clear(LINKLIST L) { if (is_empty(L)) { printf("鏈表爲空,無需clear操做.\n"); return true; } int len = L[MAXSIZE-1].data; for (int i=len; i > 0; i--) { if (! delete(L, i)) return false; } return true; } bool insert(LINKLIST L, int pos, int e) { int len = L[MAXSIZE-1].data; int head = L[MAXSIZE-1].cur; int tail = L[0].data; int now_index = L[0].cur; int next_index = L[now_index].cur; if (is_full(L)) { printf("插入失敗,鏈表已滿!\n"); return false; } if (pos < 1 || pos > len + 1) { printf("插入失敗,無效的插入位置: %d\n", pos); return false; } int pre = get_pre(L, pos); printf("嘗試插入位置 %d 值 %d", pos, e); // 插入空鏈表的第1個節點(條件成立時必定是pos=1) if (is_empty(L)) { printf(", (節點類型: 空鏈表第1個節點)"); NODE New = {e, 0}; L[now_index] = New; L[0].cur = next_index; L[0].data = now_index; ++L[MAXSIZE-1].data; L[MAXSIZE-1].cur = now_index; } // 插入新頭節點 else if (pos == 1) { printf(", (節點類型: 新頭節點)"); NODE New = {e, head}; L[now_index] = New; // head 指向新頭節點 L[MAXSIZE-1].cur = now_index; // 備用節點指向 L[0].cur = next_index; ++L[MAXSIZE-1].data; } // 插入新尾節點 else if (pos == len + 1){ printf(", (節點類型: 新尾節點)"); NODE New = {e, 0}; L[now_index] = New; // 上一個節點(前尾節點)由原來的0指向新的tail節點 L[pre].cur = now_index; L[0].cur = next_index; // 更新tail標識 L[0].data = now_index; ++L[MAXSIZE-1].data; } //插入中間節點 else { printf(", (節點類型: 中間節點)"); int this_next = L[pre].cur; // 鏈接後繼節點 NODE New = {e, this_next}; L[now_index] = New; // 鏈接前軀節點 L[pre].cur = now_index; L[0].cur = next_index; ++L[MAXSIZE-1].data; } putchar('\n'); return true; } bool delete(LINKLIST L, int pos) { /*刪除任意節點共用操做: * len減1 * 回收空間 *刪除不一樣類型節點須要作的額外操做: * pos == 1 的狀況:頭節點非尾節點,或頭節點同時爲尾節點 * 無需再查找刪除位置的前軀節點下標 * 更新鏈表head, tail標識 * pos > 1的狀況:尾節點, 或中間節點 * 刪除尾節點:pos == len * 查找前軀節點下標 * 前軀節點的遊標改成0 * 更新鏈表tail標識爲前軀節點 * 刪除中間節點: * 查找前軀節點下標 * 鏈接前軀節點及後繼節點 * */ printf("嘗試刪除位置: %d, ", pos); if (is_empty(L)) { printf("刪除失敗, 鏈表爲空!\n"); return false; } int head = L[MAXSIZE-1].cur; int tail = L[0].data; if (pos < 1 || pos > MAXSIZE-2) { printf("刪除失敗, 位置超出範圍\n"); return false; } else if (pos == 1) { int new_head = L[head].cur; // 被刪除節點數據置0 L[head].data = 0; // 判斷頭節點是否同時爲尾節點 if (new_head == 0) { printf("(節點類型:頭節點 + 尾節點)"); // tail指向0(head不變,下次追加元素從這個開始追加) L[0].data = 0; } else { printf("(節點類型:頭節點)"); L[MAXSIZE-1].cur = new_head; } // 回收空間 L[head].cur = L[0].cur; L[0].cur = head; } else { int pre = get_pre(L, pos); // 刪除的位置等於長度則爲尾節點 if (pos == L[MAXSIZE-1].data) { // 被刪除節點數據置0 L[tail].data = 0; printf("(節點類型:尾節點)"); // 更新tail指向 L[0].data = pre; // 上一個節點變爲尾節點,更新遊標 L[pre].cur = 0; // 回收空間 L[tail].cur = L[0].cur; L[0].cur = tail; } else { printf("(節點類型:中間節點)"); // 鏈接前軀和後繼 int now_index = L[pre].cur; L[pre].cur = L[now_index].cur; // 被刪除節點數據置0 L[now_index].data = 0; // 回收空間 L[now_index].cur = L[0].cur; L[0].cur = now_index; } } --L[MAXSIZE-1].data; printf(", 刪除成功!\n"); return true; } // 函數不作複雜檢查,沒法找到時返回-1 int get_pre(LINKLIST L, int pos) { if (pos == 1) return 0; int p = L[MAXSIZE-1].cur; int i = 1; while (L[p].cur && i < pos-1) { p = L[p].cur; ++i; } return p; } bool append(LINKLIST L, int e) { printf("追加元素:%d\n", e); if (is_full(L)) { printf("追加失敗,鏈表已滿!\n"); return false; } NODE New = {e, 0}; //追加的尾元素固定指向0 int tail_index = L[0].data; //獲取鏈表尾元素的下標 int now_index = L[0].cur; //本次追加元素使用的下標 int next_index = L[now_index].cur; //保存備用下標的下一個下標做爲新備用下標 L[now_index] = New; ++L[MAXSIZE-1].data; //len(當前有效元素)加1 L[0].data = now_index; //更新鏈表tail標識 L[0].cur = next_index; //更新鏈表備用下標 // 非init後首次插入,須要tail元素鏈接新元素操做 if (tail_index != 0) L[tail_index].cur = now_index; return true; } bool is_empty(LINKLIST L) { if (L[MAXSIZE-1].data == 0) return true; return false; } bool is_full(LINKLIST L) { if (L[MAXSIZE-1].data == MAXSIZE-2) return true; return false; } void traverse(LINKLIST L) { if (is_empty(L)) { printf("鏈表爲空!\n"); return; } printf("鏈表元素:"); // 保存鏈表的頭元素下標(並不老是1) int head = L[MAXSIZE-1].cur; // 當head == 0 表明有效節點遍歷結束 while (head != 0) { printf("%d ", L[head].data); head = L[head].cur; } putchar('\n'); } void traverse_all(LINKLIST L) { printf("--------------current linklist state-----------------\n"); printf("%10s", "Cursor: "); for (int i=0; i<MAXSIZE;i++) { printf("%4d ", L[i].cur); } putchar('\n'); printf("%10s", "Data: "); for (int i=0; i<MAXSIZE;i++) { printf("%4d ", L[i].data); } putchar('\n'); printf("%10s", "index: "); for (int i=0; i<MAXSIZE;i++) { printf("%4d ", i); } putchar('\n'); } void init(LINKLIST L) { for (int i=0; i<MAXSIZE-1; i++) { L[i].cur = i + 1; L[i].data = 0; } /* * 數組的尾元素的遊標初始化指向第1個有數據的元素下標 * 雖然此時1並非是有效元素,可是append追加元素不用再加判斷爲空修改head變量了 */ L[MAXSIZE-1].cur = 1; //head L[MAXSIZE-1].data = 0; //len } int main(void) { LINKLIST L; init(L); // test append traverse(L); traverse_all(L); append(L, 11); traverse_all(L); append(L, 12); traverse_all(L); append(L, 13); append(L, 14); append(L, 15); append(L, 16); append(L, 17); append(L, 18); traverse_all(L); append(L, 19); traverse_all(L); traverse(L); // test delete delete(L, 9); delete(L, 0); delete(L, 1); traverse_all(L); delete(L, 7); traverse_all(L); delete(L, 4); traverse_all(L); delete(L, 2); traverse_all(L); delete(L, 2); traverse_all(L); delete(L, 3); traverse_all(L); delete(L, 1); traverse_all(L); delete(L, 1); traverse_all(L); delete(L, 1); traverse(L); // test append append(L, 21); traverse_all(L); append(L, 22); traverse_all(L); append(L, 23); append(L, 24); append(L, 25); append(L, 26); append(L, 27); append(L, 28); traverse_all(L); append(L, 29); traverse_all(L); traverse(L); // test clear clear(L); traverse_all(L); traverse(L); clear(L); // test insert insert(L, 0, 100); insert(L, 2, 101); insert(L, 1, 32); traverse_all(L); traverse(L); insert(L, 1, 31); traverse_all(L); traverse(L); insert(L, 3, 33); traverse_all(L); traverse(L); insert(L, 4, 34); traverse_all(L); traverse(L); insert(L, 5, 35); traverse_all(L); traverse(L); insert(L, 5, 355); traverse_all(L); traverse(L); insert(L, 4, 344); traverse_all(L); traverse(L); insert(L, 3, 333); traverse_all(L); traverse(L); insert(L, 2, 322); traverse_all(L); traverse(L); // test pop get(L, 9); get(L, 0); get(L, 8); get(L, 1); // test pop pop(L); traverse_all(L); traverse(L); pop(L); traverse_all(L); traverse(L); pop(L); traverse_all(L); traverse(L); pop(L); traverse_all(L); traverse(L); pop(L); pop(L); traverse_all(L); traverse(L); pop(L); pop(L); pop(L); traverse_all(L); traverse(L); return 0; }
output編程
鏈表爲空! --------------current linklist state----------------- Cursor: 1 2 3 4 5 6 7 8 9 1 Data: 0 0 0 0 0 0 0 0 0 0 index: 0 1 2 3 4 5 6 7 8 9 追加元素:11 --------------current linklist state----------------- Cursor: 2 0 3 4 5 6 7 8 9 1 Data: 1 11 0 0 0 0 0 0 0 1 index: 0 1 2 3 4 5 6 7 8 9 追加元素:12 --------------current linklist state----------------- Cursor: 3 2 0 4 5 6 7 8 9 1 Data: 2 11 12 0 0 0 0 0 0 2 index: 0 1 2 3 4 5 6 7 8 9 追加元素:13 追加元素:14 追加元素:15 追加元素:16 追加元素:17 追加元素:18 --------------current linklist state----------------- Cursor: 9 2 3 4 5 6 7 8 0 1 Data: 8 11 12 13 14 15 16 17 18 8 index: 0 1 2 3 4 5 6 7 8 9 追加元素:19 追加失敗,鏈表已滿! --------------current linklist state----------------- Cursor: 9 2 3 4 5 6 7 8 0 1 Data: 8 11 12 13 14 15 16 17 18 8 index: 0 1 2 3 4 5 6 7 8 9 鏈表元素:11 12 13 14 15 16 17 18 嘗試刪除位置: 9, 刪除失敗, 位置超出範圍 嘗試刪除位置: 0, 刪除失敗, 位置超出範圍 嘗試刪除位置: 1, (節點類型:頭節點), 刪除成功! --------------current linklist state----------------- Cursor: 1 9 3 4 5 6 7 8 0 2 Data: 8 0 12 13 14 15 16 17 18 7 index: 0 1 2 3 4 5 6 7 8 9 嘗試刪除位置: 7, (節點類型:尾節點), 刪除成功! --------------current linklist state----------------- Cursor: 8 9 3 4 5 6 7 0 1 2 Data: 7 0 12 13 14 15 16 17 0 6 index: 0 1 2 3 4 5 6 7 8 9 嘗試刪除位置: 4, (節點類型:中間節點), 刪除成功! --------------current linklist state----------------- Cursor: 5 9 3 4 6 8 7 0 1 2 Data: 7 0 12 13 14 0 16 17 0 5 index: 0 1 2 3 4 5 6 7 8 9 嘗試刪除位置: 2, (節點類型:中間節點), 刪除成功! --------------current linklist state----------------- Cursor: 3 9 4 5 6 8 7 0 1 2 Data: 7 0 12 0 14 0 16 17 0 4 index: 0 1 2 3 4 5 6 7 8 9 嘗試刪除位置: 2, (節點類型:中間節點), 刪除成功! --------------current linklist state----------------- Cursor: 4 9 6 5 3 8 7 0 1 2 Data: 7 0 12 0 0 0 16 17 0 3 index: 0 1 2 3 4 5 6 7 8 9 嘗試刪除位置: 3, (節點類型:尾節點), 刪除成功! --------------current linklist state----------------- Cursor: 7 9 6 5 3 8 0 4 1 2 Data: 6 0 12 0 0 0 16 0 0 2 index: 0 1 2 3 4 5 6 7 8 9 嘗試刪除位置: 1, (節點類型:頭節點), 刪除成功! --------------current linklist state----------------- Cursor: 2 9 7 5 3 8 0 4 1 6 Data: 6 0 0 0 0 0 16 0 0 1 index: 0 1 2 3 4 5 6 7 8 9 嘗試刪除位置: 1, (節點類型:頭節點 + 尾節點), 刪除成功! --------------current linklist state----------------- Cursor: 6 9 7 5 3 8 2 4 1 6 Data: 0 0 0 0 0 0 0 0 0 0 index: 0 1 2 3 4 5 6 7 8 9 嘗試刪除位置: 1, 刪除失敗, 鏈表爲空! 鏈表爲空! 追加元素:21 --------------current linklist state----------------- Cursor: 2 9 7 5 3 8 0 4 1 6 Data: 6 0 0 0 0 0 21 0 0 1 index: 0 1 2 3 4 5 6 7 8 9 追加元素:22 --------------current linklist state----------------- Cursor: 7 9 0 5 3 8 2 4 1 6 Data: 2 0 22 0 0 0 21 0 0 2 index: 0 1 2 3 4 5 6 7 8 9 追加元素:23 追加元素:24 追加元素:25 追加元素:26 追加元素:27 追加元素:28 --------------current linklist state----------------- Cursor: 9 0 7 5 3 8 2 4 1 6 Data: 1 28 22 25 24 26 21 23 27 8 index: 0 1 2 3 4 5 6 7 8 9 追加元素:29 追加失敗,鏈表已滿! --------------current linklist state----------------- Cursor: 9 0 7 5 3 8 2 4 1 6 Data: 1 28 22 25 24 26 21 23 27 8 index: 0 1 2 3 4 5 6 7 8 9 鏈表元素:21 22 23 24 25 26 27 28 嘗試刪除位置: 8, (節點類型:尾節點), 刪除成功! 嘗試刪除位置: 7, (節點類型:尾節點), 刪除成功! 嘗試刪除位置: 6, (節點類型:尾節點), 刪除成功! 嘗試刪除位置: 5, (節點類型:尾節點), 刪除成功! 嘗試刪除位置: 4, (節點類型:尾節點), 刪除成功! 嘗試刪除位置: 3, (節點類型:尾節點), 刪除成功! 嘗試刪除位置: 2, (節點類型:尾節點), 刪除成功! 嘗試刪除位置: 1, (節點類型:頭節點 + 尾節點), 刪除成功! --------------current linklist state----------------- Cursor: 6 9 7 5 3 8 2 4 1 6 Data: 0 0 0 0 0 0 0 0 0 0 index: 0 1 2 3 4 5 6 7 8 9 鏈表爲空! 鏈表爲空,無需clear操做. 插入失敗,無效的插入位置: 0 插入失敗,無效的插入位置: 2 嘗試插入位置 1 值 32, (節點類型: 空鏈表第1個節點) --------------current linklist state----------------- Cursor: 2 9 7 5 3 8 0 4 1 6 Data: 6 0 0 0 0 0 32 0 0 1 index: 0 1 2 3 4 5 6 7 8 9 鏈表元素:32 嘗試插入位置 1 值 31, (節點類型: 新頭節點) --------------current linklist state----------------- Cursor: 7 9 6 5 3 8 0 4 1 2 Data: 6 0 31 0 0 0 32 0 0 2 index: 0 1 2 3 4 5 6 7 8 9 鏈表元素:31 32 嘗試插入位置 3 值 33, (節點類型: 新尾節點) --------------current linklist state----------------- Cursor: 4 9 6 5 3 8 7 0 1 2 Data: 7 0 31 0 0 0 32 33 0 3 index: 0 1 2 3 4 5 6 7 8 9 鏈表元素:31 32 33 嘗試插入位置 4 值 34, (節點類型: 新尾節點) --------------current linklist state----------------- Cursor: 3 9 6 5 0 8 7 4 1 2 Data: 4 0 31 0 34 0 32 33 0 4 index: 0 1 2 3 4 5 6 7 8 9 鏈表元素:31 32 33 34 嘗試插入位置 5 值 35, (節點類型: 新尾節點) --------------current linklist state----------------- Cursor: 5 9 6 0 3 8 7 4 1 2 Data: 3 0 31 35 34 0 32 33 0 5 index: 0 1 2 3 4 5 6 7 8 9 鏈表元素:31 32 33 34 35 嘗試插入位置 5 值 355, (節點類型: 中間節點) --------------current linklist state----------------- Cursor: 8 9 6 0 5 3 7 4 1 2 Data: 3 0 31 35 34 355 32 33 0 6 index: 0 1 2 3 4 5 6 7 8 9 鏈表元素:31 32 33 34 355 35 嘗試插入位置 4 值 344, (節點類型: 中間節點) --------------current linklist state----------------- Cursor: 1 9 6 0 5 3 7 8 4 2 Data: 3 0 31 35 34 355 32 33 344 7 index: 0 1 2 3 4 5 6 7 8 9 鏈表元素:31 32 33 344 34 355 35 嘗試插入位置 3 值 333, (節點類型: 中間節點) --------------current linklist state----------------- Cursor: 9 7 6 0 5 3 1 8 4 2 Data: 3 333 31 35 34 355 32 33 344 8 index: 0 1 2 3 4 5 6 7 8 9 鏈表元素:31 32 333 33 344 34 355 35 插入失敗,鏈表已滿! --------------current linklist state----------------- Cursor: 9 7 6 0 5 3 1 8 4 2 Data: 3 333 31 35 34 355 32 33 344 8 index: 0 1 2 3 4 5 6 7 8 9 鏈表元素:31 32 333 33 344 34 355 35 get error! pos(9) out of range. get error! pos(0) out of range. get success! val:35 get success! val:31 get success! val:35 嘗試刪除位置: 8, (節點類型:尾節點), 刪除成功! pop success! val: 35 --------------current linklist state----------------- Cursor: 3 7 6 9 5 0 1 8 4 2 Data: 5 333 31 0 34 355 32 33 344 7 index: 0 1 2 3 4 5 6 7 8 9 鏈表元素:31 32 333 33 344 34 355 get success! val:355 嘗試刪除位置: 7, (節點類型:尾節點), 刪除成功! pop success! val: 355 --------------current linklist state----------------- Cursor: 5 7 6 9 0 3 1 8 4 2 Data: 4 333 31 0 34 0 32 33 344 6 index: 0 1 2 3 4 5 6 7 8 9 鏈表元素:31 32 333 33 344 34 get success! val:34 嘗試刪除位置: 6, (節點類型:尾節點), 刪除成功! pop success! val: 34 --------------current linklist state----------------- Cursor: 4 7 6 9 5 3 1 8 0 2 Data: 8 333 31 0 0 0 32 33 344 5 index: 0 1 2 3 4 5 6 7 8 9 鏈表元素:31 32 333 33 344 get success! val:344 嘗試刪除位置: 5, (節點類型:尾節點), 刪除成功! pop success! val: 344 --------------current linklist state----------------- Cursor: 8 7 6 9 5 3 1 0 4 2 Data: 7 333 31 0 0 0 32 33 0 4 index: 0 1 2 3 4 5 6 7 8 9 鏈表元素:31 32 333 33 get success! val:33 嘗試刪除位置: 4, (節點類型:尾節點), 刪除成功! pop success! val: 33 get success! val:333 嘗試刪除位置: 3, (節點類型:尾節點), 刪除成功! pop success! val: 333 --------------current linklist state----------------- Cursor: 1 7 6 9 5 3 0 8 4 2 Data: 6 0 31 0 0 0 32 0 0 2 index: 0 1 2 3 4 5 6 7 8 9 鏈表元素:31 32 get success! val:32 嘗試刪除位置: 2, (節點類型:尾節點), 刪除成功! pop success! val: 32 get success! val:31 嘗試刪除位置: 1, (節點類型:頭節點 + 尾節點), 刪除成功! pop success! val: 31 pop error! linklist is empty. --------------current linklist state----------------- Cursor: 2 7 6 9 5 3 1 8 4 2 Data: 0 0 0 0 0 0 0 0 0 0 index: 0 1 2 3 4 5 6 7 8 9 鏈表爲空!