数据结构——双向循环链表的建立、添加、遍历(十三)

前言

双向循环链表是链表的一种特殊形式,每个节点包含两个指针域:pPre指向直接前驱节点,pNext指向直接后继节点。链表的头节点的pPre指向尾节点,尾节点的pNext指向头节点,形成一个闭环。

一、建立链表

代码:

struct Node

{

int iData;

struct Node* pNext;

struct Node* pPre;

};

  • iData:存储节点的整型数据。
  • pNext:指向下一个节点的指针。
  • pPre:指向前一个节点的指针。

int main(void)

{

struct Node stHead = {0};

stHead.iData = 0;

stHead.pNext = &stHead;

stHead.pPre = &stHead;

int iCount = 0;

system("pause > 0");

return 0;

}

  • 初始化头节点 stHead,数据域 iData 设为 0。
  • pNextpPre 均指向自身,形成一个环状结构。

二、添加节点

1、尾添加
代码:

void AddToEnd(struct Node* stHead, int* iCount, int iData)//尾添加

{

//参数合法性检测

if (NULL == stHead)

return;

//创建节点

struct Node* pTemp = (struct Node*)malloc(sizeof(struct Node));

if (NULL == pTemp)

return;

//节点赋值

pTemp->iData = iData;

pTemp->pNext = NULL;

pTemp->pPre = NULL;

//将节点连上去

//先连,将新节点接在指定位置上

pTemp->pNext = stHead;

pTemp->pPre = stHead->pPre;

//后断

stHead->pPre->pNext = pTemp;

stHead->pPre = pTemp;

//数量++

*iCount += 1;

}

实现双向循环链表的尾部节点添加操作。参数包括链表头节点指针stHead、节点计数器指针iCount和待插入数据iData

步骤:

参数合法性检测

检查链表头节点是否为空指针,若为空直接返回,避免非法访问。

新节点创建与初始化

动态分配新节点内存并检查分配结果,若分配失败直接返回,初始化新节点的数据和指针域。

链表连接逻辑

将新节点插入到尾节点位置:

先将新节点接在指定位置,然后断开原尾节点和头节点的连接。

必须先断开原尾节点指向头节点,再断开头节点指向原尾节点。

  1. 新节点前驱指向尾节点:pTemp->pPre = stHead->pPre

  2. 新节点后继指向头节点:pTemp->pNext = stHead

  3. 原尾节点后继指向新节点:stHead->pPre->pNext = pTemp

  4. 头节点前驱指向新节点:stHead->pPre = pTemp

节点计数更新

通过指针修改外部计数器 *iCount += 1。

2、头添加
代码:

void AddToHead(struct Node* stHead, int* iCount, int iData)//头添加

{

//参数合法性检测

if (NULL == stHead)

return;

//创建节点

struct Node* pTemp = (struct Node*)malloc(sizeof(struct Node));

if (NULL == pTemp)

return;

//节点赋值

pTemp->iData = iData;

pTemp->pNext = NULL;

pTemp->pPre = NULL;

//链接

//先连

pTemp->pPre = stHead;

pTemp->pNext = stHead->pNext;

//后断

stHead->pNext->pPre = pTemp;

stHead->pNext = pTemp;

//数量++

*iCount += 1;

}

实现双向链表的头部插入操作,参数包括链表头节点指针stHead、节点计数器指针iCount以及待插入数据iData

步骤:

参数合法性检测

检查链表头节点是否为空指针,若为空直接返回,避免非法访问。

新节点创建与初始化

动态分配新节点内存并检查分配结果,若分配失败直接返回,初始化新节点的数据和指针域。

链表插入操作

先将新节点接在指定位置,然后断开头节点和原第一个节点的连接。

必须先断开原第一个节点指向头节点,再断开头节点指向原第一个节点。

  1. 新节点前驱指向头节点:pTemp->pPre = stHead

  2. 新节点前驱指向原第一个节点:pTemp->pNext = stHead->pNext

  3. 原第一个节点后继指向新节点:stHead->pPre->pNext = pTemp

  4. 头节点后继指向新节点:stHead->pPre = pTemp

节点计数更新

通过指针修改外部计数器 *iCount += 1。

三、遍历链表

代码:

void Look(struct Node* stHead, int iCount)//遍历

{

//参数合法性检测

if (NULL == stHead || stHead->pNext == stHead)

return;

//循环遍历

printf("节点个数共有%d个: ", iCount);

struct Node* pTemp = stHead->pNext;

while (pTemp != stHead)

{

printf("%d ", pTemp->iData);

pTemp = pTemp->pNext;

}

putchar('\n');

}

实现了一个循环链表的遍历功能,输出链表中所有节点的数据值及节点个数。

步骤:

参数合法性检查

确认头节点不为空且链表非空(头节点的下一个节点不是自己)

循环遍历

遍历过程从第一个有效节点开始(stHead->pNext),通过while循环依次访问每个节点,每个节点的数据通过printf输出,直到再次遇到头节点为止,最后用putchar输出换行符

调用:

先尾添加,后头添加。

AddToEnd(&stHead, &iCount, 4);

AddToEnd(&stHead, &iCount, 5);

AddToEnd(&stHead, &iCount, 6);

Look(&stHead, iCount);

AddToHead(&stHead, &iCount, 1);

AddToHead(&stHead, &iCount, 2);

AddToHead(&stHead, &iCount, 3);

Look(&stHead, iCount);

相关推荐
tobias.b13 小时前
计算机基础知识-数据结构
java·数据结构·考研
不想看见40415 小时前
Valid Parentheses栈和队列--力扣101算法题解笔记
开发语言·数据结构·c++
计算机安禾15 小时前
【C语言程序设计】第37篇:链表数据结构(一):单向链表的实现
c语言·开发语言·数据结构·c++·算法·链表·蓝桥杯
皮卡狮16 小时前
高阶数据结构:AVL树
数据结构·算法
不要秃头的小孩17 小时前
50. 随机数排序
数据结构·python·算法
故事和你9118 小时前
sdut-python-实验四-python序列结构(21-27)
大数据·开发语言·数据结构·python·算法
丶小鱼丶18 小时前
数据结构和算法之【栈】
java·数据结构
不要秃头的小孩18 小时前
力扣刷题——111.二叉树的最小深度
数据结构·python·算法·leetcode
散峰而望18 小时前
【基础算法】从入门到实战:递归型枚举与回溯剪枝,暴力搜索的初级优化指南
数据结构·c++·后端·算法·机器学习·github·剪枝
elseif12320 小时前
CSP-S提高级大纲
开发语言·数据结构·c++·笔记·算法·大纲·考纲