C语言: 链表 -- (环形双链表)

环形双链表示意图:

Dome:

#pragma once
#include<stdio.h>
#include<stdlib.h>


/*节点数据结构*/
typedef struct node
{
	int data;//值
	struct node* pPer;//上一节点
	struct node* pNext;//下一节点
}NODE,*PNODE;

/*双链表数结构*/
typedef struct List
{
	NODE* pHead;//链表头指针
	NODE* pTail;//链表尾指针
}LIST;

//初始化
void init(LIST* vPtr);

//尾部添加节点数据
void add_data_back(LIST* vPtr, int data);

//头部插入数据
void add_data_head(LIST* vPtr, int data);

//查找数据
PNODE find(LIST* vPtr, int data);

//修改数据
void modification(LIST* vPtr, int old_data, int new_Data);

//根据查找数据位置插入新数据
void insert_data(LIST* vPtr, int find_data, int new_Data);

//删除数据
void delete_Data(LIST* vPtr, int data);


//显示所有数据
void show_all(LIST* vPtr);

#include"list.h"

//初始化
void init(LIST* vPtr)
{
	vPtr->pHead = vPtr->pTail = NULL;
}

//尾部添加节点数据
void add_data_back(LIST* vPtr, int data)
{
	if (vPtr == NULL)
	{
		return;
	}
	PNODE vPtrNew = malloc(sizeof(NODE));
	if (vPtrNew != NULL)
	{
		vPtrNew->data = data;
		vPtrNew->pNext = NULL;
		vPtrNew->pPer = NULL;

		if (vPtr->pHead == NULL && vPtr->pTail == NULL)//没有节点
		{
			vPtr->pHead = vPtr->pTail = vPtrNew;
			vPtrNew->pNext = vPtrNew->pPer = vPtrNew;
		}
		else if(vPtr->pHead==vPtr->pTail)//单个节点
		{
			vPtr->pHead->pNext = vPtr->pHead->pPer = vPtrNew; //头节点前驱和后驱都等于新节点
			vPtrNew->pNext = vPtrNew->pPer = vPtr->pHead;//新节点的前驱和后驱都等于头节点
			vPtr->pTail = vPtrNew;//尾部指向新节点
		}
		else//多个节点
		{
			//新节点的前驱和后驱分别指向 链表结构的 尾部节点 和头部 节点
			vPtrNew->pPer = vPtr->pTail;
			vPtrNew->pNext = vPtr->pHead;


			vPtr->pTail->pNext = vPtrNew;//链表结构的 尾部后驱直指向新节点
			vPtr->pHead->pPer = vPtrNew;//链表结构的 头部前驱直指向新节点


			vPtr->pTail = vPtrNew;//尾部指向新节点
		}
	}
}

//显示所有数据
void show_all(LIST* vPtr)
{
	if (vPtr->pHead == NULL && vPtr->pTail == NULL)//没有节点
	{
		return;
	}
	else if (vPtr->pHead == vPtr->pTail)//单个节点
	{
		printf("值:【%d】;前驱指针:【%p】;后驱指针:【%p】;节点:【%p】;头指针:【%p】;尾指针:【%p】\n", vPtr->pHead->data, vPtr->pHead->pNext, vPtr->pHead->pPer,vPtr, vPtr->pHead, vPtr->pTail);
	}
	else//多个节点
	{
		PNODE pnd = vPtr->pHead;
		for (; pnd->pNext != vPtr->pHead; pnd = pnd->pNext)
		{
			printf("值:【%d】;前驱指针:【%p】;后驱指针:【%p】;节点:【%p】;头指针:【%p】;尾指针:【%p】\n", pnd->data, pnd->pNext, pnd->pPer, pnd,vPtr->pHead, vPtr->pTail);
			printf("\n");
		}
		printf("值:【%d】;前驱指针:【%p】;后驱指针:【%p】;节点:【%p】;头指针:【%p】;尾指针:【%p】\n", pnd->data, pnd->pNext, pnd->pPer, pnd,vPtr->pHead, vPtr->pTail);
	}
}

