C语言实现环形链表

虽然现在开发多用Java了,闲着没事拿指针来练练手还是挺有意思的。约瑟夫的问题的解决方案有很多,可以用一个循环10不到解决,但要推导出一个公式;用一维数组加两个循环也可以,这种删除一个数据,后面元素的下标都要跟着变,不太可取。

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

typedef struct Linknode
{
	int data;
	struct Linknode *pNext;
}node,*PNODE;

//尾部插入
PNODE addback(PNODE phead,int data){
	PNODE pnew= (PNODE)malloc(sizeof(node));
	pnew->data=data;
	if(phead==NULL){//一个节点的环 
		phead=pnew;
		pnew->pNext=phead;
	}
	else{//多个节点
		PNODE p=phead;
		while(p->pNext!=phead){//循环到尾部 
			p=p->pNext;
		} 
		p->pNext=pnew;//链接到新的节点
		pnew->pNext=phead;//头尾相连 
	}
	return phead;
}
//头部插入
PNODE addfront(PNODE phead,int data){
	
	PNODE pnew=((PNODE)malloc(sizeof(node)));
	pnew->data=data;
	//一个节点的环 
	if(phead==NULL){
		phead=pnew;
		pnew->pNext=phead;
	}else{	//多个节点
		PNODE p=phead;
		while(p->pNext!=phead){//循环到尾部 
			p=p->pNext;
		} 
		p->pNext=pnew;
		pnew->pNext=phead;
		phead=pnew;
	}
	return phead;
} 

void showall(PNODE phead){
	printf("----------------showall-----------------\n");
	if(phead==NULL){
		return;
	}else if(phead->pNext==phead){//只有一个节点
		printf("%d,%p,%p",phead->data,phead,phead->pNext); 
	}else{
		PNODE p=phead;
		while(p->pNext!=phead){
		  printf("\n%d,%p,%p",p->data,p,p->pNext); 
		  p=p->pNext;
		}
		printf("\n%d,%p,%p",p->data,p,p->pNext); //补充相等的情况 
	}
}

PNODE findfirst(PNODE phead,int data){//找到第一个对应值为data的结点 
	if(phead==NULL){
	  return NULL;
	}else if(phead->pNext==phead){
		//只有一个节点
		if(phead->data==data){
		  return phead; 
		}
	}else{
		PNODE p=phead;
		while(p->pNext!=phead){
			if(p->data==data){
				return phead;
			} 
		  p=p->pNext;
		}
		if(p->data==data){
			return phead;
		}
	}
} 

PNODE deletefirst(PNODE phead,int data,PNODE* ppNext){//删除第一个对应值为data的结点 
	PNODE p1=NULL;
	PNODE p2=NULL;
	p1=phead;
	while(p1->pNext!=phead){
		if(p1->data==data){
			break;
		}else{
			p2=p1;
			p1=p1->pNext;
		}
	}
	if(p1!=phead){
		p2->pNext=p1->pNext;
		*ppNext=p1->pNext;
		free(p1);
	}else{//刚好是头结点 
		PNODE p=phead;
		while(p->pNext!=phead){
			p=p->pNext;
		}
		phead=phead->pNext;
		*ppNext=p1->pNext;
		free(p1);
		p->pNext=phead;
	}
	return phead;
}

int getnum(PNODE phead){//计算结点的个数
   	if(phead==NULL){
	  return 0;
	}else if(phead->pNext==phead){
		//只有一个节点
		return 1;
	}else{
		int i=1;
		PNODE p=phead;
		while(p->pNext!=phead){
		  i++;
		  p=p->pNext;
		}
		return i;
	}	
}

//如果存在结点值为finddata的结点,则在其前面插入data 
PNODE insertfirst(PNODE phead,int finddata,int data){
	
	PNODE p1=NULL;
	PNODE p2=NULL;
	p1=phead;
	while(p1->pNext!=phead){
		if(p1->data==finddata){
			break;
		}else{
			p2=p1;
			p1=p1->pNext;
		}
	}
	
	PNODE pnew=((PNODE)malloc(sizeof(node)));
	pnew->data=data;
	
	if(p1!=phead){
		pnew->pNext=p1;
		p2->pNext=pnew;
	}else{//刚好是头结点 
		PNODE p=phead;
		while(p->pNext!=phead){//循环到尾部 
			p=p->pNext;
		} 
		p->pNext=pnew;
		pnew->pNext=phead;
		phead=pnew;
	}
	return phead;	
	
}

