循环单链表的初始化、插入、删除、按位遍历、融合、销毁、求节点数等操作(C语言实战题代码详解)

本题以尾插法构建带头结点的循环链表,在插入、删除、按位遍历中添加了异常判断的情况,并可以实现循环操作,具体各部分代码如下:
一、循环单链表的抽象数据类型定义:

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

#define  OK     1
#define  ERROR  0 

typedef  int   Elemtype;                  //数据类型重定义 
typedef  int   Status;                     //状态类型重定义 
typedef struct CLNode{
	Elemtype data;                         //链表数据域 
	struct CLNode *next;                   //链表指针域 
}CLNode,*CLinklist;
Status Length_CLinklist(CLinklist *L);     //函数声明

二、循环单链表初始化:

/*循环单链表初始化*/
Status Init_CLinklist(CLinklist *L)
{
	*L=(CLinklist)malloc(sizeof(CLNode)); //创建头结点 
	if(!(*L)) return ERROR;               //创建失败返回ERROR 
	(*L)->next=*L;                        //头结点指针指向本身 
	return OK;
}

三、循环单链表的尾插法构建:

/*循环单链表的尾插法构建,输入data,0的时候结束输入*/
void Create_CLinklist(CLinklist *L)
{
	CLNode *p,*q;                                //定义链尾节点和新生节点 
	int flag=1,number;                           //设立旗帜, 
	p = *L;
	while(flag)
	{
		scanf("%d",&number);
		if( number!=0 )
		{
			q=(CLinklist)malloc(sizeof(CLNode)); //创建新生节点 
			if(!q) exit(0);                      //创建失败结束程序 
			q->data=number;
			p->next=q; 	p=q;                     //这里和单链表的尾插法相同 
		}
		else
		{
			p->next = *L;                         //尾指针指向头结点 
			flag=0;
		}
	}
	
}

四、循环单链表的插入:

/*循环单链表的插入,插入错误返回0,插入成功返回1*/
Status Insert_CLinklist(CLinklist *L,int i,Elemtype e)
{
	int j=1; 
	CLNode *p,*q;                               //定义链尾节点和新生节点 
	p = *L;
	
	if(i<1||p->next==*L||i>Length_CLinklist(L))  
	return ERROR;                               //插入位置小于1,空表或大于表长则返回0  
	  
	while( p->next!=*L && j<i )
	{
		p=p->next;
		j++;
	}
	q=(CLinklist)malloc(sizeof(CLNode));
	q->data=e;
	q->next=p->next;
	p->next=q;
	return OK;
} 

五、循环单链表的删除:

/*循环单链表的删除,删除错误返回0,删除成功返回1,用e返回被删除的元素*/
Status Delete_CLinklist(CLinklist *L,int i,Elemtype *e)
{
	int j=1; 
	CLNode *p,*q;
	p = *L;
	
    if(i<1||p->next==*L||i>Length_CLinklist(L))  
	return ERROR;  //删除位置小于1,空表或大于表长则返回0
	
	while( p->next != *L && j<i)
	{
		p=p->next;
		j++;
	}
	q=p->next;
	*e=q->data;
	p->next=q->next;
	free(q);                           //释放掉删除结点 
	return OK;
}

六、循环单链表按指定结点位置开始遍历:

/*从指定的结点遍历循环链表*/ 
Status Print_CLinklist(CLinklist *L,int i)
{
	int j=1;
	CLNode *p,*q;
	p = *L;
	
	if(i<1||p->next==*L||i>Length_CLinklist(L))
	return ERROR;  //遍历位置小于1,空表或大于表长则返回0      
	

	printf("\n从第%d个结点开始遍历的链表为:\n",i);
	while(j<i)                  //找到要开始遍历的节点 
	{
		p=p->next;
		j++;
	}
	q=p->next;                  //开始遍历的节点赋给q 
	while(q != *L)              //找到头结点,因为头结点不遍历,所以要跳过头结点 
	{
		printf("%d ",q->data);
		q=q->next;
	}
	q=(*L)->next;               //把首节点赋给q 
	while(q != p->next)         //以开始遍历节点为止,继续遍历 
	{
		printf("%d ",q->data);
		q=q->next;
	}
	return OK;
} 

