c实现循环链表

解决约瑟夫环问题核心步骤:

1.建立具有n个节点、无头的循环链表

2.确定第一个报数人的位置

3.不断从链表中删除链节点,直到链表为空

    

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;

typedef struct lnode
{
    int data;
    struct lnode *link;
}lnode;

/**
 * @brief 约瑟夫环问题:
 *    n 个人,编号为 1,2,...,n 
 *    从编号K的人开报数(从1开始)
 *    喊道 m 的人出列,也就是:从 1 数到 m,
 *
 * @param total    总人数
 * @param start    确定第一个开始报数的人编号
 * @param outnum   指定出列者喊到的数
 */
void JOSEPHUS(int total, int start, int outnum)
{
    //1. 定义变量
    lnode *p;    
    lnode *r;
    lnode *curr; //curr 指向尾, curr->link 指向头

    //2. 建立第一个节点
    p = (lnode*)malloc(sizeof(lnode));
    p->data = 1;
    p->link = p;
    curr = p;

    //3. 建立循环链表
    for (int i=2; i<=total; i++)
    {
        lnode *t = (lnode*)malloc(sizeof(lnode));
        t->data = i;
        t->link = curr->link;
        curr->link = t;
        curr = t;
        printf("%d\n", i);
    }

    //4. 指针移动到第一个报数的人
    while (start--)
    {
        r = p;
        p = p->link;
    }

    //5. 开始遍历删除
    while (total--)
    {
        //定位删除点
        for (int s=outnum-1; s--; r=p,p=p->link);

        printf("%d->", p->data);
        
        //删除节点
        r->link = p->link;
        free(p);
        p = r->link;
    }
    printf("\n");
}

int main()
{
    int total = 10; //总人数
    int start = 1;  //确定第一个开始报数的人编号(1,2,...)
    int outnum = 4; //指定出列者喊到的数
    
    JOSEPHUS(total, start, outnum);
}

 

posted on 2019-07-15 08:44  欢跳的心  阅读(456)  评论(0编辑  收藏  举报