【数据结构基础_双向循环链表(有空头)_(C语言实现)】

双向循环链表(含空头)

双向循环链表呢,就是将尾结点指向头结点形成一个环形

本文主要是针对双向循环链表进行增、删、改、查操作

创建一个结构体当做节点
struct Node
{
	int iData;
	struct Node* pNext;
	struct Node* pPre;
};

定义空头

	//空头
	struct Node stHead;
	stHead.iData = 0;
	stHead.pNext = &stHead;
	stHead.pPre = &stHead;
	int iCount = 0;

此处的pNext和pPre都指向空头,当然也可以置空,不过为了方便操作,就不置空了,iCount为计数器(记录节点的个数)

增加:1.尾添加
void AddToEnd(struct Node* stHead, int* iCount, int iData)
{
	//参数合法性检测
	if (NULL == stHead)
		return;
	//创建节点
	struct Node* pTemp = (struct Node*)malloc(sizeof(struct Node));
	//节点赋值
	if (pTemp == NULL)
		return;
	pTemp->iData = iData;
	pTemp->pNext = NULL;
	pTemp->pPre = NULL;
	//将节点连上去
	//先连 将新节点连在指定位置
	pTemp->pPre = stHead->pPre;
	pTemp->pNext = stHead;
	//后断
	stHead->pPre->pNext = pTemp;
	stHead->pPre = pTemp;
	//数量自加
	(*iCount) += 1;
}
增加:2.头添加
void AddToHead(struct Node* stHead, int* iCount, int iData)
{
	//参数合法性检测
	if (NULL == stHead)
		return;
	struct Node* pTemp = CreateNode();
	if (pTemp == NULL)
		return;
	pTemp->iData = iData;
	//链接
	//先连
	pTemp->pPre = stHead;
	pTemp->pNext = stHead->pNext;
	//后断
	stHead->pNext->pPre = pTemp;
	stHead->pNext = pTemp;
	//数量自加
	(*iCount) += 1;
}
遍历链表

由于是双向循环链表,所以最后节点指向空头,遍历条件为 (pTemp != stHead)

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');
}
释放链表
void FreeList(struct Node* stHead, int* iCount)
{
	//参数合法性检测
	if (NULL == stHead || stHead->pNext == stHead)
		return;
	//循环遍历
	struct Node* pTemp = NULL;
	pTemp = stHead->pNext;
	if (pTemp == NULL)
		return;
	while (pTemp != stHead)
	{
		//记录
		struct Node* pT = NULL;
		pT = pTemp;
		if (pT == NULL)
			return;
		//向下走
		pTemp = pTemp->pNext;
		//释放记录
		free(pT);
	}
	//数据清0
	*iCount = 0;
	stHead->pNext = stHead;
	stHead->pPre = stHead;
}

释放链表记得指针要置空哈
并且计数器置零

查找:1.根据下标查询

由于每次都会用到创建节点代码,避免重复和浪费,咱们创建一个专门的函数

