(c语言) 单循环链表实现约瑟夫环

最近又重新写了一次约瑟夫环。

一.  约瑟夫环问题概述:

       设有n个人围坐在一- 个圆桌周围,现从第s个人开始报数,数到第m个的人出列,然后从出列的下一个人重新开始报数,数到第m的人又出列,..... 如此反复直到所有的人全部出列为止。对于任意给定的n、s和m,求出按出列次序得到的n个人员的序列。

 

二.  步骤

    1.创建由 n个结点组成的不带头结点的Josephus循环单链表

    2.找循环链 表中的第s个结点

    3.求第m 个应出列的元素删除它

 

三.  相关代码

# include<stdio.h>
# include<stdlib.h>

typedef struct Node
{
    int data; 
    struct Node * pNext;  
}Node, *pNode;  //pNode相当于Node *

pNode creat_list(int n){
    pNode pHead, pTail;
    pHead = (pNode)malloc(sizeof(Node));
    if(pHead == NULL)
    {
        printf("空间不足,分配失败!\n");
        exit(-1);
    }

    pTail = pHead;
    pHead->data = 1;
    pHead->pNext = NULL;

    for(int i=2; i<=n ;i++){  //尾插法,从第2个节点开始创建并往后边的节点中存入数据
        pNode pNew = (pNode)malloc(sizeof(Node));
        if(pNew == NULL)
        {
            printf("空间不足,分配失败!\n");
            exit(-1);
        }
        pNew->data = i;
        pNew->pNext = NULL;
        pTail->pNext = pNew; //前一个指针指向新插入节点
        pTail = pTail->pNext; //末尾指针往后移
    }
    
    pTail->pNext = pHead; //开始循环链表,最后一个指针指向第一个位置

    return pHead;
}

void traverse(pNode pHead) //遍历链表
{
    pNode a = pHead;
    while(a->pNext != pHead)
    {
        printf("%d ", a->data);
        a = a->pNext;
    }
    printf("%d\n", a->data);  //此时a已经指向了最后一个节点
}


void getyue(pNode pHead,int s, int m){
    pNode a = pHead, b = NULL;

    if( s==1 && m==1) //输出一个删一个
    {
        while(pHead != a->pNext)
        {
           printf("%d ", a->data);
           b = a->pNext;
           free(a);  //清除当前节点内存,防止内存泄漏
           a = b; //此句表明a指针已经往后移
         }
         printf("%d\n", a->data); //最后一个节点内容
    }
    else
    {
        for(int i=1; i<s ; i++) //找到s
        {
            a = a->pNext;
        }

        if( m==1)
        {
            printf("%d ", a->data);
            while(pHead->pNext != pHead)
            {
                b = a->pNext;
                a->pNext = b->pNext; //删除当前节点
                printf("%d ", b->data);
                if(b == pHead)
                {
                    pHead = b->pNext;
                }
                free(b);
            }
        }
        else
        {
          while (a != a->pNext) { //当链表中只剩一个节点时结束
              for(int i=1;i<m;i++){ //找到m前的那一个节点
                  b = a;
                  a = a->pNext;
              }
              printf("%d ", a->data);

              b->pNext = a->pNext; //删除当前节点
              free(a);
              a = b->pNext;       
          }
          printf("%d\n", a->data);
        }
    }
}


int main()
{
    pNode pHead = NULL;
    int n=0, m=0, s=0;

    printf("请依次输入小组人数、从第几个人开始报数、报到数字几的人出局(中间用空格隔开):\n");
    scanf("%d %d %d", &n, &s, &m);

    pHead = creat_list(n);
    printf("\n当前人员序列: ");
    traverse(pHead); //遍历输出
    printf("\n出列人员序列: ");
    getyue(pHead, s, m);
    printf("\n");

    return 0;
}

四.  运行结果

五.  总结

        一开始只写了s!=1, m!=1的情况,后边测试多次后发现不得行,根据着测试结果又进行了多次修改调试,最后成了上述代码结果。可能仍有错误或是考虑不周的情况,欢迎大家指出!(还是得多打代码诶~)

猜你喜欢

转载自blog.csdn.net/qq_51368339/article/details/118030935