zoukankan      html  css  js  c++  java
  • 约瑟夫环问题的解决

    约瑟夫环问题介绍

    已知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号
    ",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!
    ",stderr);
            exit(EXIT_FAILURE);
    		
    	} 
    	
    	phead->pnext=NULL;
    	
    	
        /////////////////////////////////
        for(i=0;i<n;i++)
        {
            p1=(NODE*)malloc(sizeof(NODE)); //分配内存
            if(p1==NULL)                    //检查合法性
            {
               fputs("memory error!
    ",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()函数里加了一个判断:当删除节点为第一个数据节点时,更改头节点的指针域的值,

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






  • 相关阅读:
    Ztree
    WebAPI
    数据传输
    jqyery+ajax 提交表单
    初试 MVC+Boostrap
    CSV 导入SQL Server 中
    10-C语言循环结构(一)
    Linux测试语句(test)
    C 链表
    C递归
  • 原文地址:https://www.cnblogs.com/lulipro/p/5052628.html
Copyright © 2011-2022 走看看