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()函数里加了一个判断:当删除节点为第一个数据节点时,更改头节点的指针域的值,

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






  • 相关阅读:
    Atitit.Java exe bat  作为windows系统服务程序运行
    Atitit. Object-c语言 的新的特性  attilax总结
    Atitit. Object-c语言 的新的特性  attilax总结
    Atitit。Time base gc 垃圾 资源 收集的原理与设计
    Atitit。Time base gc 垃圾 资源 收集的原理与设计
    Atitit.go语言golang语言的新的特性  attilax总结
    Atitit.go语言golang语言的新的特性  attilax总结
    Atitit.pdf 预览 转换html attilax总结
    Atitit.pdf 预览 转换html attilax总结
    Atitit.office word  excel  ppt pdf 的web在线预览方案与html转换方案 attilax 总结
  • 原文地址:https://www.cnblogs.com/lulipro/p/5052628.html
Copyright © 2011-2022 走看看