main(){
//	printf("node有%d字节\n",sizeof(node));
//	printf("PNODE有%d字节\n",sizeof(PNODE));
	
	PNODE phead=NULL;
	printf("----------------addfront-----------------\n");
	for(int i=0;i<5;i++){
		phead=addfront(phead,i);//插入数据 
	}
	showall(phead);
	
//	printf("\n----------------addback-----------------\n");
//	phead=NULL;
//	for(int i=0;i<5;i++){
//		phead=addback(phead,i);//插入数据 		
//	}
//	showall(phead);		
//	
//	printf("\n---- findfirst(找到第一个值为3的结点)-----------------\n");
//	PNODE pfind=findfirst(phead,3);
//	pfind->data=77777;
//	showall(phead);	
//	
//	printf("\n------deletefirst(删除值为2的结点)-----------------\n");
//	phead=deletefirst(phead,2);
//	showall(phead);
//	
//	printf("\n------insertfirst(在结点为4的前面插入999999999)-----------------\n");
//	phead=insertfirst(phead,4,999999999);
//	showall(phead);

    printf("\n\n\n");
    //约瑟夫问题
	PNODE p=phead;
	while(getnum(phead)!=1){
		for(int i=1;i<=3;i++){
			p=p->pNext;
		}
		phead=deletefirst(phead,p->data,&p);
		//删除之后p要从下一个结点继续,所以需有第 3个参数改变其地址 
		printf("\n");
		showall(phead);
	} 
	printf("\n");
	printf("最后剩下的是%d\n",phead->data);

}
	
	



  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是用C语言实现环形链表的基本代码: ```c #include <stdio.h> #include <stdlib.h> // 定义节点结构体 typedef struct node { int data; struct node *next; } Node; // 创建新节点 Node *new_node(int data) { Node *node = (Node *)malloc(sizeof(Node)); node->data = data; node->next = NULL; return node; } // 添加节点到链表末尾 void add_node(Node **head, int data) { Node *node = new_node(data); if (*head == NULL) { *head = node; (*head)->next = *head; } else { Node *curr = *head; while (curr->next != *head) { curr = curr->next; } curr->next = node; node->next = *head; } } // 打印链表 void print_list(Node *head) { if (head == NULL) { printf("List is empty.\n"); } else { Node *curr = head; do { printf("%d ", curr->data); curr = curr->next; } while (curr != head); printf("\n"); } } // 删除节点 void delete_node(Node **head, int data) { if (*head == NULL) { printf("List is empty.\n"); return; } Node *curr = *head; Node *prev = NULL; while (curr->data != data) { prev = curr; curr = curr->next; if (curr == *head) { printf("Node not found.\n"); return; } } if (curr == *head && curr->next == *head) { *head = NULL; } else if (curr == *head) { Node *last = *head; while (last->next != *head) { last = last->next; } *head = (*head)->next; last->next = *head; } else { prev->next = curr->next; } free(curr); } int main() { Node *head = NULL; add_node(&head, 1); add_node(&head, 2); add_node(&head, 3); add_node(&head, 4); add_node(&head, 5); print_list(head); delete_node(&head, 3); print_list(head); delete_node(&head, 1); print_list(head); delete_node(&head, 5); print_list(head); return 0; } ``` 在这个代码中,我们通过定义一个指向自身的头节点来实现环形链表。添加节点时,我们遍历链表找到最后一个节点,然后将新节点添加到最后一个节点的后面,并将其指向头节点。删除节点时,我们遍历链表找到要删除的节点,并将其从链表中移除,然后释放内存。需要注意的是,如果要删除的是头节点,我们需要特殊处理。如果链表只有一个节点,我们将头节点设为NULL。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值