【C语言教程】“双向循环链表”学习总结和C语言代码实现!
双向循环链表
定义
双向循环链表和它名字的表意一样,就是把双向链表的两头连接,使其成为了一个环状链表。只需要将表中最后一个节点的next指针指向头节点,头节点的prior指针指向尾节点,链表就能成环儿,如图所示:
需要注意的是,虽然双向循环链表成环状,但本质上还是双向链表,因此在双向循环链表中,依然能够找到头指针和头节点等。双向循环链表和双向链表相比,唯一的不同就是双向循环链表首尾相连,其他都完全一样。
注意:因为我上面已经讲了双向链表,所以这里只注重讲他们的实现差异。另因为带头节点会更好操作,所以我的代码都有头节点。
1、双向循环链表的创建
初始化时需要将头节点的next和prior都指向自己。

//1、初始化双向循环链表(带头节点)
Status initLinkList(LinkList *list){
//创建头节点
*list = malloc(sizeof(Node));
if (*list == NULL) {
return ERROR;
}
//前驱和后继都指向自己
(*list)->prior = *list;
(*list)->data = -1;
(*list)->next = *list;
printf("已初始化链表~\n");
return OK;
}
2、遍历双向循环链表
注意它的尾节点的next不再是Null,而是头节点
//2、遍历双向循环链表
void printfLinkLisk(LinkList list){
printf("遍历链表:\n");
if (list == NULL || list->next == list) {
printf("这是一个空链表\n");
return;
}
LinkList p = list;
//判断next是否全部正确
printf("根据next从前往后遍历:");
while (p->next != list) {
printf("%d ",p->next->data);
p = p->next;
}
printf("\n");
//判断prior是否全部正确
printf("根据prior从后往前遍历:");
while (p != list) {
printf("%d ",p->data);
p = p->prior;
}
printf("\n");
}
3、根据索引位置添加节点
这里不需要判断尾节点的next是否为Null,因为它会指向头节点。
//3、根据索引位置插入数据至链表中
Status insertLinkList(LinkList *list, int index, ElemType data){
if (list == NULL || index < 0) {
return ERROR;
}
int i = 0;
LinkList priorNode = *list;
//判断插入的位置,这里开始位置是0,index超过链表长度则插入末尾
while (i < index && priorNode->next != *list) {
priorNode = priorNode->next;
i++;
}
LinkList newNode = malloc(sizeof(Node));
if (newNode == NULL) {
return ERROR;
}
newNode->data = data;
//插入操作共四步,看好了,别眨眼
//1.将priorNode->next节点的前驱指向新节点
priorNode->next->prior = newNode;
//2.将新节点->next指向原来的priorNode->next
newNode->next = priorNode->next;
//3.将priorNode->next指向新节点
priorNode->next = newNode;
//4.新节点的前驱指向priorNode
newNode->prior = priorNode;
return OK;
}
4、根据索引位置删除节点
这里不需要判断尾节点的next是否为Null,因为它会指向头节点。
//4、根据索引位置删除节点
Status deleteLinkListByIndex(LinkList *list, int index, ElemType *data){
if (*list == NULL || index < 0) {
return ERROR;
}
LinkList locaNode = *list;
int i = 0;
//注意别删了头节点
while (i <= index) {
locaNode = locaNode->next;
if (locaNode == *list) {
printf("没有这个你想要删除的节点\n");
return ERROR;
}
i++;
}
//开始删除,只需要做两步
locaNode->prior->next = locaNode->next;
locaNode->next->prior = locaNode->prior;
*data = locaNode->data;
free(locaNode);
return OK;
}
5、根据存储的值删除节点
这里不需要判断尾节点的next是否为Null,因为它会指向头节点。
//5、根据存储的值删除节点
Status deleteLinkListByData(LinkList *list, ElemType data){
if (*list == NULL) {
return ERROR;
}
LinkList locaNode = (*list)->next;
while (locaNode != *list) {
if (locaNode->data == data) {
break;
}
locaNode = locaNode->next;
}
if (locaNode == *list) {
printf("没有这个你想要删除的节点\n");
return ERROR;
}
//开始删除,只需要做两步
locaNode->prior->next = locaNode->next;
locaNode->next->prior = locaNode->prior;
free(locaNode);
return OK;
}
6、根据值查找节点
尾节点的next可是头节点哦,找到它就是最后一个了。
//6、查找元素
Status selectNode(LinkList list, ElemType data, LinkList *locaNode){
if (list == NULL) {
return ERROR;
}
LinkList p = list->next;
while (p != list) {
if (p->data == data) {
*locaNode = p;
break;
}
p = p->next;
}
if (*locaNode == NULL) {
printf("没有这个你想要的节点\n");
return ERROR;
}
else {
return OK;
}
}
其它辅助代码
#include "stdlib.h"
#define OK 1
#define ERROR 0
//元素类型
typedef int ElemType;
//状态类型
typedef int Status;
//定义节点结构体
typedef struct Node {
struct Node *prior;
ElemType data;
struct Node *next;
} Node;
typedef Node *LinkList;
int main(int argc, const char * argv[]) {
LinkList list;
initLinkList(&list);
for (int i = 0; i < 10; i ++) {
insertLinkList(&list, i, i);
}
printfLinkLisk(list);
int index, data;
printf("输入你想插入的位置(从0开始)和存储的值:");
scanf("%d %d",&index,&data);
insertLinkList(&list, index, data);
printfLinkLisk(list);
printf("输入你想删除的位置(从0开始):");
scanf("%d",&index);
deleteLinkListByIndex(&list, index, &data);
printfLinkLisk(list);
printf("输入你想删除的节点的值(只删最前的那个):");
scanf("%d",&data);
deleteLinkListByData(&list, data);
printfLinkLisk(list);
printf("\n");
return 0;
}
输出结果:
—END—
看到这里是不是又学到了很多新知识呢~
如果你很想学编程,小编推荐我的C语言/C++编程学习基地【点击进入】!
都是学编程小伙伴们,带你入个门还是简简单单啦,一起学习,一起加油~
还有许多学习资料和视频,相信你会喜欢的!
涉及:游戏开发、常用软件开发、编程基础知识、课程设计、黑客等等......
【C语言教程】“双向循环链表”学习总结和C语言代码实现!的更多相关文章
- 【C语言教程】双向链表学习总结和C语言代码实现!值得学习~
双向链表 定义 我们一开始学习的链表中各节点中都只包含一个指针(游标),且都统一指向直接后继节点,通常称这类链表为单向链表. 虽然使用单向链表能 100% 解决逻辑关系为 "一对一" ...
- C语言通用双向循环链表操作函数集
说明 相比Linux内核链表宿主结构可有多个链表结构的优点,本函数集侧重封装性和易用性,而灵活性和效率有所降低. 可基于该函数集方便地构造栈或队列集. 本函数集暂未考虑并发保护. 一 ...
- 数据结构8: 双向链表(双向循环链表)的建立及C语言实现
之前接触到的链表都只有一个指针,指向直接后继,整个链表只能单方向从表头访问到表尾,这种结构的链表统称为 “单向链表”或“单链表”. 如果算法中需要频繁地找某结点的前趋结点,单链表的解决方式是遍历整个链 ...
- c语言实现--双向循环链表操作
1,双向链表相当于两个单向循环链表. 2,双向链表的结点定义. 1 struct DULNode 2 { 3 int data; 4 struct DULNode * prior; 5 struct ...
- C语言实现双向循环链表
#include <stdio.h> #include <stdlib.h> #include <string.h> struct list_head { stru ...
- Swift语言教程中文文档
Swift语言教程中文文档 Swift语言教程(一)基础数据类型 Swift语言教程(二)基础数据类型 Swift语言教程(三)集合类型 Swift语言教程(四) 集合类型 Swift语言教程(五)控 ...
- Swift3.0语言教程字符串转换为数字值
Swift3.0语言教程字符串转换为数字值 Swift3.0语言教程字符串转换为数字值,在NSString中,开发者可以将字符串转换为数字值,通过这些数字值可以实现一些功能,如加法运算.减法运算等.数 ...
- Swift3.0语言教程比较、判断字符串
Swift3.0语言教程比较.判断字符串 Swift3.0语言教程比较.判断字符串,在一个程序中字符串很多时,常常会做的操作就是对这些字符串进行比较和判断.本小节将讲解这些内容. 1.不区分大小写比较 ...
- Xamarin XAML语言教程构建进度条ProgressBar
Xamarin XAML语言教程构建进度条ProgressBar Xamarin XAML语言教程构建进度条ProgressBar,ProgressBar被称为进度条,它类似于没有滑块的滑块控件.进度 ...
随机推荐
- jenkins通过API触发构建任务
添加一个可变参数 配置token 参数用 ${参数名称} 引用 外部调用url地址:ip:port/view/视图名称/job/任务名称/buildWithParameters?token=test& ...
- Linux:正则表达式2
基础正则表达式 ^ : 以xx开头 $ :以xx结尾 ^$ :代表空行 . 任意一个字符 \ :转义符号,让有着特殊意义的字符可被使用 * :重复0个或多个前面的字符,例如 a* 2表示a后面 ...
- 基于 ramfs 的 OTA
背景 默认的 OTA 方案是基于 recovery 系统完成的.某个产品考虑产品形态和 flash 容量之后,计划去掉 recovery 系统(不考虑掉电安全),这就需要 OTA 方案能支持在只有单个 ...
- get、post请求方式在jmeter中使用步骤
jmeter:性能测试工具,压测 一.jmeter工具测试接口时使用步骤: 1.测试计划右键--添加--Threads(Users)--线程组(线程数就是并发数) 2.线程组右键--Sampler-- ...
- [补题][Codeforces478D]Red-Green Towers(DP)
题目链接 http://codeforces.com/problemset/problem/478/D 题意 叠放塔:有红.绿两种色块.从第一层开始,第一层1块,第二层2块,第i层i块. 要求每一层只 ...
- js 去掉字符串最后一个逗号:笑死我了
今天突然遇到js 去掉字符串最后一个逗号的问题,本想偷懒搜个代码吧,没想到看到百度的第一条记录是这么一篇文章. 网易博客: http://blog.163.com/li_crane/blog/stat ...
- vue | 基于vue的城市选择器和搜索城市对应的小区
城市选择器应该是比较常用的一个组件,用户可以去选择自己的城市,选择城市后返回,又根据自己选择的城市搜索小区. 功能展示 这是选择结果 这是选择城市 这是搜索小区 这是搜索小区接口,key为城市名字,i ...
- domReady的理解
domReady的理解 domReady是名为DOMContentLoaded事件的别称,当初始的HTML文档被完全加载和解析完成之后,DOMContentLoaded事件被触发,而无需等待样式表.图 ...
- python中yield的用法详解——最简单,最清晰的解释(转载)
原文链接 首先我要吐槽一下,看程序的过程中遇见了yield这个关键字,然后百度的时候,发现没有一个能简单的让我懂的,讲起来真TM的都是头头是道,什么参数,什么传递的,还口口声声说自己的教程是最简单的, ...
- keepalived+nginx集群
https://blog.csdn.net/l1028386804/article/details/72801492?ops_request_misc=%257B%2522request%255Fid ...