news 2026/7/3 11:33:56

不带头节点的循环双链表

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
不带头节点的循环双链表

1.创建一个双链表的类型

typedef struct DLNode { int data; struct DLNode* prior, * next;//里面有两个指针,一个前驱指针,一个后驱指针 } DLNode, * DLinkList;//重新定义一个名字,DLNode是节点名字,DLinkList是双链条的名字,也是个指针

2.用创建好的结构体创建一个变量,进行初始化

int InitDLinkList(DLinkList*L) { (*L) = NULL;//把表头置为空 return 0; }

3.判断表是不是空表,因为有两个节点指针,判断节点指针是不是都为空即可

int Is_empty(DLinkList*L) { return((*L)->next == NULL) && ((*L)->prior == NULL);//只要两个节点都指向空说明这个链表没有数据 }

4.给定一个位序进行插入,因为不带头节点所以考虑的事情相对多,要考虑第一个元素可最后一个元素

int insertLocate(DLinkList* L, int i, int elem)//在位序为i处插入一个elem 的元素 { if (i < 0) { return 1; } if (i == 1) { DLNode* s = (DLNode*)malloc(sizeof(DLNode)); if (s == NULL) { return 1; } s->data = elem; s->next = NULL; s->prior = NULL; (*L) = s; return 0; } int j = 1; DLNode* p = (*L);//将第一个元素付给p节点,就一个节点这个节点就是p while (p != NULL && j < i - 1) { p = p->next; j++; } if (p == NULL) { return 1;//i的值不合法 } DLNode* q = (DLNode*)malloc(sizeof(DLNode)); if (q == NULL) { return 1; } q->data = elem; q->next = p->next; if(p->next!=NULL)//如果等于就只需要链接三条线因为最后一个元素没有前驱指针 p->next->prior = q; p->next = q; q->prior = p; return 0; }

5.给定一个节点进行插入操作

int InsertDLNode(DLinkList* L, DLNode* p,DLNode*s, int elem)//在指定的节点p插入一个数据元素为elem的数据 { if (p == NULL) { return 1; } s->next = p->next;//插入到p节点的后面,然后交换p指针和q指针的值 if(p->next!=NULL) p->next->prior = s; p->next = s; s->prior = p; s->data = p->data; p->data = elem; return 0; }

6.给定一个值,查找这个值的位序

int GetLocate(DLinkList* L, int elem)//查找elem的位序 { DLNode* p = (*L); int count = 0; while (p) { count++; if (p->data == elem) { return count;//返回位序 } p = p->next; } return -1;//找不到返回-1

7.给定一个值,删除第一个相同的值

nt DeleteElem(DLinkList* L, int elem) { if ((*L)->data == elem) { DLNode* p = (*L)->next; (*L)->next->prior = (*L)->prior; free(*L); (*L) = p; } int pos=GetLocate(L, elem);//pos=位序 int j = 1; DLNode* p = (*L); while (p != NULL && j < pos - 1) { p = p->next; j++; } if (p == NULL) { return 0; } DLNode* ptr = p->next; p->next = ptr->next; if (ptr->next != NULL) ptr->next->prior = p; free(ptr); }

8.打印整个链表的数据

void Display(DLinkList* L) { DLNode* p = (*L); while (p!=NULL)//如果p等于NULL说明这个时候就是错误的,不会进入循环里面 { printf("%d-> ", p->data); p = p->next; } printf("NULL\n"); }

9.头插法建立双链表,头插法很重要,链表的逆置需要用到头插法

int HeadInsert(DLinkList* L)//头插法建立单链表 { int x = 0; scanf("%d", &x); DLNode* s = (DLNode*)malloc(sizeof(DLNode)); if (s == NULL) { return 1; } s->data = x; s->next = NULL; s->prior = NULL;//头插法建立双链表的时候先整一个头节点,逻辑上的头节点 (*L) = s; scanf("%d", &x); while (x)//x为零就结束建立 { DLNode* s = (DLNode*)malloc(sizeof(DLNode)); if (s == NULL) { return 1; } s->next = (*L); (*L)->prior = s; s->data = x; (*L) = s; scanf("%d", &x); } return 0; }

10.尾插法建立单链表

int TailInsert(DLinkList* L) { int x = 0; scanf("%d", &x); DLNode* s = (DLNode*)malloc(sizeof(DLNode)); if (s == NULL) { return 1; } s->data = x; s->next = NULL; s->prior = NULL; (*L) = s; //(*L)->next = NULL; scanf("%d", &x); DLNode* tail = (*L);//把头节点赋值个头指针 while (x) { DLNode* s = (DLNode*)malloc(sizeof(DLNode)); if (s == NULL) { return 1; } s->data = x; tail->next = s->next; s->prior = tail; tail->next = s; tail = s; scanf("%d", &x); } tail->next = NULL;//最后要把尾指针置为NULL return 0; }

11.总体代码

#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> typedef struct DLNode { int data; struct DLNode* prior, * next;//里面有两个指针,一个前驱指针,一个后驱指针 } DLNode, * DLinkList;//重新定义一个名字,DLNode是节点名字,DLinkList是双链条的名字,也是个指针 int InitDLinkList(DLinkList*L) { (*L) = NULL;//把表头置为空 return 0; } int Is_empty(DLinkList*L) { return((*L)->next == NULL) && ((*L)->prior == NULL);//只要两个节点都指向空说明这个链表没有数据 } int InsertDLNode(DLinkList* L, DLNode* p,DLNode*s, int elem)//在指定的节点p插入一个数据元素为elem的数据 { if (p == NULL) { return 1; } s->next = p->next;//插入到p节点的后面,然后交换p指针和q指针的值 if(p->next!=NULL) p->next->prior = s; p->next = s; s->prior = p; s->data = p->data; p->data = elem; return 0; } int insertLocate(DLinkList* L, int i, int elem)//在位序为i处插入一个elem 的元素 { if (i < 0) { return 1; } if (i == 1) { DLNode* s = (DLNode*)malloc(sizeof(DLNode)); if (s == NULL) { return 1; } s->data = elem; s->next = NULL; s->prior = NULL; (*L) = s; return 0; } int j = 1; DLNode* p = (*L);//将第一个元素付给p节点,就一个节点这个节点就是p while (p != NULL && j < i - 1) { p = p->next; j++; } if (p == NULL) { return 1;//i的值不合法 } DLNode* q = (DLNode*)malloc(sizeof(DLNode)); if (q == NULL) { return 1; } q->data = elem; q->next = p->next; if(p->next!=NULL)//如果等于就只需要链接三条线因为最后一个元素没有前驱指针 p->next->prior = q; p->next = q; q->prior = p; return 0; } int GetLocate(DLinkList* L, int elem)//查找elem的位序 { DLNode* p = (*L); int count = 0; while (p) { count++; if (p->data == elem) { return count;//返回位序 } p = p->next; } return -1;//找不到返回-1 } int DeleteElem(DLinkList* L, int elem) { if ((*L)->data == elem) { DLNode* p = (*L)->next; (*L)->next->prior = (*L)->prior; free(*L); (*L) = p; } int pos=GetLocate(L, elem);//pos=位序 int j = 1; DLNode* p = (*L); while (p != NULL && j < pos - 1) { p = p->next; j++; } if (p == NULL) { return 0; } DLNode* ptr = p->next; p->next = ptr->next; if (ptr->next != NULL) ptr->next->prior = p; free(ptr); } void Display(DLinkList* L) { DLNode* p = (*L); while (p!=NULL)//如果p等于NULL说明这个时候就是错误的,不会进入循环里面 { printf("%d-> ", p->data); p = p->next; } printf("NULL\n"); } int HeadInsert(DLinkList* L)//头插法建立单链表 { int x = 0; scanf("%d", &x); DLNode* s = (DLNode*)malloc(sizeof(DLNode)); if (s == NULL) { return 1; } s->data = x; s->next = NULL; s->prior = NULL;//头插法建立双链表的时候先整一个头节点,逻辑上的头节点 (*L) = s; scanf("%d", &x); while (x)//x为零就结束建立 { DLNode* s = (DLNode*)malloc(sizeof(DLNode)); if (s == NULL) { return 1; } s->next = (*L); (*L)->prior = s; s->data = x; (*L) = s; scanf("%d", &x); } return 0; } int TailInsert(DLinkList* L) { int x = 0; scanf("%d", &x); DLNode* s = (DLNode*)malloc(sizeof(DLNode)); if (s == NULL) { return 1; } s->data = x; s->next = NULL; s->prior = NULL; (*L) = s; //(*L)->next = NULL; scanf("%d", &x); DLNode* tail = (*L);//把头节点赋值个头指针 while (x) { DLNode* s = (DLNode*)malloc(sizeof(DLNode)); if (s == NULL) { return 1; } s->data = x; tail->next = s->next; s->prior = tail; tail->next = s; tail = s; scanf("%d", &x); } tail->next = NULL;//最后要把尾指针置为NULL return 0; } int main() { DLinkList L; InitDLinkList(&L); /*insertLocate(&L, 1, 2); insertLocate(&L, 2, 3); insertLocate(&L, 3, 4); insertLocate(&L, 4, 5); insertLocate(&L, 5, 6);*/ TailInsert(&L); //insertLocate(&L, 6, 7); //DeleteElem(&L,7); //DeleteElem(&L, 7); int ret=Is_empty(&L); if (ret) { printf("空\n"); } else { printf("非空\n"); } Display(&L); int pos = GetLocate(&L, 6); printf("%d\n",pos);// return 0; }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/26 5:37:59

JavaScript处理时间详解:时分秒的获取、计算与格式化

在JavaScript中处理时间&#xff0c;尤其是时、分、秒的获取、计算与格式化&#xff0c;是前端开发中一项基础且频繁的任务。无论是制作倒计时、显示当前时间&#xff0c;还是处理时间间隔&#xff0c;都离不开对这三个时间单位的精确操作。本文将从实际应用场景出发&#xff0…

作者头像 李华
网站建设 2026/7/2 7:42:28

AI基础从入门到实战:完整学习路线与代码实践

一、AI学习路线规划 AI学习需要遵循"数学基础→编程工具→机器学习→深度学习→项目实战"的系统路径&#xff0c;通常需要9-12个月完成从零基础到项目实战的完整学习。 阶段一&#xff1a;数学与编程基础&#xff08;1-3个月&#xff09; 数学基础是AI的基石&#…

作者头像 李华
网站建设 2026/6/29 6:06:46

驾驭昇腾CANN异步流水线从算子优化到系统级性能跃迁

目录 1 摘要 2 技术原理 2.1 架构设计理念解析 2.2 核心算法实现 2.2.1 异步执行模型深度解析 2.2.2 Stream并行机制实现原理 2.3 性能特性分析 2.3.1 同步 vs 异步性能对比 2.3.2 内存访问模式优化 3 实战部分 3.1 完整可运行代码示例 3.2 分步骤实现指南 步骤1&…

作者头像 李华
网站建设 2026/6/30 13:36:33

天远多头借贷行业风险版API接口调用代码流程、接入方法以及应用场景

一、精细化风控时代的“多头”计量工具 在互金与银行信贷业务中&#xff0c;“多头借贷”&#xff08;Multi-Lending&#xff09;往往是借款人资金链断裂的前兆。然而&#xff0c;传统的借贷次数统计已难以满足精细化风控的需求——借款人是在银行申请房贷&#xff0c;还是在夜…

作者头像 李华
网站建设 2026/7/2 22:30:52

音元系统:目录

目录 1 绪论 2 已有析音法 2.1 已有各式析音法的分类 2.1.1 各类各式二分法 2.1.1.1 两段二分法 2.1.1.1.1 声韵二分法 2.1.1.1.2 首干二分法 2.1.1.2 质调二分法 2.1.2 一调二质分析法 2.1.2.1 节调声质韵质分析法 2.1.2.2 节调声母韵母分析法 2.1.3 一调三质分析…

作者头像 李华
网站建设 2026/6/24 21:41:15

Java毕业设计不会做怎么办?

同学别慌&#xff0c;毕业设计确实是大学生涯的一大挑战&#xff0c;但完全有办法解决。很多同学都经历过这个阶段&#xff0c;我们一步步来梳理。 &#x1f50d; 第一步&#xff1a;冷静分析现状 明确截止时间 - 离答辩还有多少周&#xff1f; 评估当前进度 - 是完全没开始&…

作者头像 李华