c语言实现简单环形链表,C语言实现环形链表

这篇博客介绍了如何使用C++实现链表的创建、插入、查找、删除等基本操作,并展示了利用链表解决约瑟夫问题的示例代码。通过头部和尾部插入函数,以及删除指定值节点的函数,展示了链表数据结构的运用。最后,应用这些操作解决约瑟夫问题,即按特定规则删除链表节点,直到只剩下一个节点。
摘要由CSDN通过智能技术生成

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

#include

#include

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);

}

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值