数据结构C语言—约瑟夫环问题

本文介绍了一个使用双向循环链表实现的约瑟夫环问题解决方案,通过90行C代码,详细展示了如何根据报数值m选择指针移动方向,以高效地求解出列顺序。

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

                                   90行代码用双向链表解决约瑟夫环问题

问题描述:

             约瑟夫环(Joseph)问题的一种描述是:编号为1,2,3,......,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数),一开始任选一个正整数作为报数值m,从第一个人开始按照顺时针方向自1开始顺序报数,报到m时停止报数,报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。试设计一个程序求出出列顺序。

设计要求:

(1)采用双向循环链表存储结构,描述线性表的抽象数据类型。

(2)写一高效算法,根据报数值m选择指针的移动方向。

代码如下:

#include<stdio.h>
#include<stdlib.h>
typedef struct Node
{
int date,num;                    //记录密码和序号
struct Node *next,*prior;  //前继指针和后续指针
}Node;

//双向链表初始化
Node *Inslist()
{
Node *head;
head=(Node *)malloc(sizeof(Node));
head->next=head;
head->prior=head;
return head;
}

//录入数据
void createlist(Node *L,int n)
{
Node *s,*r;
int i,x;
r=L;
scanf("%d",&x);           //输入密码
r->date=x;
r->num=1;
for(i=2;i<=n;i++){
        scanf("%d",&x);   //录入每个人的密码
        s=(Node *)malloc(sizeof(Node));
        s->date=x;
        s->num=i;           //初始化每个人的序号
        s->prior = r;        //插入新的结点
        s->next = r->next;
        r->next->prior= s;
        r->next= s;
        r=s;
}
}

//双向循环链表的输出
void printflist(Node *L,int t)
{
Node *p;
p=L;
int m,i,sum,k=0;
printf("输入报数值m:");
scanf("%d",&m);
while(p->next!=p){
            sum=t-k;                       //sum为剩余人数
            while(m-sum>0) 
            m=m-sum;
            if(m<=sum/2){             //判断链表寻找方向,提高查找效率
            for(i=1;i<m;i++){
                p=p->next;
            }
            printf("%d ",p->num);
            m=p->date;
            p->prior->next=p->next;
            p->next->prior=p->prior;
            L=p->next;
            free(p);
            p=L;
    }
    else{
            m=sum-m+1;
            for(i=1;i<=m;i++){
                p=p->prior;
            }
            printf("%d ",p->num);
            m=p->date;
            p->prior->next=p->next;
            p->next->prior=p->prior;
            L=p->next;
            free(p);
            p=L;
    }
            k++;
}
printf("%d",p->num);
printf("\n");
}
int main(void)
{
Node *L;
int x,m;
L=Inslist();
printf("输入几个数:\n");
scanf("%d",&x);
printf("输入数据\n");
createlist(L,x);
printf("输出数据\n");
printflist(L,x);
system("pause");
return 0;
}

程序运行结果如下图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值