ps:我现在是大二上,这个学期修数据结构,知识点是我上课,下课在书上,网上各种地方找到理解了之后写出来的这些东西,可能会有错误(请C友们指正),这个学期会把数据结构更新完,一些比较简单的增删改查我第一篇博客讲了之后,后面不会花费篇幅讲增删改查了,简单的东西我很快就会更完,以后大部分篇幅会讲算法哈哈哈。

来啦,兄弟们中午好啊! 废话不多缩,come with me ,baby.

循环链表:

**
昨天的单向链表不知道有没有兄弟姐妹(顺序不分先后)注意到,链表的最后一个指针指向的是NULL呢? 正是通过单向链表的最后一个指针指向的是NULL,我们才得以完成链表的遍历,完成链表的遍历是增删查改的重中之重。今天呢,我们来康康循环链表,同学们不用担心,循环链表肥肠的简单。
单向链表的最后一个指针指向NULL,循环链表的最后一个指针指向头结点。就是这么一个简单的改变,让整个链表由一条链变成了一个环,由此,遍历方式也有不同,接下来上代码,

初始化循环链表:

typedef struct list{
int data;//数据域
list *next;//指针域
};
list CreatHead()//创建头节点
{
list head=(list)malloc(sizeof(list));
head->next=head;//头指针指向头节点,没毛病奥,铁子,从头节点就已经变成一个环了
return head;
}
void CreatList(list
head){ //初始化整个链表,咱们今天来一手尾插法嗷
list *p=head; //这个是尾结点
for(int i=0;i<5;i++)
{
list newnode=(list)malloc(sizeof(list)); //给新鲜的节点开辟地址空间
newnode->data=i; //赋值,跟昨天一样滴,
newnode->next=p->next;
p->next=newnode;//这两行代码没问题吧,跟昨天也是一样的
p=newnode;//让尾部节点一直跟着最新进来的节点走
}

}
写好了,我们看看输出链表函数怎么写:
这是单链表的输出方式,只要指针指向的下一个不为空,则输出内容

printfList(list *p)
{list *head=p;printf("循环链表数据如下:\n");while(p->next!=NULL){p=p->next;printf("%d ",p->data);}printf("\n"); }

这个代码我们拉进主函数康康会怎么输出:

