• 一个小笔记(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; 
    
    }
  • 相关阅读:
    wpf如何将图片设置为窗体的背景
    C#用Oracle.DataAccess中连接Oracle要注意版本问题!
    C#格式化数值结果表
    将字符串的16进制转换成byte[]
    Java各个类型与byte[]的转换
    记录下 Jquery的使用
    页面div与顶部有缝隙问题
    Js 转换Json返回的时间格式(转)
    Div垂直居中水平居中
    C# 日期格式大全
  • 原文地址:https://www.cnblogs.com/recordprogram/p/5656736.html
Copyright © 2020-2023  润新知