数据布局代码集训day16(得当考研、自学、期末和专升本)

[复制链接]
发表于 2026-1-25 21:14:35 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
本题来自B站up:白话拆解数据布局

本日标题就一个:约瑟夫环题目。
        一个圈共有N个人(N为不确定的数字),第一个人的编号为0大概1(两个都可以,看你的步伐怎样编写),假设这边我将第一个人的编号设置为1号,那么第二个人的编号就为2号,第三个人的编号就为3号,第N个人的编号就为N号,如今提供一个数字M,第一个人开始从1报数,第二个人报的数就是2,依次类推,报到M这个数字的人出局,紧接着从出局的这个人的下一个人重新开始从1报数,和上面过程类似,报到M的人出局,直到N个人全部出局,叨教,这个出局的次序是什么?

        这张图内圈代表元素,外圈代表出局的次序。这里的元素有10个,报到三出局。出局就相称于从这个圈出去了,圈内元素减1。

        这题有三种方法,第一个方法是用次序表,用i记载出列下标,用count记载出列的个数,由于走完一圈后须要回到开头继续数,以是要i=i%L.length重置一下,删除的操纵就是元素前移,前面已经说过了。
    void fa1(SqList &L,int N,int M){    
        int count=0,i=0;  
        while(count!=N){
            for(int k=0;k<M-1;k++,i++);
            if(i>=L.length)      i=i%L.length;
            printf("%d ",L.data);
            for(int j = i; j < L.length - 1; j++) {
            L.data[j] = L.data[j + 1];
        }
            count++;
            L.length--;     
        }
    }
实践:打印依次出队的元素

        法二:用循环单链表,刚好类似于图上的布局,和上面一样,找M,然后删除,就是重置的时间注意一下就行了。
    void fa2(Linklist &L,int N,int M){
        if (L == NULL || L->next == L)
            return; // 空链表或链表只有一个节点时,无需删除
        Lnode *pre ,*p;        // 删除的两个指针
        pre=L;
        p=L->next;
        while(L!=L->next){
            for(int i=0;i<M-1;i++){
                pre=p;
                p=p->next;
                if(p==L){        // 重置
                p=p->next;
                pre=pre->next;
                }
            }
            printf("%d ",p->data);
           
            pre->next=p->next;
            free(p);
            p=pre->next;
            }
    }
实践:
 
        法三:递归的做法,当 i == 1 时,表现只剩下一个人。这时,这个人的位置通过公式 (M - 1 + N) % N 来盘算;函数通过调用自身,递归地淘汰人数(N-1)和索引(i-1),渐渐缩小题目的规模;递归调用的结果会通过加上步长 M 并取模 N 来调解,确保盘算的位置在当前圆圈中有用。
  int fa3(int N,int M,int i){
        if(i==1)    return (M-1+N)%N;
        else return (fa3(N-1,M,i-1)+M)%N;
    }
 实践:这里输出的是位序,换算出来和上面一样。
  1. #include <iostream>
  2. #include <cstdio>
  3. #include <stack>
  4. #include <ctime>
  5. using namespace std;
  6. typedef int ElemType;
  7. struct SqList {
  8.     ElemType data[100];
  9.     int length;
  10. };
  11. typedef struct Lnode{
  12.     int data;
  13.     Lnode *next;
  14. }Lnode,*Linklist;
  15. Linklist list_insertbytail(Linklist &L) {
  16.     Lnode *s;
  17.     int x;
  18.    
  19.     // 初始化头节点(哨兵节点),不存储实际数据
  20.     L = (Lnode*)malloc(sizeof(Lnode));
  21.     L->next = L;  // 初始化为循环结构
  22.     Lnode *r = L; // r始终指向链表的尾节点
  23.    
  24.     cin >> x;
  25.     while (x != 9999) {
  26.         s = (Lnode*)malloc(sizeof(Lnode));  // 为新节点分配空间
  27.         s->data = x;                        // 将数据存入新节点
  28.         s->next = L;                        // 新节点的next指向头节点,形成环
  29.         r->next = s;                        // 将新节点链接到尾部
  30.         r = s;                              // 更新尾节点指针为r
  31.         
  32.         cin >> x;                           // 继续输入下一个数据
  33.     }
  34.     return L;  // 返回循环链表
  35. }
  36. // 约瑟夫环问题,N个人报数,报到M的出列,从M的下一个开始报,报到M的再次出列,问剩下的那个是谁
  37. class Solution{
  38. public:
  39.     void fa1(SqList &L,int N,int M){    // 找M,删M,从下一个开始
  40.         int count=0,i=0;  // count统计出列个数,到N-1就行了
  41.         while(count!=N){
  42.             for(int k=0;k<M-1;k++,i++);
  43.             if(i>=L.length)      i=i%L.length;
  44.             printf("%d ",L.data[i]);
  45.             for(int j = i; j < L.length - 1; j++) {
  46.             L.data[j] = L.data[j + 1];
  47.         }
  48.             count++;
  49.             L.length--;
  50.             
  51.         }
  52.     }
  53.     void fa2(Linklist &L,int N,int M){
  54.         if (L == NULL || L->next == L)
  55.             return; // 空链表或链表只有一个节点时,无需删除
  56.         Lnode *pre ,*p;
  57.         pre=L;
  58.         p=L->next;
  59.         while(L!=L->next){
  60.             for(int i=0;i<M-1;i++){
  61.                 pre=p;
  62.                 p=p->next;
  63.                 if(p==L){
  64.                 p=p->next;
  65.                 pre=pre->next;
  66.                 }
  67.             }
  68.             printf("%d ",p->data);
  69.             
  70.             pre->next=p->next;
  71.             free(p);
  72.             p=pre->next;
  73.             }
  74.     }
  75.     int fa3(int N,int M,int i){
  76.         if(i==1)    return (M-1+N)%N;
  77.         else return (fa3(N-1,M,i-1)+M)%N;
  78.     }
  79. };
  80. int main(){
  81.     // SqList L;
  82.     // L.length =10;
  83.     // // srand(static_cast<unsigned int>(time(nullptr)));
  84.     // // // 随机赋值
  85.     // for(int i =0;i<L.length;i++){
  86.     //     L.data[i] = i+1;   
  87.     // }
  88.     // Linklist L;
  89.     // list_insertbytail(L);
  90.     // Lnode *p = L->next;
  91.     int N,M;
  92.     cin>>N>>M;
  93.     printf("start:");
  94.     Solution a;
  95.     // a.fa1(L,10,3);
  96.     for(int i=1;i<=N;i++)
  97.         printf("%d ",a.fa3(N,M,i));
  98.     return 0;
  99. }
复制代码
 
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表