七、循环单链表的融合(将两个循环单链表融合成一个循环单链表):

/*循环链表的连接,将循环链表L,和循环链表L1融合为循环链表L*/
void Merge_Linklist(CLinklist *L,CLinklist *L1)
{ /*链表融合后返回的是*L,这有一个头结点*/ 
	CLNode *p,*q;
	p = (*L)->next;
	if( p == *L ) return;              //空表结束 
	q = (*L1)->next;
	if( q == *L1 ) return;             
	while( p->next != *L ) p=p->next;  //让链表一指向最后一个结点 
	while( q->next != *L1) q=q->next;  //让链表二指向最后一个结点
	p->next=(*L1)->next;               //让链表一尾结点指向链表二首节点 
	q->next=*L;	                       //让链表二尾结点指向链表一头结点 
}

八、循环单链表求节点数(表长):

/*求循环链表表长*/
Status Length_CLinklist(CLinklist *L)
{
	int i=0;
	CLNode *p;
	p=(*L)->next;  
	if( p == *L )  return ERROR;   //空表返回0 
	while(p != *L)
	{
		i++;
		p=p->next;
	}
	return i;	                 //返回表长 
} 

九、循环单链表的遍历(头结点开始遍历):

/*循环单链表的遍历*/
void Display(CLinklist *L)
{
	CLNode *p;
	p=(*L)->next;                //头结点指向第一个节点 
	while(p!=*L)
	{
	
		printf("%d ",p->data);
		p=p->next;
	}
} 

十、循环链表的清除:

/*清除循环链表*/
Status Clear_CLinklist(CLinklist *L)
{
	CLNode *p,*q;
	p = (*L)->next;
	if( p == *L ) return ERROR;   //空表返回0 
	while( p != *L)
	{
		q=p->next;
		free(p);
		p=q;
	}
	p->next = *L;               // 循环链空表是指向头结点 
	return OK;	
}

十一、主函数:

int main()
{
	int value,e,length,n,num;
	CLinklist L,L1;
	printf("\t\t...........................  0      退出     .............................\n\n"); 
	printf("\t\t...........................  1 循环链表初始化.............................\n\n"); 
	printf("\t\t...........................  2 循环链表的插入.............................\n\n"); 
	printf("\t\t...........................  3 循环链表的删除.............................\n\n"); 
	printf("\t\t...........................  4 循环链表的遍历.............................\n\n");
	printf("\t\t...........................  5 循环链表的表长.............................\n\n");  
	printf("\t\t...........................  6 循环链表的融合.............................\n\n");
	printf("\t\t...........................  7 循环链表的销毁.............................\n\n");  
	
	do
	{
		printf("\n\n请选择操作序号:");
		scanf("%d",&num);
		switch(num) 
		{
		
			case 1:
					value=Init_CLinklist(&L);
					if(value==0)
					{
						printf("\n初始化失败!\n");
						continue;
					}
					printf("请输入循环链表数据(0表示结束输入):\n");
					Create_CLinklist(&L);
					printf("\n初始化循环单链表元素为:\n");
					Display(&L);
					break;
				
			case 2:
					printf("\n请输入插入的序号:"); 
					scanf("%d",&n);
					printf("请输入要插入的值:");
					scanf("%d",&num);
					value=Insert_CLinklist(&L,n,num);
					if(value==0)
					{
						printf("\nposition error!\n");
						continue;
					}
					printf("\n插入后循环单链表元素为:\n");
					Display(&L);
					break;
			case 3:
				    printf("\n请输入删除结点的序号:"); 
				    scanf("%d",&n);
					value=Delete_CLinklist(&L,n,&e);
					if(value==0)
					{
						printf("\nposition error!\n");
		                continue;
					}
					printf("被删除的元素为:%d\n",e);
					printf("删除后循环单链表元素为:\n");
					Display(&L);
					break;
			case 4:
					printf("\n从第几个结点开始遍历:");
					scanf("%d",&n);
					value=Print_CLinklist(&L,n);
					if(value == 0)
					{
						printf("\nposition error!\n");
		                continue;
					}
					break;
		
			case 5:
					length=Length_CLinklist(&L);
					printf("\n当前循环链表表长为:%d",length);
					break;
			case 6:
					Init_CLinklist(&L1);
					printf("请输入你要融合的另一个循环链表的数据(0表示结束输入):\n");
					Create_CLinklist(&L1);
					Merge_Linklist(&L,&L1);
					printf("\n融合后的循环链表从第几个结点开始遍历:");
					scanf("%d",&num);
					printf("从第%d个结点开始遍历的链表为:\n",num);
					Print_CLinklist(&L,num);
					break;
			case 7: 
					 Clear_CLinklist(&L);
					 break;
		}
		
	}while(num!=0);
	return 0;
}

