存放游标和实际数据 数据的第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 链表为空!