C语言-双向链表
双向链表,主要是构建了一个向前地址的指针p_prev,用于指向前面的指针地址
02link.h
/* 构造链表的结构体 */ #ifndef __02LINK_H__ #define __02LINK_H__ #include <stdio.h> #include <stdlib.h> typedef struct node{ int val; struct node *p_next; struct node *p_prev; } node; typedef struct { node head; node tail; node *p_cur; } link; void link_init(link *); void link_deinit(link *); int link_size(link *); //判断链表是否为空 int link_empty(link *); //在链表最后插入数字 int link_append(link *, int); //在头部插入数据 int link_head(link *, int ); //从小到大的插入顺序 int link_insert(link *, int ); //删除最后一个数字 int link_remove_tail(link *); //从链表中删除最前面的数字 int link_remove_head(link *); //删除链表中间的某个数 int link_remove(link *, int ); int link_get_tail(link *, int *); //获得最前面的数字 int link_get_head(link *, int *); //根据索引获取其中的一个数 int link_get(link *, int *, int ); void link_begin(link *); int link_next(link *, int *); #endif
02link.c
/* 构造链表的结构体 */ #include <stdio.h> #include <stdlib.h> #include "02link.h" void link_init(link *p_link) { //将头指针指向尾指针 p_link->head.p_next = &p_link->tail; p_link->tail.p_prev = &p_link->head; //将尾指针对应的指针地址设置为0 p_link->tail.p_next = NULL; p_link->head.p_prev = NULL; p_link->p_cur = NULL; } void link_deinit(link *p_link) { while (p_link->head.p_next != &p_link->tail) { node *p_first = &p_link->head; node *p_mid = p_first->p_next; node *p_last = p_mid->p_next; p_first->p_next = p_last; p_last->p_prev = p_first; free(p_mid); p_mid = NULL; } } int link_size(link *p_link) { node* p_tmp = NULL; int cnt = 0; for (p_tmp = &p_link->head;p_tmp != &p_link->tail;p_tmp = p_tmp->p_next) { node *p_first = p_tmp; node *p_mid = p_first->p_next; node *p_last = p_mid->p_next; if (p_mid != &p_link->tail) { cnt++; } } return cnt; } //判断链表是否为空 int link_empty(link *p_link) { return (!link_size(p_link)); } //在链表最后插入数字 int link_append(link *p_link, int val) { node *p_node = NULL; node *p_tmp = NULL; p_node = (node*)malloc(sizeof(node)); if (!p_node) { free(p_node); p_node = NULL; return 0; } p_node->val = val; node* p_last = &p_link->tail; node* p_mid = p_last->p_prev; p_last->p_prev = p_node; p_node->p_prev = p_mid; return 1; } //在头部插入数据 int link_head(link *p_link, int val) { node *p_node = NULL; node *p_tmp = NULL; p_node = (node*)malloc(sizeof(node)); if (!p_node) { free(p_node); p_node = NULL; return 0; } p_node->val = val; node* p_first = &p_link->head; node* p_mid = p_first->p_next; p_first->p_next = p_node; p_node->p_next = p_mid; return 1; } //从小到大的插入顺序 int link_insert(link *p_link, int val) { node *p_node = NULL; node *p_tmp = NULL; p_node = (node*)malloc(sizeof(node)); if(!p_node) { free(p_node); p_node = NULL; return 0; } p_node->val = val; for (p_tmp = &p_link->head;p_tmp != &p_link->tail;p_tmp = p_tmp->p_next) { node *p_first = p_tmp; node *p_mid = p_first->p_next; node *p_last = p_mid->p_next; if (p_mid->val > val || p_mid == &p_link->tail) { p_first->p_next = p_node; p_node->p_next = p_mid; return 1; } } } //删除最后一个数字 int link_remove_tail(link *p_link) { node *p_node = NULL; node *p_tmp = NULL; p_node = (node*)malloc(sizeof(node)); if (!p_node) { free(p_node); p_node = NULL; return 0; } node* p_last = &p_link->tail; node* p_mid = p_last->p_prev; node* p_first = p_mid->p_prev; p_last->p_prev = p_first; free(p_mid); p_mid = NULL; return 1; } //从链表中删除最前面的数字 int link_remove_head(link *p_link) { node *p_node = NULL; node *p_tmp = NULL; p_node = (node* )malloc(sizeof(node)); if (!p_node) { free(p_node); p_node = NULL; return 0; } node* p_first = &p_link->head; node* p_mid = p_first->p_next; node* p_last = p_mid->p_next; p_first->p_next = p_last; free(p_mid); p_mid = NULL; return 1; } //删除链表中间的某个数 int link_remove(link *p_link, int val) { node *p_tmp = NULL; node *p_node = NULL; p_node = (node*)malloc(sizeof(node)); if (!p_node){ free(p_node); p_node = NULL; return 0; } for (p_tmp = &p_link->head;p_tmp != &p_link->tail;p_tmp = p_tmp->p_next) { node* p_first = p_tmp; node* p_mid = p_first->p_next; node* p_last = p_mid->p_next; if (p_mid->val == val) { p_first->p_next = p_last; free(p_mid); p_mid = NULL; return 1; } } return -1; } //获得末尾的数字 int link_get_tail(link *p_link, int *p_val) { node *p_node = NULL; node *p_tmp = NULL; if (p_link->head.p_next == &p_link->tail) { return 0; } node* p_last = &p_link->tail; node* p_mid = p_last->p_prev; *p_val = p_mid->val; return 1; } //获得最前面的数字 int link_get_head(link *p_link, int *p_val) { node *p_node = NULL; node *p_tmp = NULL; if (p_link->head.p_next == &p_link->tail) { return 0; } node* p_first = &p_link->head; node* p_mid = p_first->p_next; *p_val = p_mid->val; return 1; } //根据索引获取其中的一个数 int link_get(link *p_link, int *p_val, int sn){ int cnn = 0; node* p_tmp = NULL; if (p_link->head.p_next == &p_link->tail) { return 0; } for (p_tmp = &p_link->head;p_tmp != &p_link->tail;p_tmp = p_tmp->p_next) { node* p_first = p_tmp; node* p_mid = p_first->p_next; node* p_last = p_mid->p_next; if (sn == cnn && p_mid != &p_link->tail) { *p_val = p_mid->val; } cnn++; } return 1; } //获得开始的位置 void link_begin(link *p_link) { p_link->p_cur = &p_link->head; } //获得将当前位置移动到下一个位置 int link_next(link *p_link, int *p_val) { if (!p_link->p_cur) { return 0; } p_link->p_cur = p_link->p_cur->p_next; if (p_link->p_cur == &p_link->tail) { p_link->p_cur = NULL; return 0; } else { *p_val = p_link->p_cur->val; return 1; } }
02main.c
/* 链表调用 */ #include <stdio.h> #include "02link.h" int main() { link l = {0}; link_init(&l); int val = 0; printf("链表是否为空%d\n", link_empty(&l)); printf("链表的size是%d\n", link_size(&l)); link_append(&l, 12); link_head(&l, 10); link_insert(&l, 11); link_insert(&l, 14); printf("链表是否为空%d\n", link_empty(&l)); printf("链表的size是%d\n", link_size(&l)); //link_remove(&l, 12); /* link_get(&l, &val, 0); printf("val的数据是%d\n", val); link_get(&l, &val, 1); printf("val的数据是%d\n", val); link_get(&l, &val, 2); printf("val的数据是%d\n", val); */ link_begin(&l); //获得开始目录 for(int i = 0;i < link_size(&l);i++) { link_next(&l, &val); printf("%d ", val); } printf("\n"); link_deinit(&l); }
每天更新pyQt5内容
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?