约瑟夫环系列问题

本文通过两个具体案例探讨了循环链表在实际问题中的应用。首先,通过铁锤妹妹手中的扑克牌问题,展示了如何使用循环链表模拟牌的翻转过程。其次,详细介绍了约瑟夫环问题的解决方案,包括如何构建和操作循环链表来模拟游戏过程,直至找到最后的幸存者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据结构循环链表的应用

*铁锤妹妹手中有A—K的黑桃牌13张,每次不看牌,数数:1翻过来刚好为A;1、2翻过来刚好为2;
1、2、3翻过来刚好为3(不翻的牌放在手中这迭牌的最下面,翻开的牌翻开放在一侧);……;
1、……、13刚好为K。最后放在一旁的牌的顺序为1、2、3、4、5、……、J、Q、K。问:
原先铁锤妹妹手中的牌的循序是怎样的?
 * 答案:1 8 2 5 10 3 12 11 9 4 7 6 13
 

#include <iostream>
using namespace std;
#define N 13
 
typedef struct Node
{
    int data;
    Node *next;
}Node,*LinkList;
 
void Init(LinkList &L, int n)        //初始化 
{
    L = new Node;
    L->next = L;
    LinkList p;
    for(int j = 0; j < n; ++j)
    {
        p = new Node;
        p->data = 0;          
        p->next = L->next;    
        L->next = p;          
    }
}


void Get(LinkList &L, int n)
{
    LinkList p = L->next;
    p->data = 1; 
    int num;                     
    for( num = 2; num <= n; ++num)  
    {
        int i = 0;
        while(i < num)    
        {
            p = p->next;
            if(p->data == 0) ++i;      //跳过已存在的牌的地方 
        }
        p->data = num;
    }
}
 
void Print(LinkList &L)
{
    LinkList p = L->next;
    cout << "Print: ";
    while(p != L)
    {
        cout << p->data << " ";
        p = p->next;
    }
    cout << endl;
}
 
int main()
{
    LinkList L;
    Init(L, N);
    Get(L, N);
    Print(L);
}

一群小孩编号为1,2,…,n(n>0)围成一圈,有一个刚出锅的山芋在他们之间传递。假设刚开始由1号拿
着山芋,然后依次计数把山芋交给下一个小孩,当数到某个特定的k时,拿着山芋的小孩退出游戏,然后从
下一个小孩重新开始计数,如此不断,最后剩下的那个孩子就是幸运者。要求设计一个程序模拟次过程,
并给出不同的n,k组合下那个幸运者是谁?
1、输入的形式和输入值的范围:演示程序以用户和计算机的对话方式执行,即在计算机终端上显示“提示
信息”之后,由用户在键盘上输入相应的数据,每个人的序号由程序自动分配。以int型输入,范围在
-2147483648~2147483648;
2、输出的形式:int型;
3、程序所能达到的功能:构造链表;输入数据;执行报数;储存出列人的序号,删除出列人的信息以及把
指向出列人的指针移到出列人的下一个人,然后重新开始执行报数;直到最后一个人报数完毕,程序结束。
4、测试数据:n=9,9个人的序号分别为:1,2,3,4,5,6,7,8,9。然后b=1,从第一个开始报数。k=5,则
确定输出的序列为:5,1,7,4,3,6,9,2,8。


 

# include <iostream>
# include <string.h> 
# include <cstring>
# include <cstdlib>
# include <cstdio>
 
using namespace std;  
  
typedef struct _Node  
{  
    int data;  
    struct _Node*next;  
} node_t;  
  
typedef struct _Linklist  
{  
    node_t*phead;  
    node_t*ptail;  
    int len;  
}Linklist;  
static node_t*GetNode(int i )//新建并初始化节点  
{  
    node_t*pNode;  
    pNode=new node_t;  
    if(!pNode)  
    {  
        cout <<"内存分配失败" <<endl;  
        exit(-1);  
    }  
    pNode->data=i;  
    pNode->next=NULL;  
    return pNode;  
    delete pNode;  
}  
void init_list(Linklist*plist)//用第一个节点初始化循环单链表  
{  
    node_t*p;  
    p=GetNode(1);   
    plist->phead=p;  
    plist->ptail=p;  
    p->next=plist->phead;  
    plist->len=1;  
}  
  
//把其余数据添加到循环单链表中  
static void Create_List(Linklist*plist,int n)  
{  
    int i=0;  
    node_t*pNew;  
    for(i=2;i<=n;i++)  
    {  
        pNew=GetNode(i);  
        plist->ptail->next=pNew;  
        plist->ptail=pNew;  
        pNew->next=plist->phead;  
        plist->len++;  
    }  
}  
//输出链表内容  

