news 2026/6/12 13:16:10

不带头节点的循环双链表

作者头像

张小明

前端开发工程师

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/10 13:51:37

基于SpringBoot实现的大学生创新创业交流与分享平台

系统介绍基于SpringBootVue实现的大学生创新创业交流与分享平台采用前后端分离的架构方式&#xff0c;系统设计了管理员、导师、学生三种角色&#xff0c;管理员实现了首页看板、学生管理、导师管理、项目类型、创业资讯、创业项目、活动类型、报名、系统管理、个人中心等模块。…

作者头像 李华
网站建设 2026/6/11 2:54:27

已有析音法

已有析音法 析音法是分析语音的方法。分析语音&#xff0c;就是对语音作分析&#xff0c;被简称为析音。因此&#xff0c;分析语音的方法被简称为析音法。在汉语中&#xff0c;在学术上&#xff0c;析音法过去通常被称呼为语音分析法或音节分析法。 在汉语中&#xff0c;析音…

作者头像 李华
网站建设 2026/6/10 15:35:42

时间迷思:你手机上的“秒”,凭什么定义全世界?

文章目录前言一、 世界时 - 基于地球自转1.1 太阳时1.2恒星时二、原子的脉搏——重新定义“一秒”三、尴尬的妥协——当原子秒遇上太阳日四、GPS时间 - 导航系统的生命线总结前言 “现在几点了&#xff1f;”这是一个再平常不过的问题。但为了回答它&#xff0c;人类建立了一套…

作者头像 李华
网站建设 2026/6/10 15:51:11

2025 洗衣液行业投资逻辑:政策驱动绿色转型,细分赛道暗藏机遇

2025 洗衣液行业投资逻辑&#xff1a;政策驱动绿色转型&#xff0c;细分赛道暗藏机遇 中国洗涤用品工业协会 2025 年数据显示&#xff0c;国内洗衣液市场规模已突破 580 亿元&#xff0c;年复合增长率维持在 6.2% 左右&#xff0c;预计 2030 年将进一步突破 760 亿元。作为刚需…

作者头像 李华
网站建设 2026/6/10 15:42:40

3、开源软件项目剖析与Linux安装准备

开源软件项目剖析与Linux安装准备 开源软件项目的魅力与Linux的诞生 在很多人眼中,Linux就像是一个奇异的突变体,难以想象一个如此复杂且依赖严谨规范的计算机操作系统,竟由全球各地松散的计算机极客志愿者们共同开发。但实际上,开源方式能创造出卓越的软件,往往源于人类…

作者头像 李华