C语言实现双向循环链表

C语言实现双向循环链表(附有源码)

一、双向循环链表的结构

C语言实现双向循环链表_第1张图片

以三个节点为例,双向循环链表结构如上图所示。每个节点都分为数据域和指针域,数据域是存储数据的;指针域存储前向指针和后向指针,前向指针指向该节点的上一个节点,后向指针指向该节点的下一个节点。循环链表是指首尾要相连,即第一个节点的前向指针指向最后一个节点,最后一个节点的后向指针指向第一个节点,形成一个环。

二、实现一个双向循环链表

1. 首先创建一个双向循环链表的节点
typedef struct Node
{
	int data;
	struct Node *Next;
	struct Node *Pre;
}NODE, *HNODE;
2. 创建链表的菜单项、初始化、增、删、改、查等函数
//操作菜单
void menuDisplay(){

	printf("菜单\n");
	printf("*****************************\n");
	printf("1、进入系统	0\n");
	printf("2、创建链表	1\n");
	printf("3、添加节点	2\n");
	printf("4、删除节点	3\n");
	printf("5、更改节点	4\n");
	printf("6、查找数据	5\n");
	printf("7、打印链表	6\n");
	printf("8、删除链表	7\n");
	printf("9、退出系统	8\n");
	printf("*****************************\n");
}
//创建双向循环链表
HNode CreateLinkNode(void)
{
	int i, length = 0, data = 0;
	HNode p_new = NULL, pTail = NULL;
	HNode head = (HNode)malloc(sizeof(NODE));
 
	if (NULL == head)
	{
		printf("内存分配失败!\n");
		exit(EXIT_FAILURE);
	}
	head->data = 0;
	head->next= head;
	head->pre= head;
	pTail = head;
 
	printf("请输入想要创建链表的长度:");
	scanf("%d", &length);
 
	for (i=1; i<length+1; i++)
	{
		p_new = (HNode)malloc(sizeof(NODE));
 
		if (NULL == p_new)
		{
			printf("内存分配失败!\n");
			exit(EXIT_FAILURE);
		}
 
		printf("请输入第%d个节点元素值:", i);
		scanf("%d", &data);
 
		p_new->data = data;
		p_new->pre= pTail;
		p_new->next= head;
		pTail->next= p_new;
		head->pre= p_new;
		pTail = p_new;
	}
	return head;
}

//打印链表
void PrintfLinkNode(HNode head)
{
	HNode pt = head->next;
 
	printf("链表打印结果为:");
	while (pt != head)
	{
		printf("%d ", pt->data);
		pt = pt->next;
	}
	putchar('\n');
}
//查找数据
void searchLinkNode(HNode head, int data){
	HNode pt = head->next;
	int i =1 ,m=0;
 
	while (pt != head)
	{
		if(pt->data==data){
			printf("第%d个位置上为:%d\n",i,pt->data);
			m++;
		}
		pt = pt->next;
		i++;
	}
	if(m==0){
		printf("没有找到该数据!");
	}else{
		printf("一共找到%d个数据",m);
	}
	m=0;
	putchar('\n');

}
 
//判断链表是否为空
int IsEmpty(HNode head)
{
	HNode pt = head->next;
 
	if (pt == head)
		return 1;
	else
		return 0;
}
 
//计算链表长度
int LinkNodeLength(HNode head)
{
	int length = 0;
	HNode pt = head->next;
 
	while (pt != head)
	{
		length++;
		pt = pt->next;
	}
	return length;
}
//插入节点
int InsertLinkNode(HNode head, int pos, int data)
{
	HNode p_new = NULL, pt = NULL;
	if (pos > 0 && pos < LinkNodeLength(head) + 2)
	{
		p_new = (HNode)malloc(sizeof(NODE));
 
		if (NULL == p_new)
		{
			printf("内存分配失败!\n");
			exit(EXIT_FAILURE);
		}
 
		while (1)
		{
			pos--;
			if (0 == pos)
				break;
			head = head->next;
		}
		
		p_new->data = data;
		pt = head->next;
		p_new->next= pt;
		p_new->pre= head;
		head->next= p_new;
		pt->pre= p_new;
		
		return 1;
	}
	else
		return 0;
}