十二、部分运行效果截图:
在这里插入图片描述

  • 20
    点赞
  • 93
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是可以自定义的单链表初始化遍历插入删除进行控制的C语言代码: ```c #include <stdio.h> #include <stdlib.h> typedef struct node { int data; struct node *next; } Node; typedef struct list { int length; Node *head; } List; // 初始化链表,并返回链表头指针 List *initList() { List *list = (List *) malloc(sizeof(List)); list->length = 0; list->head = NULL; return list; } // 输出链表的所有数据 void traverse(List *list) { if (list == NULL || list->head == NULL) { return; } Node *p = list->head; while (p != NULL) { printf("%d ", p->data); p = p->next; } printf("\n"); } // 在头部插入节点 void insertAtHead(List *list, int data) { Node *node = (Node *) malloc(sizeof(Node)); node->data = data; node->next = NULL; if (list->head == NULL) { list->head = node; } else { node->next = list->head; list->head = node; } list->length++; } // 在尾部插入节点 void insertAtTail(List *list, int data) { Node *node = (Node *) malloc(sizeof(Node)); node->data = data; node->next = NULL; if (list->head == NULL) { list->head = node; } else { Node *p = list->head; while (p->next != NULL) { p = p->next; } p->next = node; } list->length++; } // 按照索引位置插入节点 void insertAtIndex(List *list, int index, int data) { if (index > list->length || index < 0) { return; } if (index == 0) { insertAtHead(list, data); return; } if (index == list->length) { insertAtTail(list, data); return; } Node *node = (Node *) malloc(sizeof(Node)); node->data = data; node->next = NULL; Node *p = list->head; Node *prev = NULL; int i; for (i = 0; i < index; i++) { prev = p; p = p->next; } node->next = p; prev->next = node; list->length++; } // 删除节点 void deleteAtHead(List *list) { if (list->head == NULL) { return; } Node *p = list->head; list->head = p->next; free(p); p = NULL; list->length--; } // 删除节点 void deleteAtTail(List *list) { if (list->head == NULL) { return; } if (list->length == 1) { deleteAtHead(list); return; } Node *p = list->head; Node *prev = NULL; while (p->next != NULL) { prev = p; p = p->next; } prev->next = NULL; free(p); p = NULL; list->length--; } // 删除指定位置的节点 void deleteAtIndex(List *list, int index) { if (list->head == NULL || index < 0 || index >= list->length) { return; } if (index == 0) { deleteAtHead(list); return; } if (index == list->length - 1) { deleteAtTail(list); return; } Node *p = list->head; Node *prev = NULL; int i; for (i = 0; i < index; i++) { prev = p; p = p->next; } prev->next = p->next; free(p); p = NULL; list->length--; } int main() { List *list = initList(); insertAtHead(list, 1); insertAtTail(list, 3); insertAtIndex(list, 1, 2); traverse(list); deleteAtHead(list); deleteAtTail(list); deleteAtIndex(list, 0); traverse(list); return 0; } ``` 对于编程类的问,ChatGPT可以给出答案,如上面的代码。如果您还有其它问,请继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值