线性表应用三:约瑟夫环问题

任务描述

约瑟夫环是典型的线性表,可以使用不带头结点的循环单链表进行存储。本关任务,通过使用不带头结点的循环电链表存储约瑟夫环,并模拟约瑟夫环的报数出圈过程,得出约瑟夫环出圈序列。输入n(1<=n<=100)为约瑟夫初始结点个数,输入m(1<=m<=100)为一轮报数数值,输出出圈序列。 例:n=9 m=3 约瑟夫环

相关知识

据说著名犹太历史学家约瑟夫(Josephus)有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与约瑟夫及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而约瑟夫和他的朋友并不想遵从。约瑟夫要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。约瑟夫问题可以抽象为:n 个人围成一圈 (3<=n<=100)(从零开始编号),从第一个人开始报数,第m个将被杀掉 (1<=m<=n),最后剩下一个,其余人都将被杀掉 。例如n = 6,m = 5,被杀掉的顺序为:4, 3, 5, 1, 2, 0。

编程要求

本关的编程任务是补全step8/polynomailList.h文件中的 createJoselink ()、move ()、deleteNextnode ()、printJoseque() 函数,分别实现约瑟夫环的创建,指针固定步数的移动、后继结点的删除、约瑟夫环删除序列打印,这四个函数的具体说明如下:

// 函数createJoselink:创建包含n个结点(不带头结点)的循环单链,结点的数据值以此是1~n // 参数:n-约瑟夫环初始结点个数 // 返回值:约瑟夫环不带头循环单链表的首个结点指针 node* createJoselink(int t);

// 函数move:指针向前移动step步 // 参数:p-起点指针指向的结点位置,step-指针在循环单链中向前移动的步数 // 返回值:从p指针所指向的结点位置,向前移动step步后所指向的结点位置 node* move(node* p, int step);

// 函数deleteNextnode:删除p指针所指向的下一个结点 // 参数:pre-指向待删除结点的前驱结点(注意:当循环单链只剩下一个结点时,pre指针指向的结点即待删除结点) void deleteNextnode(node* pre);

// 函数printJoseque:输出约瑟夫环删除序列,编号之间用一个空格隔开 // 参数:n-约瑟夫环初始总人数,m-一轮报数值 void printJoseque(int n, int m);

评测说明

本关中包含两个文件分别是: step8/joseLink.h :此文件为学员文件,包含不带头结点的循环单链表结构约瑟夫环问题相关处理函数,其中createJoselink () 、move () deleteNextnode ()、printJoseque()为学员待实现函数。 step8/test.cpp:此文件为评测文件(含main函数),引用“joseLink.h”,主要用于输入约瑟夫环初始人数n和一轮报数数值m,并调用printJoseque()函数输出约瑟夫环删除序列。 (上述两个文件可通过点击在代码取的右上角文件夹中的step8文件夹中查看)

输入输出说明

输入约瑟夫环初始人数n(1<=n<=100),输入一轮报数数值m(1<=m<=100),输出约瑟夫环元素删除序列,例如:

测试输入: 6 5 预测输出: 5 4 6 2 3 1

测试输入: 9 3 预测输出: 3 6 9 4 8 5 2 7 1

test.h

#include "joseLink.h"
int main()
{
    int n, m;    
    // 输入初始总人数n,和一轮报数值m
    cin >> n >> m;
    // 输出约瑟夫出圈序列,两编号之间用一个空格隔开
    printJoseque(n,  m);
    return 0;
}

joseLink.h

#include <iostream>
using namespace std;

//单链表结点结构定义
struct node
{
    int  data;
    node* next;  // 指针域,指向下一个结点
};

// 函数createJoselink:创建包含n个结点(不带头结点)的循环单链,结点的数据值以此是1~n 
// 参数:n-约瑟夫环初始结点个数
// 返回值:约瑟夫环不带头循环单链表的首个结点指针
node* createJoselink(int t);

// 函数move:指针向前移动step步 
// 参数:p-起点指针指向的结点位置,step-指针在循环单链中向前移动的步数
// 返回值:从p指针所指向的结点位置,向前移动step步后所指向的结点位置
node* move(node* p, int step);

// 函数deleteNextnode:删除p指针所指向的下一个结点
// 参数:pre-指向待删除结点的前驱结点(注意:当循环单链只剩下一个结点时,pre指针指向的结点即待删除结点)
void deleteNextnode(node* pre);

// 函数printJoseque:输出约瑟夫环删除序列,编号之间用一个空格隔开
// 参数:n-约瑟夫环初始总人数,m-一轮报数值
void printJoseque(int n, int m);

// 函数delList:删除链表,释放空间
// 参数:h-链表头指针
void delList(node* h);

// 函数printList:输出链表,每个数据之间用一个空格隔开
// 参数:h-链表头指针
//void printList(node* h);

void delList(node* h)
{
    node* p = h; //指针p指向头结点,第一个要删除的结点
    while (p) //这个结点是存在的
    {
        h = h->next; //头指针h指向下一个结点(下一个结点的地址存在当前结点的指针域中,即h->next中
        delete p; //删除p指向的结点
        p = h; //p指向当前的头结点,即下一个要删除的结点
    }
}

node *newNode(int data) 
{ 
   node *temp = new node; 
   temp->next = temp; 
   temp->data = data; 
} 
node* createJoselink( int t)
{
    // 请在此添加代码,补全函数createJoselink
   /********** Begin *********/
    node *p, *q;
    p = (node*)malloc(sizeof(node));
    p->next = NULL;
    p->next = p;

    for (int i = 1; i <= t; i++)
    {
        q = (node*)malloc(sizeof(node));
        q->data = i;
        q->next = p->next;
        p->next = q;
    }
    return p;
    /********** End **********/

}

node* move(node* p, int step)
{
    // 请在此添加代码,补全函数move
    /********** Begin *********/
    for(int i = 0; i < step ; i++) //移动到删除节点位置        
    {
        p = p->next;
    }
    return p;
    /********** End **********/
}

void deleteNextnode(node* pre)
{
   
    // 请在此添加代码,补全函数deleteNextnode
    /********** Begin *********/
    node *q = pre->next;
    pre->next = q->next;
    free(q);
    /********** End **********/

}

void printJoseque(int n, int m)
{
    // 请在此添加代码,补全函数printJoseque
    /********** Begin *********/
    node *head = newNode(1); 
    node *prev = head; 
    for (int i = 2; i <= n; i++) 
    { 
        prev->next = newNode(i); 
        prev = prev->next; 
    } 
    prev->next = head; // Connect last 
                       // node to first 
  
    /* while only one node is left in the 
    linked list*/
    node *ptr1 = head, *ptr2 = head; 
    while (ptr1->next != ptr1) 
    { 
        // Find m-th node 
        int count = 1; 
        while (count != m) 
        { 
            ptr2 = ptr1; 
            ptr1 = ptr1->next; 
            count++; 
        } 
  
        /* Remove the m-th node */
        ptr2->next = ptr1->next;
        printf ("%d ", ptr1->data);  
        free(ptr1); 
        ptr1 = ptr2->next;
    }
    printf ("%d ", ptr1->data);   
    /********** End **********/

}
原文地址:https://www.cnblogs.com/xxxsans/p/14005294.html