虽然现在开发多用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); }
版权声明:本文为博主原创文章,未经博主允许不得转载。如需转载,请注明出处:http://blog.csdn.net/lindonglian
时间: 2024-11-04 21:03:04