c语言数据结构之单向循环链表约瑟夫问题

问题描述:

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


废话不多说,上代码:


/*==========Definition.h==============*/
/*标准库函数*/
#include<string.h>
#include<ctype.h>
#include<malloc.h>
#include<limits.h>
#include<stdio.h>
#include<stdlib.h>
#include<io.h>
#include<math.h>
#include<process.h>

/*常量定义*/
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define LIST_INIT_SIZE 5 /*循环链表存储空间的初始分配量*/

/*类型定义*/
/*Status是函数的类型,其值是函数结果状态代码,如OK等*/
typedef int Status;
/*Boolean是布尔类型,其值是TRUE或FALSE*/
typedef int Boolean;
/*演示程序设定元素类型为int,如有必要可以修改成其他类型*/
typedef int ElemType;
/*线性表的链式存储结构*/
struct Node
{
   ElemType data; /*数据域*/
   struct Node * next; /*后继指针域*/
   ElemType bianhao;
};
typedef struct Node LinkNode;
typedef struct Node * LinkList;





/*=======循环链表功能模块========*/


/*正序构造一个循环链表,并使用参数L返回*/
Status Initialize(LinkList&L,int n)
{
	/*产生头结点,并使L指向此头结点。此语句等价于:L=(LinkList)malloc(sizeof(struct Node)); */
	L=(LinkList)malloc(sizeof(LinkNode));
	if(!L) /*存储分配失败*/
		exit(OVERFLOW);
	/*指针域暂时置为空*/
	L->next=NULL;
	LinkList p,q;
	q=L;
	for(int i=0;i<n;i++)
	{
		/*生成新的有效数据结点*/
		p=(LinkList)malloc(sizeof(LinkNode));
		scanf("%d",&p->data);
		p->bianhao=i+1;
		/*该语句不能省,否则会造成程序异常*/
		p->next=NULL;
		q->next=p;
        q=p;
	}
	q->next=L;
	scanf("&d",L->data);
	L->bianhao=n;
	return OK;
}


/*=======在带头节点的循环链表L中,删除第i个元素,并由e返回其值========*/


Status LinkDelet(LinkList&L, int i, ElemType  &e,ElemType &n)
{
    LinkList p=L;
	int j = 0;
	while (p->next&&j < i - 1)       //查找到第i-1个节点
	{
		p = p->next;
		++j;
	}
	LinkList q;                   //删除第i个结点
    q = p->next;
    p->next = q ->next;
	e = q->data;
    n=q->bianhao;
	free(q);
	L=p;
	return OK;
}  




/*==================解决约瑟夫问题================*/
int main()
{
    int mima,m,n,bianhao,num;
    LinkList L;
    printf("=====下面为约瑟夫排序问题的计算过程及结果=====\n");
    printf("请输入环中元素的个数(正整数):");
    scanf("%d",&n);  
    printf("请输入%d个数据元素(每次输入一个元素后空格,全部输完以后回车):",n);
    Initialize(L,n);
	printf("请输入上限值m:");
    scanf(" %d",&m);
	printf("出列顺序为:");
    for(int i=0;i<n;i++)
    {
        LinkDelet(L,m,mima,bianhao);
		m=mima;
        printf(" %d",bianhao);
    }
	printf("\n");
	return 0;
}



一开始,创建循环链表是把我难住了,虽然书上说的很简单,但是一开始我的链表是带头结点的,而且并不打算在头结点存值,所以把尾结点指向头结点的下一个结点,循环起来难免出错。于是最后只得妥协,先将尾结点的下一个结点指向头结点,同时给头结点赋值,这样才输出正确的结果。



运行结果



  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值