双向循环链表

这篇博客介绍了如何创建和操作双向循环链表,包括链表的创建、判空、长度计算、插入、删除、查找、修改元素等功能。此外,还提供了链表的逆序实现和主函数,用于根据用户输入执行相应操作。代码中详细注释了每个功能的实现步骤,便于理解和学习。
摘要由CSDN通过智能技术生成

双向循环链表,定义了前后指针,而且链表形成一个闭环,实现了从每一个节点都可以遍历到所有节点,并且可以两个方向遍历,我的代码不完善,缺少了遍历方向的选择,怎么判断哪一个方向更加方便等

 

1.双向链表的头文件,先定义要实现的功能,规范好函数的返回值,形参

/*===============================================
*   文件名称:linklist.h
*   创 建 者:     
*   创建日期:2022年07月28日
*   描    述:
================================================*/
#ifndef __LINKLIST__
#define __LINKLIST__

typedef int data_t;

typedef struct node
{
	data_t data;//数据域
	struct node *next;//指针域
	struct node *prior;
}LinkList;

//1.创建头结点;
LinkList *Create_Linklist();

//2.判空
int Linklist_Empty(LinkList *link);

//3.计算表长
int Linklist_Length(LinkList *link);

//4.从表头插入节点(头插法/尾插法)
void Linklist_Insert_Head(LinkList *link,data_t data);
void Linklist_Insert_Front(LinkList *link,data_t data);

//5.按位置插入数据
void Linklist_Insert_Pos(LinkList *link,int pos,data_t data);

//6.按位置删除数据
void Linklist_Delete_Pos(LinkList *link,int pos);

//7.按数据删除
void Linklist_Delete_Data(LinkList *link,data_t data);

//8.按位置查找元素
int Linklist_Find_Pos(LinkList *link,int pos);

//9.按数据查找元素
int Linklist_Find_Data(LinkList *link,data_t data);

//10.按值修改元素
void Linklist_Change_Data(LinkList *link,data_t data,data_t new_data);

//11.清空链表
void Linklist_Setnull(LinkList *link);

//12.删除链表//形参改变实参的值要用二级指针,闯入实参的地址
void Linklist_free(LinkList **link);

//13.显示链表
void Linklist_Show(LinkList *link);

//14.链表的逆序
LinkList *Order_Linklist(LinkList *link);

void Order_Linklist_1(LinkList *link);
void Order_Linklist_2(LinkList *link);
void Order_Linklist_3(LinkList *link);


#endif

2.功能函数,把每一个功能都封装成函数,由主函数来调用

/*===============================================
*   文件名称:linklist.c
*   创 建 者:     
*   创建日期:2022年07月28日
*   描    述:
================================================*/
#include <stdio.h>
#include <stdlib.h>
#include "linklist.h"



//1.创建头结点;

LinkList *Create_Linklist()
{
	LinkList *head=(LinkList *)malloc(sizeof(LinkList));
	if(NULL==head)
	{
		printf("malloc error\n");
		return NULL;
	}
	head->data=-1;
	head->next=head;
	head->prior=head;
	printf("链表创建成功");
	return head;
}

//2.判空

