欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

双循环链表的初始化、查找、插入、删除、定位等操作C语言数据结构(注释详细)

程序员文章站 2024-03-22 11:42:34
...

用C语言定义双循环链表,分别用函数实现下列功能:
{

  1. 初始化双循环链表;
  2. 定位运算:在带头结点的双循环链表中查找第i个结点的地址;
  3. 查找运算:在带头结点的双循环链表中查找其结点值等于x(x的值自己定义)的结点;
  4. 双循环链表的插入运算:在带头结点的双循环链表中第i个位置插入值为x(x的值自己定义)的新结点;
  5. 双循环链表的删除运算:在带头结点的双循环链表中删除第i个元素;

}

正在学c语言数据结构的同学最好不要照搬,通过注释自己摸索写出属于自己的代码才是最重要的。

话不多说,直接上代码:

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

/********************定义节点*********************/
struct node
{
	int data;//数据区域
	struct node* next;//指针后继区域
	struct node* priv;//指针前驱区域
};

/****************定义双循环链表结构******************/
struct singlelink
{
	struct node* head;//首节点
	struct node* rear;//尾节点
	int length;//双循环链表长度
};

/*****************初始化双循环链表/*****************/
void initlink(struct singlelink* link)
{
	link->head = (struct node*)malloc(sizeof(struct node));//初始化首节点
	link->head->data = 0;//让首元节点的数据域为0
	link->length = 0;
}

/********************插入数据*****************/
int insert(struct singlelink* link, int position, int value)
{
	int i = 0, j = 0;
	struct node* newnode = (struct node*)malloc(sizeof(struct node));
	if (position<0 || position>link->length)//判断输入位置是否合法
	{
		printf("插入的位置超出双循环链表现有范围,请重新输入!\n");
		return;//非法,返回上一步操作
	}
	if (position == 0)//当插入在表头位置时
	{
		newnode->data = value;//将数据赋值给插入的节点的数据区域
		link->head->priv = newnode;//将头节点的直接前驱链接
		newnode->next = link->head;//将头结点的NULL值赋值给插入的节点的指针区域,插入值直接后继连接成功
		link->head->next = newnode;//将插入节点的地址赋值给头节点的指针区域
		newnode->priv = link->head;//将新插入节点的直接前驱链接
	}
	else//当插入在非表头位置时
	{
		struct node* first = link->head->next;//first为当前的节点,link->head->next表示头节点
		while (i != link->length)//循环自增i,直到判断的i不满足条件时,p指向位置值
		{
			++i;//数据不匹配,则移到下一节点继续判断
			if (i == position)//找到数据,直接输出
			{
				printf("查找成功!\n该节点数据为:%d,已在该节点后插入元素%d完成\n", first->data, value);
				break;
			}
			first = first->next;//指针后移一位
			j++;//长度往下判断一位
		}
		newnode->data = value;//将输入的值赋给插入的节点的数据区域
		first->next = newnode;//将插入节点的地址赋值给上一个节点的指针区域
		newnode->priv = first;//将插入节点的直接前继两两链接
		newnode->next = link->head->next;//将连接上一个节点的的地址转接给待插入的节点的指针区域
		link->head->next->priv = newnode;
	}
	printf("插入成功!\n");
	link->length++;//让双循环链表长度+1
	return 1;
}

/********************查找数据**********************/
struct node* find(struct singlelink* link, int position)
{
	int i = 0, j = 0;
	struct node* first = link->head->next;//first为当前的节点
	while (j != link->length)//如果当前的节点没有到结尾,则输出数据
	{
		if (i == position)//找到数据,直接输出
		{
			printf("查找成功!\n该节点数据为:%d\n", first->data);
			return;
		}
		first = first->next;//指针后移一位
		i++;//数据不匹配,则移到下一节点继续判断
		j++;//长度往下判断一位
	}
	printf("找不到该数据,请检查是否存在该数据\n");
	return;//判断完成,仍没有该点,则返回上一步操作
}

/********************删除数据***********************/
void deletelink(struct singlelink* link, int position)
{
	struct node* dele;//定义一个待删除的节点
	struct node* first = link->head->next;//first为当前的节点
	if (position<0 || position>link->length)//判断输入位置是否合法
	{
		printf("删除的位置超出双循环链表现有范围,请重新输入!");
		return;//返回上一步操作
	}
	if (position == 0)//当删除在表头位置时
	{
		dele = link->head;
		link->head = dele->next;
		free(dele);
	}
	else//当删除在非表头位置时
	{
		int i = 0, j = 0;
		while (i != link->length)//循环自增i,直到判断的i不满足条件时,p指向位置值
		{
			++i;//数据不匹配,则移到下一节点继续判断
			first = first->next;//指针后移一位
			if (i == position)//找到数据,直接输出
			{
				first->priv->next = first->next;
				first->next->priv = first->priv;
				printf("查找成功!\n该节点数据为:%d,已删除\n", first->data);
				free(first);
				break;
			}
			j++;//长度往下判断一位
		}
	}
	link->length--;//双循环链表长度减一
}

/************输出双循环链表中的全部数据***************/
void printlink(struct singlelink* link)
{
	int i = 0;
	struct node* current = link->head;//将头节点赋值给当前节点current
	if (link->length == 0)
		printf("该数据表为空,请插入数据后重试!\n");
	while (i != link->length)//当current等于自己current->next->priv时,逻辑非值为0,当其不等于NULL时,逻辑非值为1,一直循环
	{
		printf("[%d]->", current->next->data);
		current = current->next;
		i++;
	}
	printf("\n");
}

/********************主测试程序*********************/
int main()
{
	//定义双循环链表
	int i, j, num, x;
	struct singlelink link;
	initlink(&link);//初始化双循环链表
	while (1)
	{
		printf("\t提示:系统已自动初始化双循环链表\n\n");
		printf("\t\t1.插入节点\n\n");
		printf("\t\t2.删除节点\n\n");
		printf("\t\t3.查找节点数据\n\n");
		printf("\t\t4.输出双循环链表中全部节点数据\n\n");
		printf("\t\t5.清空屏幕内容\n\n");
		printf("\t\t6.退出程序\n\n");
	A:		printf("\n\n请选择功能项,并按回车执行:");
		scanf("%d", &num);
		switch (num)
		{
		case 1:	//插入数据
		{
			printf("请输入想插入的节点位置(请从0开始逐一输入):\n");
			scanf("%d", &i);
			printf("请输入想插入的节点数据为:\n");
			scanf("%d", &x);
			insert(&link, i, x);
			goto A;
		}
		case 2://删除节点
		{
			printf("请输入你要删除的节点位置为:\n");
			scanf("%d", &i);
			deletelink(&link, i);
			printf("删除成功!\n");
			goto A;
		}
		case 3://查找节点数据
		{
			struct node* dat;
			printf("请输入你想找的节点位置为:\n");
			scanf("%d", &x);
			find(&link, x);
			goto A;
		}
		case 4://输出双循环链表中全部节点数据
		{
              printf("该双循环链表的全部节点为:\n");
			printlink(&link);
			goto A;
		}
		case 5://清空屏幕内容
		{
			system("cls");
			break;
		}
		case 6://退出程序
		{
			system("cls");
			printf("退出成功!");
			return;
		}
		}
	}
}