#Include<stdio.h>
#include<stdlib.h>
typedef struct list{int data;//数据域 list *next;//指针域
};
list *CreatHead()//创建头节点
{list *head=(list*)malloc(sizeof(list));head->next=head;//头指针指向头节点,没毛病奥,铁子,从头节点就已经变成一个环了return head;
}
void CreatList(list* head){   //初始化整个链表,咱们今天来一手尾插法嗷list *p=head;   //这个是尾结点for(int i=0;i<5;i++){list *newnode=(list*)malloc(sizeof(list));   //给新鲜的节点开辟地址空间newnode->data=i;                                //赋值,跟昨天一样滴,newnode->next=p->next;p->next=newnode;//这两行代码没问题吧,跟昨天也是一样的p=newnode;//让尾部节点一直跟着最新进来的节点走}}
printfList(list *p)
{list *head=p;printf("循环链表数据如下:\n");while(p->next!=NULL){p=p->next;printf("%d ",p->data);}printf("\n"); }
int main()
{list *p=CreatHead();CreatList(p); printfList(p);
}

贴上代码:


嘿嘿,是不是感觉看麻了,为什么会酱紫输出呢?0 1 2 3 4 然后一个乱七八糟的数字,正常的输出应该是0 1 2 3 4 然后完事儿,这是因为我们输出的循环条件是while(p->next!=NULL),因为是循环链表,指针永远都不会为空且最后一个指针指向头节点,而且头节点是没有初始化数据域的,所以酱紫弄就循环输出(0 1 2 3 4 乱码)了接下来改善一下输出函数:

printfList(list *p)
{list *head=p;printf("循环链表数据如下:\n");while(p->next!=head){p=p->next;printf("%d ",p->data);}printf("\n"); }

这里我把循环输出的条件改成了只要指针指向的结点不为头结点,则进行输出,酱紫就是正常输出了:

正常了奥,兄弟们,接下来就是遍历链表完成增删改查这一类操作了,真的太简单洛,我把代码放到最后面,要的兄弟姐妹去拿就OK洛。

双向链表:

兄弟姐妹们,我们还是对比学习,之前学习的单链表的遍历方法是从头指针指向后继,
这就有一种局限性,头指针只能从前往后,不能从后往前,单一节点也只能找到后继结点,不能找到它的前驱结点,正是因为这种局限性,辣么双向链表就应运而生咯,双向链表一点也不难,大家往下看嘛。
既然要实现双向遍历,那么一个节点肯定要放两个指针,一个指向前驱节点,一个指向后继节点,数据保持不变。
双向链表节点代码如下:

typedef struct list()
{int data;list *next;// 后继指针,list *prior;//前驱指针
}

初始化双向链表:

list *CreatHead()//搞一个头结点出来
{list *head=(list*)malloc(sizeof(list));head->prior=NULL;//前继指针置空head->next=NULL;//后驱指针置空
}
void CreatList(list *head){list *p=head;//这里咱们用尾插法所以先搞一个尾指针p出来for(int i=1;i<6;i++){list *newnode=(list*)malloc(sizeof(list));newnode->data=i;//给新鲜的结点数据域赋值newnode->next=p->next;//这里就是老样子喽p->next=newnode;newnode->prior=p;p=newnode;//尾结点一直跟着新鲜的结点跑}
}

双向链表的增删改查和单向链表的增删改查没有不一样的地方,兄弟姐妹们,如果是从尾部结点开始遍历整个链表的话,咱们就把指向前驱结点的指针想像成从头结点往后遍历就OK了,不难的,敲一遍代码就懂是什么意思了。

删除结点

void DeleteNode(list *head,int add)//add为删除结点的位置
{list *p=head;for(int i=0;i<5;i++){p=p->next;if(i==add-1){p->prior->next=p->next;//删除节点的前驱节点指向的节点变为删除节点指向的节点p->next->prior=p->prior;//删除节点的后继节点的前驱指针指向删除节点的前驱节点free(p);//咱们要把删除了的节点空间给释放了,做一个负责任的男人,从你我做起!break;} }
}

插入节点:

void insertNode(list *head,int q,int add)//add为要插入数据的位置,q为数据
{for(int i=0;i<5;i++) {head=head->next; if(i==add-1){list *p=(list*)malloc(sizeof(list));p->data=q;p->next=head->next;head->next->prior=p;head->next=p;p->prior=head;}}
}

查找:

void query(list *p,int q)//p为所要查找结点的数据域,
{//由尾部指针往前查找和由头指针往后查找是一模一样的原理,咱们就外甥打灯笼--照舅了.int i=0; while(p->next!=NULL){p=p->next;i++;if(p->data==q){printf("您所查找的数据位于第%d位\n",i);break;}}
}

放进主函数试试效果:

#include<stdio.h>
#include<stdlib.h>
typedef struct list
{int data;list *next;list *prior;
}list;
list *CreatHead()
{list *head=(list*)malloc(sizeof(list));head->prior=NULL;head->next=NULL;return head;
}
void CreatList(list *head){list *p=head;for(int i=1;i<6;i++){list *newnode=(list*)malloc(sizeof(list));newnode->data=i;newnode->next=p->next;p->next=newnode;newnode->prior=p;p=newnode;}}
void printfList(list *p)
{printf("从头节点开始遍历输出数据:\n"); while(p->next!=NULL){p=p->next;printf("%d ",p->data);}printf("%\n");printf("从尾节点开始遍历输出数据:\n");while(p->prior!=NULL){//p=p->prior;printf("%d ",p->data);p=p->prior;}printf("\n");
}
void insertNode(list *head,int q,int add)//add为要插入数据的位置,q为数据
{for(int i=0;i<5;i++) {head=head->next; if(i==add-1){list *p=(list*)malloc(sizeof(list));p->data=q;p->next=head->next;head->next->prior=p;head->next=p;p->prior=head;}}}
void DeleteNode(list *head,int add)//add为删除结点的位置
{list *p=head;for(int i=0;i<5;i++){p=p->next;if(i==add-1){//   printf("%d",i);p->prior->next=p->next;p->next->prior=p->prior;free(p);break;} }
}
void query(list *p,int q)//p为所要查找结点的数据域,
{//由尾部指针往前查找和由头指针往后查找是一模一样的原理,咱们就外甥打灯笼--照舅了.int i=0; while(p->next!=NULL){p=p->next;i++;if(p->data==q){printf("您所查找的数据位于第%d位\n",i);break;}}
}
int main()
{list *p=CreatHead();CreatList(p);printf("在第一位数据之后插入3\n");insertNode(p,3,1);printf("删除第二位结点\n");DeleteNode(p,2);printf("查找数据域为3的数据所在位置\n");query(p,3);printfList(p);}

测试打印链表:

测试删除第二位节点:

测试增加节点
测试查找节点:

双向链表的操作完了,觉得怎么样呢?是不是很简单?,我写得不是很全,欢迎有疑惑的同学私信我或者在评论区讨论,我们一起学习。
下面我贴上循环链表的代码,需要的兄弟姐妹自取,记得给我点个关注点个赞,让我感受一下手机响不停的感觉好吗?(QAQ)

#include <stdio.h>
#include <stdlib.h>
/*
循环链表
*/
typedef struct list
{int data;   //数据域list *next; //指针域
};
list *CreatHead()
{list *head = (list *)malloc(sizeof(list));head->next = head;return head;
}
void CreatList(list *head)
{list *p = head;for (int i = 0; i < 5; i++){list *newnode = (list *)malloc(sizeof(list));newnode->data = i;newnode->next = p->next;p->next = newnode;p = newnode;}
}
printfList(list *p)
{list *head = p;printf("循环链表数据如下:\n");while (p->next != head){p = p->next;printf("%d ", p->data);}printf("\n");
}
void insert(list *p, int q, int add)
{for (int i = 0; i < 5; i++){p = p->next;if (i == add - 1){list *newnode = (list *)malloc(sizeof(list));newnode->data = q;newnode->next = p->next;p->next = newnode;}}
}
void DeleteNode(list *head, int add)
{list *p;for (int i = 0; i < 5; i++){p = head;head = head->next;if (i == add - 1){p->next = head->next;free(head);break;}}
}
void query(list *head, int q)
{int i = 0;while (head->next != head){i++;head = head->next;if (head->data == q){printf("查找数据位于第%d位置\n", i);break;}}
}
int main()
{list *p = CreatHead();CreatList(p);printf("在第一位数据之后插入3\n");insert(p, 3, 1);printf("删除第二位结点\n");DeleteNode(p, 2);printf("查找数据域为3的数据所在位置\n");query(p, 3);printfList(p);system("pause");
}

上面这段代码根据你的需求打上注释就可以用了,今天的分享到这里就结束了,希望能收获大家的好评,记得给我点赞关注嗷,兄弟姐妹们!再见!

《数据结构》严蔚敏第二版 2.53 循环链表,双向链表相关推荐

  1. 数据结构 严蔚敏 第二章 线性表

    数据结构 严蔚敏 第二章 线性表 线性表:由n个(n>=0)数据特征相同的元素构成的有限序列. 线性表的类型定义表示和实现 顺序表 存储单元地址连续 随机存取 若每个元素占用 m 个存储单元,以 ...

  2. 构建线性表的c语言代码,数据结构严蔚敏C语言版—线性表顺序存储结构(顺序表)C语言实现相关代码...

    1.运行环境 这里说明一下这里所有的C语言代码都是基于code::blocks 20.03编译运行的.当然一些其他集成开发环境应该也是可以的,个人不太喜欢功能太过强大的IDE,因为那同样意味着相关设置 ...

  3. 数据结构严蔚敏C语言版—线性表顺序存储结构(顺序表)C语言实现相关代码

    数据结构严蔚敏C语言版-线性表顺序存储结构(顺序表)C语言实现相关代码 1.运行环境 2.准备工作 1)项目构建 1>新建一个SeqList项目 2>新建两个文件Sources和Heade ...

  4. 数据结构(C语言)第二版 第三章课后答案

    数据结构(C语言)第二版 第三章课后答案 1~5 C C D A A 6~10 D A B C D 11~15 D D B C B 1.选择题 (1)若让元素1, 2, 3 , 4, 5 依次进栈,则 ...

  5. 【计算机】数据结构-严蔚敏/清华大学P3

    [计算机]数据结构-严蔚敏/清华大学P1 第二章    线  性表 线性结构 是 一个数据元素的有序(次序)集 线性结构的基本特征: 1.  集合中必存在唯一的一个"第一元素": ...

  6. 《Java程序设计与数据结构教程(第二版)》学习指导

    <Java程序设计与数据结构教程(第二版)>学习指导 目录 图书简况 学习指导 第一章 绪论 第二章 数据和表达式 第三章 使用类和对象 第四章 条件和循环 第五章 编写类 第六章 图形用 ...

  7. 数据结构(C语言)第二版 第四章课后答案

    数据结构(C语言)第二版 第四章课后答案 1~5 B B C A B 6~10 B B C B B 11~15 A B D (C,B) C 1.选择题 (1)串是一种特殊的线性表,其特殊性体现在(B) ...

  8. 数据结构(C语言)第二版 第一章课后答案

    数据结构(C语言)第二版 第一章课后答案 这本书,我以后也会用,所以趁着考完试做个整理,顺便分享出来.电子资源发不出来,放评论区吧,有需要自取. 1. 简述下列概念:数据.数据元素.数据项.数据对象. ...

  9. 数据结构(C语言)第二版 第五章课后答案

    数据结构(C语言)第二版 第五章课后答案 1~5 A D D C A 6~10 C C B D C 11~15 B C A C A 1.选择题 (1)把一棵树转换为二叉树后,这棵二叉树的形态是(A) ...

最新文章

  1. 深度学习之好的博客文章
  2. 浅析Postgres中的并发控制(Concurrency Control)与事务特性(上)
  3. C# MD5摘要算法、哈希算法
  4. python绘制3d坐标轴_matplotlib在python上绘制3D散点图实例详解
  5. VMweare 安装 Kali Linux 系统
  6. sqlite for linux 可视化数据管理工具
  7. 快速锁屏电脑快捷键_电脑系统经典常用的快捷键你知道几个呢?
  8. Spotlight监控Oracle--Spotlight On Oracle安装和使用
  9. Mybatis框架Mybatis下载步骤
  10. CRC_8循环冗余校验码verilog实现
  11. Base64编码详解与URL安全的Base64编码
  12. Vue-basic 19.单文件组件
  13. 山东科技大学第二届ACM校赛解题报告
  14. 西北工业大学明德学院计算机老师,师资队伍结构
  15. css实现icon动画效果
  16. 记一次惨痛的拆机记录
  17. MEM/MBA 复试准备(04-02)MEM专题
  18. mysql的可视化图表_利用ECharts可视化mysql数据库中的数据
  19. VMware虚拟机的创建和启动,保姆式教学
  20. STM32 移植FreeModbus详细过程

热门文章

  1. 整理软件外包接单经验谈_01、寻找客户
  2. 如何每天自动申请京东试用
  3. Kafka:用于日志处理的分布式消息系统
  4. linux里面的$是什么意思?
  5. GPIO内部结构和各种模式
  6. HPU数学基础训练level1
  7. Joomla技术支持-SP Page Builder
  8. 基于java的超市积分管理系统
  9. 数据治理和合规性:如何确保大数据应用遵守法规和标准
  10. 菜鸟学习Mybatis 01