精简的约瑟夫环问题

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

/* 精简的瑟夫环问题
 * N个人围着坐成一圈, 各自的编号从1到N, 可以从编号为1的人开始报数, 为接近现实情况,
 * 报数从1开始, 设定一个报数的上限值M, 报数为M的人出列, 下一编号的人继续从1开始报
 * 数, 问最后剩下人是那个编号?
 * 例如: N=5, N=1时, 大家从1开始一次退出,最后剩下编号3; N=5, M=2时, 依次退出的
 * 编号顺序为: 2, 4, 1, 5,最后剩下编号3; N=8, M=4时,
 * 出列顺序为:4, 8, 5, 2, 1, 3, 7, 最后剩下6.

 * 用户输入M, N值, 注意是从编号为1的人开始报数, 通用问题应该可以从编号为X的人开始。
 */
//使用链表
typedef struct _tRING_NODE_
{
    int pos;
    _tRING_NODE_ *next;
}tRING_NODE;

tRING_NODE* create_ring(int num)
{
    if (num < 1) return NULL;

    tRING_NODE *head = NULL;
    tRING_NODE *ptr, *ptrTmp = NULL;
    int i = 1;

    while (num > 0)
    {
        ptr = new tRING_NODE;
        ptr->pos = i++;
        if (head == NULL)
            head = ptrTmp = ptr;
        ptrTmp->next = ptr;
        ptrTmp = ptr;
        --num;
    }
    ptrTmp->next = head; /* 循环链表 */
    return head;
}

void show_ring(tRING_NODE *head)
{
    if (head == NULL) return;
    tRING_NODE *ptr = head;

    while (1)
    {
        printf("%d->", ptr->pos);
        if (ptr->next == head)
            break;
        ptr = ptr->next;
    }
    printf("\n");
}

void process_ring(tRING_NODE *head, int n, int m)
{
    if (head == NULL || m < 1 || n < 1) return;

    tRING_NODE *ptr = head, *ptrTmp = ptr;
    int i = 1;

    while (n != 1)
    {
        if (i == m) //删除ptr
        {
            if (ptr == head)
            {
                head = ptr->next;
                ptrTmp->next = ptr->next;
                //printf("out of queue No=%d\n", ptr->pos);
                delete ptr;
                if (ptrTmp == head)
                    ptrTmp = ptr = head;
                else
                    ptr = ptrTmp->next;
                i = 1;
                --n;
                continue;
            }
            ptrTmp->next = ptr->next;
            //printf("out of queue No=%d\n", ptr->pos);
            delete ptr;
            ptr = ptrTmp->next;
            i = 1;
            --n;
        }
        else
        {
            ptrTmp = ptr;
            ptr = ptr->next;
            ++i;
        }
    }
    if (head != NULL)
    {
        head->next = head;
        printf("1.with linklist, last No=%d\n", head->pos);
        delete head; head = NULL;
    }
}

//使用数组
void ysfh_question(int N, int M)
{
    int *pArray = new int[N+1];
    int n = N, step = 1, k = 1;
    int flag = 1;

    memset(pArray, 0x0, sizeof(int) * (N+1));
    while (n != 1)
    {
        if (step == M)
        {
            //printf("delete ID=%d\n", k);
            pArray[k] = 1;
            while (pArray[k] != 0)
                k = ((k+1 >= N+1)? (k+1)%N : k+1);

            step = 1;
            --n;
        }
        else
        {
            if (pArray[k] == 0)
            {
                if (flag != 0)
                    k = ((k+1 >= N+1)? (k+1)%N : k+1);

                if (pArray[k] != 0)
                {
                    k = ((k+1 >= N+1)? (k+1)%N : k+1);
                    flag = 0;
                    continue;
                }
                ++step;
                flag = 1;
            }
            else
            {
                flag = 0;
                k = ((k+1 >= N+1)? (k+1)%N : k+1);
            }
        }
    }

    for (int i = 1; i <= N; ++i)
        if (pArray[i] == 0)
            printf("2.with array, Last No=%d\n", i);

    delete []pArray; pArray = NULL;
}

 int main(void)
{
    int n, m;
    printf("--- Josephus question ---\n");
    printf("Input N(total number of the people):\n");
    scanf("%d", &n);
    printf("Input M(out number):\n");
    scanf("%d", &m);

    tRING_NODE *pHead = create_ring(n);
    //show_ring(pHead);
    process_ring(pHead, n, m);
    ysfh_question(n, m);
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值