void joseph(Linklist* plist,int m,int k)  
{    
    node_t *pPre=plist->ptail;  
    node_t *pCur=plist->phead;  
    int i,j;  
cout << "出队列的顺序依次为: "<< endl;  
    while(plist->len != 1)  
    {  
        i=0;  
        j=0;  
        while(j<k-1)  
        {  
            pPre=pPre->next;  
            j++;  
        }  
        while(i< m -1)  
        {  
            pPre=pPre->next;  
            i++;  
        }  
        pCur=pPre->next;  
        int temp=pCur->data;  
        cout <<"第 " << temp << "  个人 "<< endl ;  
        pPre->next=pCur->next;  
        free(pCur);  
        plist->len--;  
    }  
    cout <<"第 " << pPre->data << " 个人" << endl; ;  
    cout << "幸运者是:" << pPre->data<< endl;  
}  
int main(int argc, char * argv[])  
{  
    int n=0;  
    cout <<"小孩个数 : "<<endl;  
    cin >> n;  
    int m=0;  
    cout << "每数到几时,此人出列?"<<endl;  
    int k;  
    cin >> k;  
    cout << "从第几个小孩开始数?" << endl;  
    cin >>m;  
    Linklist pList;  
    init_list(&pList);  
    Create_List(&pList,n);    
    joseph(&pList,m,k);  
    return 0;  
}  

/*
铁锤妹妹想到一个杀人游戏游戏规则如下:铁锤妹妹抓了n个人对这n个人进行编号,分别从1到n,
排成一个圈,顺时针从1开始数到m,数到m的人被杀,剩下的人继续游戏,活到最后的一个人是胜利者。
请输出每次被杀的人的编号注意最后一个活着的人不用输出
输入
多组测试数据,输入n和m值。1<n,m<200,EOF结束
输出
输出每次被杀的人的编号 注意 最后一个人不用输出
*/
/*//数组方法 

#include<stdio.h>
int main()
{
    int n,m;
    while(scanf("%d %d",&n,&m)&&n!=0&&m!=0)
    {
        int i=0,j=0,a[205]= {0},t=0;
        while(1)
        {
            j++;
            if(a[j%n]==0)
                i++;
            if(i==m)
            {
                i=0;
                a[j%n]=1;
                t++;
                if(j%n==0)
                    printf("%d\n",n);
                else
                    printf("%d\n",j%n);
            }
            if(t==n)
                break;
        }
    }
    return 0;
}


*/ 

循环链表

# include <iostream>
# include <string.h> 
# include <cstring>
# include <cstdlib>
# include <cstdio>
 
using namespace std;  
  
typedef struct _Node  
{  
    int data;  
    struct _Node*next;  
} node_t;  
  
typedef struct _Linklist  
{  
    node_t*phead;  
    node_t*ptail;  
    int len;  
}Linklist;  
static node_t*GetNode(int i )//新建并初始化节点  
{  
    node_t*pNode;  
    pNode=new node_t;  
    if(!pNode)  
    {  
        cout <<"内存分配失败" <<endl;  
        exit(-1);  
    }  
    pNode->data=i;  
    pNode->next=NULL;  
    return pNode;  
    delete pNode;  
}  
void init_list(Linklist*plist)//用第一个节点初始化循环单链表  
{  
    node_t*p;  
    p=GetNode(1);   
    plist->phead=p;  
    plist->ptail=p;  
    p->next=plist->phead;  
    plist->len=1;  
}  
  
//把其余数据添加到循环单链表中  
static void Create_List(Linklist*plist,int n)  
{  
    int i=0;  
    node_t*pNew;  
    for(i=2;i<=n;i++)  
    {  
        pNew=GetNode(i);  
        plist->ptail->next=pNew;  
        plist->ptail=pNew;  
        pNew->next=plist->phead;  
        plist->len++;  
    }  
}  
//输出链表内容  

void joseph(Linklist* plist,int m,int k)  
{    
    node_t *pPre=plist->ptail;  
    node_t *pCur=plist->phead;  
    int i,j;   
    while(plist->len != 1)  
    {  
        i=0;  
        j=0;  
        while(j<k-1)  
        {  
            pPre=pPre->next;  
            j++;  
        }  
        while(i< m -1)  
        {  
            pPre=pPre->next;  
            i++;  
        }  
        pCur=pPre->next;  
        int temp=pCur->data;  
        cout  << temp << endl ;  
        pPre->next=pCur->next;  
        free(pCur);  
        plist->len--;  
    }     
}  
int main(int argc, char * argv[])  
{  
    int n,k,m=1;    
    cin >> n;   
    cin >> k;    
    Linklist pList;  
    init_list(&pList);  
    Create_List(&pList,n);    
    joseph(&pList,m,k);  
    return 0;  
}  

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流萤数点

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值