约瑟夫环问题的解决

来源:互联网 发布:迪曼宠物用品淘宝真假 编辑:程序博客网 时间:2024/06/11 18:30

约瑟夫环问题介绍

已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为1的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。



# include <stdio.h># include <stdlib.h># include <assert.h>typedef int DataTp;typedef struct node{    DataTp elem;    struct node*pnext;}NODE;typedef NODE* LinkList;NODE* CreatList(int n);void MakeLoop(LinkList phead);void DeleteNode(LinkList phead,LinkList paim);int main (void){    int sum,num;  //总人数 , 退出人的编号    int i;        LinkList pstart;  //头节点     LinkList paim;    //待删除的目标节点的地址     LinkList pt;              puts("输入总人数");    scanf("%d",&sum);       puts("输入退出的编号");    scanf("%d",&num);    pstart=CreatList(sum);  //建立链表    MakeLoop(pstart);       //变为循环链表        pt=pstart->pnext; //取出第一个数据节点地址        while(sum!=0)     {        for(i=0;i<num-1;i++)            pt=pt->pnext;      //往后寻址,找到退出目标的地址             paim=pt;              //临时保存。确定删除节点的地址         pt=pt->pnext;         //确定下次循环的头为pt                printf("退出的是%d号\n",paim->elem);        DeleteNode(pstart,paim);         //删除                   sum--;                          //总人数减少    }           return 0;}NODE* CreatList(int n){    int i;    NODE*p1,*p2;    NODE * phead;phead=(NODE*)malloc(sizeof(NODE));if(phead==NULL){fputs("memory error!\n",stderr);        exit(EXIT_FAILURE);} phead->pnext=NULL;    /////////////////////////////////    for(i=0;i<n;i++)    {        p1=(NODE*)malloc(sizeof(NODE)); //分配内存        if(p1==NULL)                    //检查合法性        {           fputs("memory error!\n",stderr);           exit(EXIT_FAILURE);        }        p1->elem=i+1;                  //补全结点信息        p1->pnext=NULL;        if(phead->pnext==NULL)         //链接             phead->pnext=p1;        else             p2->pnext=p1;        p2=p1;                          //重置    }   return phead;}void MakeLoop(LinkList phead){    NODE*p=phead->pnext; //取出第一个数据节点         assert(p!=NULL);        while(p->pnext!=NULL)         p=p->pnext;             p->pnext=phead->pnext;   // 链接,构成循环链表    return ;}void DeleteNode(LinkList phead,LinkList paim){    NODE*p=phead->pnext;  //取出第一个数据节点         assert(p!=NULL);        while(p->pnext!=paim)        p=p->pnext;        p->pnext=p->pnext->pnext;    if(paim==phead->pnext)   //如果删除的是第一个数据节点,   phead->pnext=p->pnext; //改变头节点指针域的值,使它始终指向                          //循环链链表的某一个节点。而不丢失链表节点                                                            free(paim);    return ;}



链表初始状态:

刚开始写这个程序的时候,遇到一个Bug,那就是没有解决链表丢失问题。比如当退出的节点刚好为1号节点时

,1号节点就会被Free掉,这样就不能通过phead来访问各个节点了,整个链表就丢失了。

于是我在DeleteNode()函数里加了一个判断:当删除节点为第一个数据节点时,更改头节点的指针域的值,

使指向第一个数据节点的下一个节点,这样链表就不会丢失了。







0 0
原创粉丝点击