struct Node* CreateNode()
{
	//创建节点
	struct Node* pTemp = (struct Node*)malloc(sizeof(struct Node));
	//节点赋值
	if (pTemp == NULL)
		return NULL;
	pTemp->iData = 0;
	pTemp->pNext = NULL;
	pTemp->pPre = NULL;
	return pTemp;
}
struct Node* GetNodeByIndex(struct Node* stHead, int iCount, int iIndex)
{
	//参数合法性检测
	if (NULL == stHead || iCount <= 0 || iIndex < 0 || iIndex >= iCount)
		return NULL;
	struct Node* pTemp = stHead->pNext;
	if (pTemp == NULL)
		return NULL;
	for (int i = 0; i < iIndex; i++)
	{
		pTemp = pTemp->pNext;
	}
	return pTemp;
}
查找:2.根据数值查询
struct Node* GetNodeByData(struct Node* stHead, int iData)
{
	//参数合法性检测
	if (NULL == stHead || NULL == stHead->pNext)
		return NULL;
	struct Node* pTemp = stHead->pNext;
	if (pTemp == NULL)
		return NULL;
	while (pTemp != stHead)
	{
		if (pTemp->iData == iData)
			return pTemp;
		pTemp = pTemp->pNext;
	}
	return NULL;
}
升级版添加:1.指定的下标位置添加
void InsertByIndex(struct Node* stHead, int* iCount, int iIndex, int iData)
{
	//参数合法性检测
	if (stHead == NULL || *iCount < 0 || iIndex < 0 || iIndex > *iCount)
		return;
	//1.尾添加
	if (iIndex == *iCount)
		AddToEnd(stHead, iCount, iData);
	else
	{
		//找位置
		struct Node* pTemp = GetNodeByIndex(stHead, *iCount, iIndex);
		if (pTemp == NULL)
			return;
		//创建节点
		struct Node* pT = (struct Node*)malloc(sizeof(struct Node));
		if (pT == NULL)
			return;
		pT->iData = iData;
		pT->pNext = NULL;
		pT->pPre = NULL;
		//链接
		//先连
		pT->pNext = pTemp;
		pT->pPre = pTemp->pPre;
		//后断
		pTemp->pPre->pNext = pT;
		pTemp->pPre = pT;
		//数量自加
		(*iCount) += 1;
	}
}
升级版添加:2.指定数据位置添加节点
void InsertByData(struct Node* stHead, int* iCount, int iValue, int iData)
{
	//参数合法性检测
	if (stHead == NULL || *iCount <= 0)
		return;
	//循环找节点
	struct Node* pTemp = GetNodeByData(stHead, iValue);
	if (pTemp == NULL)
		return;
	//创建节点
	struct Node* pT = (struct Node*)malloc(sizeof(struct Node));
	if (pT == NULL)
		return;
	pT->iData = iData;
	pT->pNext = NULL;
	pT->pPre = NULL;
	//链接
	//先连
	pT->pNext = pTemp;
	pT->pPre = pTemp->pPre;
	//后断
	pTemp->pPre->pNext = pT;
	pTemp->pPre = pT;
	//数量自加
	(*iCount) += 1;
}
升级版添加:3.在指定下标位置插入N个节点
void InsertSomeByIndex(struct Node* stHead, int* iCount, int iIndex, int iData, int iNodeCount)
{
	//参数合法性检测
	if (stHead == NULL || *iCount < 0 || iIndex < 0 || iIndex > *iCount)
		return;
	for (int i = 0; i < iNodeCount; i++)
	{
		InsertByIndex(stHead, iCount, iIndex, iData);
	}
}
删除:1.根据下标删除指定节点
void DeleteByIndex(struct Node* stHead, int* iCount, int iIndex)
{
	//参数合法性检测
	if (stHead == NULL || *iCount <= 0 || iIndex < 0 || iIndex >= *iCount)
		return;
	//循环找节点
	struct Node* pTemp = GetNodeByIndex(stHead, *iCount, iIndex);
	if (pTemp == NULL)
		return;
	//删除
	pTemp->pPre->pNext = pTemp->pNext;
	pTemp->pNext->pPre = pTemp->pPre;
	free(pTemp);
	//数量--
	(*iCount)--;
}
删除:2.根据下标删除一段节点
void DeleteSomeByIndex(struct Node* stHead, int* iCount, int iIndex1, int iIndex2)
{
	//参数合法性检测
	if (stHead == NULL || *iCount <= 0 || iIndex1 < 0 || iIndex2 >= *iCount)
		return;
	删除下标之间节点
	//for (int i = iIndex1; i <= iIndex2; i++)
	//{
	//	DeleteByIndex(stHead, iCount, iIndex1 + 1);
	//	iIndex2--;
	//}
	//删除下标之间节点(包括下标处节点)
	for (int i = iIndex1; i <= iIndex2 + i - 1; i++)
	{
		DeleteByIndex(stHead, iCount, iIndex1);
		iIndex2--;
	}
}
删除:3.根据数据删除所有一样的数据
void DeleteByData(struct Node* stHead, int* iCount, int iData)
{
	//参数合法性检测
	if (stHead == NULL || *iCount <= 0)
		return;
	while (1)
	{
		//找节点
		struct Node* pTemp = GetNodeByData(stHead, iData);
		if (pTemp == NULL)
			return;
		//删除
		pTemp->pPre->pNext = pTemp->pNext;
		pTemp->pNext->pPre = pTemp->pPre;
		free(pTemp);
		//数量--
		(*iCount)--;
	}
}

有些简单的大家看前面那个双向链表操作基本上一样,欢迎大家指正错误~

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千北@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值