一个小笔记(3):约瑟夫环

什么是约瑟夫环?
其实百度有说
http://baike.baidu.com/view/717633.htm

以一个传说中的问题为例子,提供源代码
主要是能够通过这个问题,了解如何来操作循环链表


在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏

最后输出结果为最后一个存活的人的编号

// 约瑟夫问题(循环链表).cpp
// Win32控制台程序
#include "stdafx.h" 
#include <stdlib.h> 

typedef struct JOSEPH_NODE 
{ 
    int iNum;   // 编号
    struct JOSEPH_NODE * pNext;
} JOSEPH_NODE_S; 

// pJosephStart结点的下一个结点就是要杀死的人,删除该结点
void Delete_Next_Joseph(JOSEPH_NODE_S * pJosephStart) 
{ 
    JOSEPH_NODE_S * pJose = pJosephStart->pNext; 
    pJosephStart->pNext = pJose->pNext; 
    free(pJose); 
} 

// 释放链表
void Destroy_Joseph(JOSEPH_NODE_S * pJosephHead) 
{ 
    while (pJosephHead->pNext != pJosephHead) 
    {
        Destroy_Joseph(pJosephHead); 
    } 
    free(pJosephHead);
} 

// 初始化链表
int Init_Joseph(int iCount, JOSEPH_NODE_S ** ppJosephHead) 
{ 
    if (iCount < 1)
    { 
        return 0; 
    } 

    JOSEPH_NODE_S * pJoseNew; 
    JOSEPH_NODE_S * pJoseCur;
    int iSize = sizeof(JOSEPH_NODE_S); 
    pJoseNew = (JOSEPH_NODE_S *)malloc(iSize); 

    if (pJoseNew == nullptr) 
    { 
        return 0; 
    } 

    pJoseNew->iNum = 1; 
    pJoseNew->pNext = pJoseNew;
    *ppJosephHead = pJoseNew; 
    pJoseCur = pJoseNew; 
 
    // 链表添加结点
    for (int i = 1; i < iCount; i++) 
    { 
        pJoseNew = (JOSEPH_NODE_S *)malloc(iSize); 

        if (pJoseNew == nullptr) 
        { 
            Destroy_Joseph(*ppJosephHead); 
            return 0; 
        } 

        pJoseNew->iNum = i + 1; 
        pJoseNew->pNext = *ppJosephHead; 

        pJoseCur->pNext = pJoseNew; 
        pJoseCur = pJoseNew; 
    } 

    return 1;
} 

// 得到最后一个存活的人
// iCount:总人数
// iSkip:每隔多少个人就杀死一个人
int GetLastNode_Joseph(int iCount, int iSkip) 
{ 
    JOSEPH_NODE_S * pJoseph = nullptr; 
    JOSEPH_NODE_S * pJoseStart = nullptr; 

    if (Init_Joseph(iCount, &pJoseph) != 1) 
    { 
        printf("初始化失败
");
        return 0; 
    }
    pJoseStart = pJoseph; 

    // 每隔0个人杀死,最后一个人存活
    if (iSkip == 0) 
    { 
        while (pJoseStart->pNext->pNext != pJoseStart) 
        { 
            Delete_Next_Joseph(pJoseStart); 
        } 

        printf("Final Num: %d

", pJoseStart->pNext->iNum); 
        free(pJoseStart->pNext); 
        free(pJoseStart); 

        return 1; 
    } 

    // 每隔iSkip个人杀死一个人
    // 直到剩下1个人,剩下最后一个结点的pNext会指向自己
     while (pJoseStart->pNext != pJoseStart) 
    { 
        for (int i = 1; i < iSkip; i++) 
        { 
            pJoseStart = pJoseStart->pNext; 
        } 

        Delete_Next_Joseph(pJoseStart); 

        pJoseStart = pJoseStart->pNext; 
    } 

    printf("Final Num: %d

", pJoseStart->iNum); 

    free(pJoseStart); 


    return 1; 

} 

int main() 
{ 
    GetLastNode_Joseph(41, 2); 

    return 0; 

}
原文地址:https://www.cnblogs.com/recordprogram/p/5656736.html