zoukankan      html  css  js  c++  java
  • 5.约瑟夫问题(循环链表)

    /* 此解法有一bug,假如有8个人,从第一个人开始数,每说到1就删除,相当于自删除,程序崩溃 */
    约瑟夫问题,有n个人,编号为1,2,...,n,围成一个圆圈,按照顺时针方向从编号为k的人从1开始报数,报数为m的人出列,如此重复下去,直到所有的人都出列。编写一个算法,要求输入n,k,m,按照出列的顺序输出编号。

    主要借助了两个游标进行移动,p有两个意义,第一,报数结束,p指向被删除的结点,第二,删除结点之后,p又指向开始报数的第一人。q作为桥梁进行衔接,因为需要删除p指向的结点。两个游标配合完成任务!

    /*----------------完整代码@映雪--------------*/
    
    #include <iostream>
    using namespace std;
    typedef struct Node
    {
        int data;
        struct Node *next;
    }ListNode,*LinkList;
    /*函数声明*/
    LinkList CreateCycList(int n);/*创建一个长度为n的循环单链表*/
    void Josephus(LinkList head,int n,int m,int k);    /*长度为n的循环单链表中,报数为编号为m的出列*/
    
    int main()
    {        
        LinkList h;
        int n,k,m;
        printf("输入环中人的个数n=");
        scanf("%d",&n);
        printf("输入开始报数的序号k=");
        scanf("%d",&k);
        printf("报数为m的人出列m=");
        scanf("%d",&m);
        h=CreateCycList(n);
        Josephus(h,n,m,k);    
        return 0;            
    }
    
    /*-----------------算法核心段-----------------*/
    
    void Josephus(LinkList head,int n,int m,int k)
    {
        ListNode *p,*q;
        int i;
        p=head;
        for(i=1;i<k;i++)/*从第k个人开始报数,将p先移到这个位置,准备开始*/
        {
            q=p;
            p=p->next;
        }
        while(p->next!=p)/*开始报数....*/
        {
            for(i=1;i<m;i++)/*数到m的人出列*/
            {
                q=p;
                p=p->next;
            }
            q->next=p->next;/*q作为辅助[衔接]p左右的两个结点,等价于删除p*/
            printf("%4d",p->data);
            free(p);/*释放结点p*/
            p=q->next;            /*p指向下一个结点,重新开始报数*/
        }
        printf("%4d
    ",p->data);/*只剩最后一个结点!*/
    }
    
    /*----------------建立循环链表------------------*/
    
    LinkList CreateCycList(int n)
    /*建立链表,用两个游标s,r配合完成!*/
    {
        LinkList head=NULL;
        ListNode *s,*r;
        int i;
        for(i=1;i<=n;i++)
        {
            s=(ListNode*)malloc(sizeof(ListNode));
            s->data=i;
            s->next=NULL;
            if(head==NULL)
                head=s;
            else
                r->next=s;
            r=s;
        }
        r->next=head;
        return head;
    }
  • 相关阅读:
    5月编程语言排行榜:动态语言的前世今生
    编程语言范式
    面向函数范式编程(Functional programming)
    bash脚本测试总结
    BASH的保护性编程技巧
    汇编Shellcode的技巧
    FreeBSD上编写x86 Shellcode初学者指南
    CnAms and cndoc
    Linux下shellcode的编写
    How To Configure NetScaler AppFlow for SolarWinds
  • 原文地址:https://www.cnblogs.com/tinaluo/p/5274434.html
Copyright © 2011-2022 走看看