//头部插入数据
void add_data_head(LIST* vPtr, int data)
{
	if (vPtr == NULL)
	{
		return;
	}
	PNODE vPtrNew = malloc(sizeof(NODE));
	if (vPtrNew != NULL)
	{
		vPtrNew->data = data;
		vPtrNew->pNext = NULL;
		vPtrNew->pPer = NULL;

		if (vPtr->pHead == NULL && vPtr->pTail == NULL)//没有节点
		{
			vPtr->pHead = vPtr->pTail = vPtrNew;
			vPtrNew->pNext = vPtrNew->pPer = vPtrNew;
		}
		else if (vPtr->pHead == vPtr->pTail)//单个节点
		{
			vPtr->pHead->pNext = vPtr->pHead->pPer = vPtrNew;//原头节点的前驱和后驱直向新节点
			vPtrNew->pNext = vPtrNew->pPer = vPtr->pHead;//新节点的前驱和后驱指向原头节点

			vPtr->pHead = vPtrNew;//头节点指向新节点
		}
		else//多个节点
		{
			vPtrNew->pNext = vPtr->pHead;//新节点的后驱指向原头节点
			vPtrNew->pPer = vPtr->pTail;//新节点的前驱指向原尾节点

			vPtr->pHead->pPer = vPtrNew;//原 头节点的前驱 指向 新节点
			vPtr->pTail->pNext = vPtrNew;//原 尾节点的后驱 指向 新节点

			vPtr->pHead = vPtrNew;//头节点指向新节点
		}
	}
}

//查找数据
PNODE find(LIST* vPtr, int data)
{
	if (vPtr->pHead == NULL && vPtr->pTail == NULL)//没有节点
	{
		return NULL;
	}
	else if (vPtr->pHead == vPtr->pTail)//单个节点
	{
		PNODE pnd = vPtr->pHead;
		if (pnd->data == data)
		{
			return pnd;
		}
		else
		{
			return NULL;
		}
	}
	else//多个节点
	{
		PNODE pnd = vPtr->pHead;
		for (; pnd->pNext != vPtr->pHead; pnd = pnd->pNext)
		{
			if (pnd->data == data)
			{
				return pnd;
			}
		}
		if (pnd->data == data)
		{
			return pnd;
		}
		else
		{
			return NULL;
		}
		
	}
}

//修改数据
void modification(LIST* vPtr, int old_data, int new_Data)
{
	if (vPtr->pHead == NULL && vPtr->pTail == NULL)//没有节点
	{
		return;
	}
	else if (vPtr->pHead == vPtr->pTail)//单个节点
	{
		PNODE pnd = vPtr->pHead;
		if (pnd->data == old_data)
		{
			pnd->data = new_Data;
		}
	}
	else//多个节点
	{
		PNODE pnd = vPtr->pHead;
		for (; pnd->pNext != vPtr->pHead; pnd = pnd->pNext)
		{
			if (pnd->data == old_data)
			{
				pnd->data = new_Data;
			}
		}
		if (pnd->data == old_data)
		{
			pnd->data = new_Data;
		}
	}
}