int Linklist_Empty(LinkList *link)
{
	if(link->next==link)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

//3.计算表长

int Linklist_Length(LinkList *link)
{
	int i=0;
	LinkList *head=link;
	while(link->next!=head)
	{
		link=link->next;
		i++;
	}
	return i;
}

//4.从表头插入节点(头插法/尾插法)

void Linklist_Insert_Head(LinkList *link,data_t data)
{
	LinkList *new=(LinkList *)malloc(sizeof(LinkList));
	if(NULL==new)
	{
		printf("malloc error\n");
		return ;
	}	
	new->data=data;
	new->next=NULL;
	new->prior=NULL;
					//2不能在3,4前面,先要把后面的两条线连上
										
	new->next=link->next;		//4
	
	link->next->prior=new;		//3
	
	new->prior=link;		//1
	
	link->next=new;		//2
	
	return ;
}

void Linklist_Insert_Front(LinkList *link,data_t data)
{
	
	return ;
}

//5.按位置插入数据

void Linklist_Insert_Pos(LinkList *link,int pos,data_t data)
{
	
	int i=Linklist_Length(link);
	if(pos<0 || pos>i+1)
	{
		printf("pos error\n");
		return ;
	}
	for(i=0;i<pos;i++)
	{
		link=link->next;
	}
	
	LinkList *new=(LinkList *)malloc(sizeof(LinkList));
	new->data=data;
						//2不能在3,4前面,先要把后面的两条线连上							
	new->next=link->next;		//4	
	link->next->prior=new;		//3	
	new->prior=link;		//1
	link->next=new;		//2

	
	
	return ;
}

//6.按位置删除数据

void Linklist_Delete_Pos(LinkList *link,int pos)
{
	if(Linklist_Empty(link))
	{
		printf("链表为空");
		return ;
	}	
	
	int i=Linklist_Length(link);
	if(pos<0 || pos>i+1)
	{
		printf("pos error\n");
		return ;
	}
	for(i=0;i<pos;i++)
	{
		link=link->next;
	}	
	
	LinkList *p=link->next;

	p->prior->next=p->next;
	p->next->prior=p->prior;
	
	free(p);
	p=NULL;
	
	return ;
}

//7.按数据删除

void Linklist_Delete_Data(LinkList *link,data_t data)
{
	if(Linklist_Empty(link))
	{
		printf("链表为空");
		return ;
	}
	int i=Linklist_Find_Data(link,data);
	
	if(i==-1) return ;
	
	Linklist_Delete_Pos(link,i);
	return ;
}

//8.按位置查找元素

int Linklist_Find_Pos(LinkList *link,int pos)
{
	int i=Linklist_Length(link);
	if(pos<0 || pos>i+1)
	{
		printf("pos error\n");
		return -1;
	}
	for(i=0;i<pos+1;i++)
	{
		link=link->next;
	}	
	
	printf("\nlink->data[%d]=%d\n",pos,link->data);
	return i;
}

//9.按数据查找元素

int Linklist_Find_Data(LinkList *link,data_t data)
{
	int i=-1,j=Linklist_Length(link);
	while(link->data!=data && i++<j-1)
	{
		link=link->next;
	}
	if(i==j)
	{
		printf("\n表中无这个元素\n");
		return -1;
	}
	
	printf("\n[%d]=%d\n",i,data);
	return i;
}

//10.按值修改元素

void Linklist_Change_Data(LinkList *link,data_t data,data_t new_data)
{
	int i=Linklist_Find_Data(link,data),j;
	for(j=0;j<=i;j++)
	{
		link=link->next;
	}
	link->data=new_data;
	return ;
}

//11.清空链表

void Linklist_Setnull(LinkList *link)
{
	
	LinkList *p=link->next;
	while( p->next != link )
	{	
		//printf("\np->data=%d\n",p->data);
		Linklist_Delete_Pos(link,0);
		p=link->next;
	}
	printf("\np->data=%d\n",p->data);
	Linklist_Delete_Pos(link,0);
	
	
	link->next=link;
	link->prior=link;
	printf("链表已清空\n");
	return ;
}

//12.删除链表

void Linklist_free(LinkList **link)//形参改变实参的值要用二级指针,传入实参的地址
{	
	if((*link)->next!=*link)
	{
		Linklist_Setnull(*link);
	}
	free(*link);
	*link=NULL;
	return ;
}
//13.显示链表
void Linklist_Show(LinkList *link)
{
	LinkList *head=link; 
	if(Linklist_Empty(link))
	{
		printf("\n链表为空\n");
		return;
	}
	
	while(link->next!=head)
	{
		link=link->next;
		printf("%4d",link->data);		
	}		
	puts("");	
}

	

LinkList *Order_Linklist(LinkList *link)
{
	LinkList *head=(LinkList *)malloc(sizeof(LinkList));
	if(NULL==head)
	{
		printf("malloc error\n");
		return NULL;
	}
	head->data=-1;
	head->next=NULL;
	
	while(link->next!=NULL)
	{
		link=link->next;
		Linklist_Insert_Head(head,link->data);
	}
	
		
	Linklist_Show(head);
	
	return head;	
}
void Order_Linklist_1(LinkList *link)
{
	LinkList *head=link->next->next;//指向第二个
	link->next->next=NULL;//第一个作为结尾,指向NULL

	while(head->next!=NULL)//保存数据要保存下一个地址,不能采用q=p,这样来保存,对p操作也相当于对q操作了,应该是q=p->next;
	{
		
		Linklist_Insert_Head(link,head->data);
		head=head->next;
	}
	
	Linklist_Insert_Head(link,head->data);
	
		
	Linklist_Show(link);
	
	return ;	
}

void Order_Linklist_2(LinkList *link)
{
	LinkList *cur,*pre,*next;
	cur=link->next;//cur指向第一个
	next=cur->next;//next指向第二个
	cur->next=NULL;//最后一个指向空
	pre=cur;	//pre指向前一个
	cur=next;	//cur指向当前
	
	while(cur->next!=NULL)
	{
		next=cur->next;//next指向前一个
		cur->next=pre;//链接后一个
		pre=cur;	//pre前移,为下次链接做准备
		cur=next;	//cur指向下一次要更改连接的目标
	}
	cur->next=pre;//最后一个链接上之前的
	link->next=cur;//再把头指针指向更改后的第一个元素
	Linklist_Show(link);
}

void Order_Linklist_3(LinkList *link)
{
	LinkList *p=link->next;
	LinkList *q=NULL;
	link->next=NULL;
	
	while(p!=NULL)
	{
		q=p->next;
		p->next=link->next;
		link->next=p;
		p=q;
	}
	Linklist_Show(link);
}

 3.主函数,封装成一个选择页面,根据用户的键盘输入,来执行不同的函数

/*===============================================
*   文件名称:main.c
*   创 建 者:     
*   创建日期:2022年07月28日
*   描    述:
================================================*/
#include <stdio.h>
#include <stdlib.h>
#include "linklist.h"

int main(int argc, char *argv[])
{ 
    	int i,pos;
    	data_t data,new_data;
   
    	LinkList *head,*link;
	
	link=head;//调用link,不改变head的值
   	while(1)
   	{
        printf("\n\n\t\t\t欢迎使用链表\n\n");
        printf("------------------------\n");
        printf("\t\t1.创建链表 \n");
        printf("\t\t2.插入元素(头插法) \n");
        printf("\t\t3.按位置插入元素 \n");
        printf("\t\t4.删除元素(按序号) \n");
        printf("\t\t5.删除元素(按值) \n");
        printf("\t\t6.查询元素(按序号) \n");
        printf("\t\t7.查询元素(按值) \n");
        printf("\t\t8.更改元素(按值) \n");
        printf("\t\t9.显示表中元素\n");
        printf("\t\t10.置空表 \n");
        printf("\t\t11.删除链表 \n");
       // printf("\t\t12.链表逆序 \n");
       printf("\t\t12.约瑟夫问题 \n");
        printf("\t\t0.退出 \n");

        printf("请输入[0~10]\n");
        scanf("%d",&i);

        switch(i)
        {
            case 1:
            {
            	head=Create_Linklist();
            	link=head;
            	break;
            }
            
            case 2:
            {
            	printf("请输入要插入的值:\n");
            	scanf("%d",&data);
            	Linklist_Insert_Head(link,data);
            	break;
            }
            
            case 3:
            {	
            	printf("请输入要插入的位置与要插入的值(以空格隔开)\n");
            	scanf("%d %d",&pos,&data);
            	Linklist_Insert_Pos(link,pos,data);
            	break;
            }
            
            case 4:
            {
            	printf("请输入要删除的位置\n");
            	scanf("%d",&pos);	
            	Linklist_Delete_Pos(link,pos);
            	break;
            }
            
            case 5:
            {
            	printf("请输入要删除的值\n");
            	scanf("%d",&data);            
            	Linklist_Delete_Data(link,data);
            	break;
            }
            
            case 6:
            {	
            	printf("请输入要查询的位置\n");
            	scanf("%d",&pos);	
            	Linklist_Find_Pos(link,pos);
            	break;
            }
            
            case 7:
            {	
            	printf("请输入要查找的值\n");
            	scanf("%d",&data);  
            	Linklist_Find_Data(link,data);
            	break;
            }
            
            case 8:
            {	
            	printf("请输入被替换的值与新值(以空格隔开)\n");
            	scanf("%d %d",&data,&new_data);
            	Linklist_Change_Data(link,data,new_data);
            	break;
            }
            case 9:Linklist_Show(head);break;
            
            case 10:Linklist_Setnull(link);break;
            
            case 11:Linklist_free(&head);break;//形参改变实参的值要用二级指针,闯入实参的地址
            
           // case 12:Order_Linklist_3(link);break;
	    case 12:Josephus();break;
            
            case 0:exit(0);
        }
    }
    return 0;
} 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值