单链表实现约瑟夫环

大家对约瑟夫环是比较陌生的,但是对于大多数人来说,丢手绢却一点都不陌生,其实约瑟夫环和丢手绢差不多。

约瑟夫环

约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。通常解决这类问题时我们把编号从0~n-1,最后结果+1即为原问题的解。
详见百度百科约瑟夫环.
在本篇博客中,我将是以一个单链表围成一个环,然后从第一个结点开始报数,当数到3的时候的那个结点就被抛出,然后从下一个开始又重新从1开始继续报数,从而留下最后一个结点,就是约瑟夫点(我自己瞎猜的);
下面是我画的一个对于一共有8个结点的环,每次报到3的时候就删除这个结点的展示图:
这里写图片描述

第一步:从1开始报数为3的时候就删除3号结点
第二步:从4号结点开始报数,当为3的时候删除6号结点;
第三步:从7号结点开始报数,当为3的时候删除1号结点;
第四步:从2号结点开始报数,当为3的时候删除5号结点;
第五步:从7号结点开始报数,当为3的时候删除2号结点;
第六步:从4号元素开始报数,当为3的时候删除8号结点;
第七步:又从4号开始报数,当为3的时候删除4号结点,此时链表中只有一个7号结点,所以最后的结点就是7号结点;

大概思路我们都有了,所以我们事先代码如下:

#include<iostream>
#include<assert.h>
using namespace std;

typedef int DataType;
typedef struct Node
{
    DataType _data;
    struct Node* _pNext;
}Node, *PNode;

Node* BuyNode(DataType data) //创建新结点
{
    PNode newNode = NULL;
    newNode = (PNode)malloc(sizeof(Node));
    if (NULL == newNode)
    {
        printf("out of memory\n");
        return NULL;
    }
    else
    {
        newNode->_data = data;
        newNode->_pNext = NULL;
    }
    return newNode;
}

void InitList(PNode* pHead)  //初始化链表
{
    assert(pHead);
    *pHead = NULL;
}

void PushBack(PNode* pHead, DataType data) //尾插
{
    assert(pHead);
    if (*pHead == NULL)
        *pHead = BuyNode(data);
    else
    {
        PNode pPreNode = *pHead;
        PNode pCurNode = BuyNode(data);
        while (pPreNode->_pNext)
            pPreNode = pPreNode->_pNext;
        pPreNode->_pNext = pCurNode;
    }
}

PNode Front(PNode pHead) //返回第一个结点
{
    if (NULL == pHead)
        return NULL;
    PNode pPreNode = pHead;
    return pPreNode;
}

PNode Back(PNode pHead) //返回最后一个结点
{
    if (NULL == pHead)
        return NULL;
    PNode pPreNode = pHead;
    while (pPreNode->_pNext && pPreNode)
        pPreNode = pPreNode->_pNext;
    return pPreNode;
}

PNode JosephCircle(PNode* pHead, int m)//约瑟夫环
{
    int count = m;
    PNode pPreNode = *pHead;
    PNode pCurNode = NULL;
    assert(pHead);
    if (NULL == *pHead)
        return NULL;
    while (pPreNode->_pNext != pPreNode)
    {
        count = m;
        while (--count)
        {
            pCurNode = pPreNode;
            pPreNode = pPreNode->_pNext;
        }
        pCurNode->_pNext = pPreNode->_pNext;
        free(pPreNode);
        pPreNode = pCurNode->_pNext;
    }
    return pPreNode;
}

int main()
{
    PNode pHead, pBackNode, pFrontNode;
    PNode tmp1;
    InitList(&pHead);
    PushBack(&pHead, 1);
    PushBack(&pHead, 2);
    PushBack(&pHead, 3);
    PushBack(&pHead, 4);
    PushBack(&pHead, 5);
    PushBack(&pHead, 6);
    PushBack(&pHead, 7);
    PushBack(&pHead, 8);

    pBackNode = Back(pHead);
    pFrontNode = Front(pHead);
    pBackNode->_pNext = pFrontNode;
    tmp1 = JosephCircle(&pHead, 3);
    cout << tmp1->_data << endl;
    return 0;
}

这里写图片描述

  • 9
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值