//根据查找数据位置的前面插入新数据
void insert_data(LIST* vPtr, int find_data, int new_Data)
{
	if (vPtr == NULL)
	{
		return;
	}
	else
	{
		PNODE pnd = NULL;
		pnd = vPtr->pHead;
		while (pnd->pNext != vPtr->pHead)
		{
			if (pnd->data == find_data)
			{
				break;
			}
			else
			{
				pnd = pnd->pNext;
			}
		}
		if (pnd->data != find_data)//没有找到数据
		{
			return;
		}
		else
		{
			PNODE vPtrNew = malloc(sizeof(NODE));
			if (vPtrNew != NULL)
			{
				vPtrNew->data = new_Data;
				vPtrNew->pNext = NULL;
				vPtrNew->pPer = NULL;
				if (vPtr->pHead == pnd && vPtr->pTail == pnd)//链表只有单个节点
				{
					vPtr->pHead->pNext = vPtr->pHead->pPer = vPtrNew;//原头节点的前驱和后驱直向新节点
					vPtrNew->pNext = vPtrNew->pPer = vPtr->pHead;//新节点的前驱和后驱指向原头节点 [vPtr->pHead = pnd]

					vPtr->pHead = vPtrNew;//头节点指向新节点
				}
				else if (vPtr->pHead == pnd && vPtr->pTail != pnd)//头部节点
				{
					pnd->pPer = vPtrNew; // [vPtr->pHead = pnd]
					vPtr->pTail->pNext = vPtrNew;
					vPtrNew->pNext = pnd;
					vPtrNew->pPer = vPtr->pTail;
					
					vPtr->pHead = vPtrNew;
				}
				else//中间节点
				{
					vPtrNew->pPer = pnd->pPer;
					vPtrNew->pNext = pnd;
					//下面两部不要颠倒,
					pnd->pPer->pNext = vPtrNew;
					pnd->pPer = vPtrNew;
					
				}
			}
		}
	}
}

//删除数据
void delete_Data(LIST* vPtr, int data)
{
	if (vPtr == NULL)
	{
		return;
	}
	else
	{
		PNODE pnd = NULL;
		pnd = vPtr->pHead;
		while (pnd->pNext!=vPtr->pHead)
		{
			if (pnd->data == data)
			{
				break;
			}
			else
			{
				pnd = pnd->pNext;
			}
		}
		if (pnd->data != data)//没有找到数据
		{
			return;
		}
		else
		{
			if (vPtr->pHead == pnd && vPtr->pTail == pnd)//链表只有单个节点
			{
				free(vPtr->pHead);
				vPtr->pHead = NULL;
				vPtr->pTail = NULL;
			}
			else if(vPtr->pHead == pnd && vPtr->pTail != pnd)//多节点删除头部节点
			{
				pnd->pNext->pPer = vPtr->pTail;//第二节点的前驱指向原链表尾部指针
				pnd->pPer->pNext = pnd->pNext;//尾节点的后驱指向 第二节点
				//vPtr->pTail->pNext = vPtr->pHead->pNext;
				//vPtr->pHead->pPer->pNext= vPtr->pHead->pNext;

				vPtr->pHead = pnd->pNext; //头节点指向第二节点
				free(pnd);
				

			}
			else if (vPtr->pHead != pnd && vPtr->pTail == pnd)//多节点删除尾部节点
			{
				pnd->pNext->pPer = pnd->pPer;//头部节点的前驱 指向倒数第二节点
				pnd->pPer->pNext = vPtr->pHead;//倒数第二节点 的后驱指向 头节点
				vPtr->pTail = pnd->pPer;//尾部节点 指向倒数第二节点

				free(pnd);
			}
			else//多节点删除中间节点
			{
				pnd->pPer->pNext = pnd->pNext;//指定节点的 前面节点的后驱 指向 指定节点的 后面节点 (跳过指定节点)
				pnd->pNext->pPer = pnd->pPer;//指定节点的 后面节点的前驱 指向 指定节点的 前面节点 (跳过指定节点)

				free(pnd);
			}
		}
	}
}

调用示例:


#include"list.h"



void main()
{
	LIST list;
	init(&list);
	for (size_t i = 0; i < 10; i++)
	{
		add_data_back(&list, i);
	}
	printf("\n 显示所有数据 :\n");
	show_all(&list);

	printf("\n 插入指定位置数据 :\n");

	for (size_t i = 0; i < 4; i++)
	{
		insert_data(&list, i,i+100);
	}

	show_all(&list);

	printf("\n 修改指定数据 :\n");
	modification(&list, 9, 999);
	modification(&list, 8, 888);
	show_all(&list);

	printf("\n删除 节点节点数据 5 和节点数据 7 :\n");
	delete_Data(&list, 5);


	delete_Data(&list, 7);

	
	show_all(&list);



	system("pause");
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值