//删除节点
int	DeleteLinkNode(HNode head, int pos)
{
	HNode pt = NULL;
	if (pos > 0 && pos < LinkNodeLength(head) + 1)
	{
		while (1)
		{
			pos--;
			if (0 == pos)
				break;
			head = head->next;
		}
		pt = head->next->next;
		free(head->next);
		head->next= pt;
		pt->pre= head;
 
		return 1;
	}
	else
		return 0;	
}
 //更改链表中某节点的值
int AlterEleDbCcLinkList(HNode head, int location, int value){
	int i = 0;
	DeleteLinkNode(head, location);
	i = InsertLinkNode(head, location,value);
	return i;
}
//删除整个链表,释放内存空间
void FreeMemory(HNode *head)
{
	HNode pt = NULL;
	while (*head != NULL)
	{
		pt = (*head)->next->next;
 
 
		if ((*head)->next== *head)
		{
			free(*head);
			*head = NULL;
		}
		else
		{
			free((*head)->next);
			(*head)->next= pt;
			pt->pre= *head;
		}
	}
}
3.主函数
int main(void)
{
	int flag = 0, length = 0;
	int position = 0, value = 0,data=0,length2=0,flag2=0;
	HNode head = NULL;
	int menuNumber,input=-1;
	menuDisplay();
	while(1){
		scanf("%d",&input);
		if(input==0){
				printf("您已进入系统!\n");
		
		while(1){
			printf("请输入与操作对应的数字:");
			scanf("%d",&menuNumber);
		if(menuNumber==1){
			flag2=1;
			head = CreateLinkNode();
			flag = IsEmpty(head);
			if (flag)
				printf("双向循环链表为空!\n");
			else
			{
				length = LinkNodeLength(head);
				printf("双向循环链表的长度为:%d\n", length);
				PrintfLinkNode(head);
			}
		}
		if(flag2!=0){
			if(menuNumber==2){
				length2 = LinkNodeLength(head);
				if(length2==0){
					printf("双向循环链表为空!\n");
				
				}else{
						printf("请输入要插入节点的位置和元素值(两个数用空格隔开):");
					scanf("%d %d", &position, &value);
					flag = InsertLinkNode(head, position, value);
					if (flag)
					{
						printf("插入节点成功!\n");
						PrintfLinkNode(head);
					}	
					else
						printf("插入节点失败!\n");
				}

			}
			if(menuNumber==3){
						flag = IsEmpty(head);
				if (flag)
					printf("双向循环链表为空,不能进行删除操作!\n");
				else
				{
					printf("请输入要删除节点的位置:");
					scanf("%d", &position);
					flag = DeleteLinkNode(head, position);
					if (flag)
					{
						printf("删除节点成功!\n");
						PrintfLinkNode(head);
					}	
					else
						printf("删除节点失败!\n");
				}
			}
			if(menuNumber==4){
				printf("请输入要更改节点的位置和元素值(两个数用空格隔开):");
				scanf("%d %d", &position, &value);
					flag = AlterEleDbCcLinkList(head, position, value);
				if (flag)
				{
					printf("更改节点成功!\n");
					PrintfLinkNode(head);
				}	
				else
					printf("更改节点失败!\n");
			
			}
			if(menuNumber==5){
					printf("请输入要查找的数据:");
					scanf("%d", &data);
					searchLinkNode(head,data);

			}
			if(menuNumber==6){
							
			PrintfLinkNode(head);
			
			}
			if(menuNumber==7){
							
				FreeMemory(&head);
				if (NULL == head)
					printf("已成功删除双向循环链表,释放内存完成!\n");
				else
					printf("删除双向循环链表失败,释放内存未完成!\n");
			
			}
			if(menuNumber==8){
				printf("您已退出系统!\n");
				menuDisplay();
				break;
			}
		}else{
		printf("请先创建一个链表!\n");

		
		}
		
	}	
		}
	
	}

	return 0;
}

4.结果展示

结果如图:
C语言实现双向循环链表_第2张图片

程序源码:c语言双向循环链表

提取码:w594

你可能感兴趣的:(链表)