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


    任务描述

    约瑟夫环是典型的线性表,可以使用不带头结点的循环单链表进行存储。本关任务,通过使用不带头结点的循环电链表存储约瑟夫环,并模拟约瑟夫环的报数出圈过程,得出约瑟夫环出圈序列。输入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 **********/
    
    }
  • 相关阅读:
    CKEditor 4 上传视频
    CKEditor 4 上传图片
    azure跨域问题(访问azure存储账户数据,blob)
    azure 上传blob到ams(CreateFromBlob)
    js 时间格式化成字符串
    js正则表达式替换HTML标签以及空格(&nbsp;)
    js 获取上传视频的时长、大小、后缀名
    webapi 跨域问题
    requests(二): json请求中固定键名顺序&消除键和值之间的空格
    requests(一): 发送一个json格式的post请求
  • 原文地址:https://www.cnblogs.com/xxxsans/p/14005294.html
Copyright © 2020-2023  润新知