精簡的約瑟夫環問題

#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;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章