循环链表(包括循环单链表、循环双链表)

一、循环单链表与循环双链表的对比

二、循环单链表

List.h

cpp 复制代码
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>

// 实现带头结点的循环单链表

// 定义结点的结构
typedef int ElemType;
typedef struct LNode
{
	ElemType data;
	struct LNode* next;
} LNode, * LinkList;


// 循环单链表的初始化
bool InitList(LinkList& L); // L是头结点的地址的别名

// 判断循环单链表是否为空(即链表中是否存储了有效数据),若为空返回true,否则返回false
bool Empty(LinkList L); // L接收头结点的地址

// 判断p指向的结点是否为循环单链表的尾结点,如果是返回true,否则返回false
bool isTail(LinkList L, LNode* p); // L接收头结点的地址

List.cpp

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include"List.h"
// 循环单链表的初始化
bool InitList(LinkList& L) // L是头结点的地址的别名
{
	// 开辟头结点的空间
	L = (LNode*)malloc(sizeof(LNode));
	if (L == NULL) // 表示头结点的空间开辟失败
		return false;
	L->next = L; // 为了构成一个环,头结点的next指针需要指向头结点,
	return true;
}

// 判断循环单链表是否为空(即链表中是否存储了有效数据),若为空返回true,否则返回false
bool Empty(LinkList L) // L接收头结点的地址
{
	if (L->next == L) // 当头结点的next指针指向头结点时,表示链表为空
		return true;
	else
		return false;
}

// 判断p指向的结点是否为循环单链表的尾结点,如果是返回true,否则返回false
bool isTail(LinkList L, LNode* p) // L接收头结点的地址
{
	if (p->next == L) //循环单链表中,尾结点的next指针指向头结点
		return true;
	else
		return false;
}

Test.cpp

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include"List.h"


void test()
{
	// 创建一个头指针(即指向头结点的指针)
	LNode* p = NULL;
	// 测试循环双链表的初始化
	InitList(p);
}

int main()
{
	test();
	return 0;
}

三、循环双链表

List.h

cpp 复制代码
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
// 实现带头结点的循环双链表

typedef int ElemType;
typedef struct DNode
{
	ElemType data; // 结点中的数据域,存储一个整数
	struct DNode* prior; // 指向前一个结点
	struct DNode* next; // 指向后一个结点
}DNode, * DLinkList;
// 将struct DNode重命名为DNode,将struct DNode*重命名为DLinkList
// 因此DNode*与DLinkList完全等价


// 循环双链表的初始化
bool InitDLinkList(DLinkList& L); // L是头结点的地址的别名

// 判断循环双链表是否为空(即链表中是否存储了有效数据)。若为空返回true,否则返回false
bool Empty(DLinkList L); // L接收头结点的地址

// 判断p指向的结点是否为尾结点。若是尾结点返回true,否则返回false
bool isTail(DLinkList L, DNode* p);

// 在p指向的结点后插入s指向的结点
bool InsertNextDNode(DNode* p, DNode* s);

// 删除p指向的结点的后面一个结点
bool DeleteNextDNode(DNode* p);

List.cpp

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include"List.h"
// 循环双链表的初始化
bool InitDLinkList(DLinkList& L) // L是头结点的地址的别名
{
	// 开辟头结点的空间
	L = (DNode*)malloc(sizeof(DNode)); // L指向头结点
	if (L == NULL) // 表示头结点的空间开辟失败
		return false;
	L->prior = L->next = L; // 为了构成一个环状,需要让头结点的next指针与prior指针均指向头结点
	return true;
}

// 判断循环双链表是否为空(即链表中是否存储了有效数据)。若为空返回true,否则返回false
bool Empty(DLinkList L) // L接收头结点的地址
{
	if (L->next = L) // 当头结点的next指针指向头结点时,表示循环双链表为空
		return true;
	else
		return false;
}

// 判断p指向的结点是否为尾结点。若是尾结点返回true,否则返回false
bool isTail(DLinkList L, DNode* p)
{
	if (p->next == L) // 尾结点的next指针指向头结点
		return true;
	else
		return false;
}


// 在p指向的结点后插入s指向的结点
bool InsertNextDNode(DNode* p, DNode* s)
{
	if (p == NULL || s == NULL) // 当p或s指向的结点无效时,无法指向删除操作
		return false;
	s->next = p->next;
	p->next->prior = s; // 如果实现的是双链表,这句代码在尾结点后插入新结点时,会导致对空指针的解引用。
	s->prior = p;
	p->next = s;
	return true;
}

// 删除p指向的结点的后面一个结点
bool DeleteNextDNode(DNode* p) // 
{
	if (p == NULL) // 当p指向的结点无效,,不能指向删除操作
		return false;
	DNode* q = p->next; // s指向待删除的结点
	p->next = q->next;
	q->next->prior = p; // 如果实现的是双链表,这句代码在删除尾结点时,会导致对空指针的解引用。
	free(q);
	q = NULL;
	return true;
}

Test.cpp

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include"List.h"
void test()
{
	// 创建一个头指针(即指向头结点的指针)
	DNode* p = NULL;
	// 测试循环双链表的初始化
	InitDLinkList(p);
}

int main()
{
	test();

	return 0;
}
相关推荐
xiangyun617 小时前
【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清
c语言·开发语言·数据结构·c++·算法
xiangyun617 小时前
【408数据结构 06】双链表、循环链表、静态链表
c语言·开发语言·数据结构·c++·算法
OKkankan8 小时前
LangChain 能力详解!:输出解析、RAG、向量数据库与 Retriever 检索器
数据结构·python·langchain·ai应用
蓝速科技8 小时前
便民服务大厅 AI 数字人一体机场景适配与落地指南丨蓝速科技
大数据·网络·数据结构·人工智能·自然语言处理·数据分析·运维开发
xxwxx__9 小时前
C++ AVL 树深度剖析:平衡二叉搜索树原理、源码与面试考点
数据结构·c++
Logic1019 小时前
C语言/数据结构数组题解:数字列表加一(Plus One)——进位处理与数组扩展
c语言·数据结构·模拟·数组·时间复杂度·算法题·进位
xxwxx__12 小时前
C++ STL set 与 map 全套详解:关联式容器、红黑树底层、代码坑点、刷题实战
数据结构·c++
程曦曦13 小时前
MySQL 生产库误删 98 张表后的时间点恢复实战:从 binlog 解析到资金对账
linux·数据结构·其他·算法·ubuntu·运维开发
郝学胜-神的一滴13 小时前
Effective Python 条款 13:善用星号解包,告别下标切片拆分的坑
服务器·开发语言·数据结构·python·程序人生·pycharm
Logic10113 小时前
C语言/数据结构位运算题解:异或XOR找出流水线上的“独特零件编号“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质