修改时间2021/9/28 可以自动生成用户定义长度的链表,用户可以自定义起始位置和步 长
问题描述:
设有n个人围坐在一个圆桌周围,现从第s个人开始报数,数到第m的人出列,然后从出列的下一个人重新开始报数,数到第m的人又出列,…,如此反复直到所有的人全部出列为止。Josephus问题是:对于任意给定的n,s和m,求出按出列次序得到的n个人员的序列。
现以n=8,s=1,m=4为例,问题的求解过程如图2-15所示。图中s1指向开始报数位置, 若初始的顺序为 n1,n2,n3,n4,n5,n6,n7,n8。则问题的解为n4,n8,n5,n2,n1,n3,n7,n6。
我们现在用顺序表来解决这个问题。
int josephus_seqList(PSeqList josephus_seq, int s, int m)
{
/*求解约瑟夫问题的出列元素序列入口参数:已经存放数据的顺序表,起始位置s,数m。出口参数:1表示成功,0表示表中没有元素*/
int s1; //用来存储要出队元素的位置,最小位置为0,最大位置为length-1
int i; //循环变量
int w; //要出队元素的值
//如果表为空
if ( !josephus_seq->length )
{
printf("表中无元素\n");
return 0;
}
//因为数组的下标从0开始,s是位置从1开始,这样就将s1变成从0开始的位置
s1 = s - 1;
printf("输出约瑟夫序列:\n");
//表长等于0时,此时已经完成了全部的出队,终止循环
for(i = josephus_seq->length; i>0; i--)
{
// if(josephus_seq->length)
//找到下一个出列元素的下标
s1 = (s1 + m - 1) % josephus_seq->length;
//输出要出队的值
w = josephus_seq->data[s1];
printf("%d\t", w);
//将出队的元素删除
Delete_SeqList(josephus_seq,s1+1);
}
return 1;
}
下面给出上面用到的Delete_SeqList()函数
void Delete_SeqList(PSeqList p, int pos)
{
int i; //循环变量
//如果顺序表为空
if( !p->length )
{
printf("顺序表为空,无法删除!\n");
return;
}
//如果删除位置有误
if(pos < 1 || pos > p->length)
{
printf("删除位置有错,无法删除!\n");
return;
}
//删除操作
for (i = pos; i < p->length; i++)
{
p->data[i - 1] = p->data[i];
}
//表长度减一
p->length--;
return;
}
以及整个可以运行的代码
/*
约瑟夫问题顺序表解决
V1.0
V1.5 用户可以自定义起始位置和步长
*/
#include<stdio.h>
#include<stdlib.h>
# define MAXSIZE 100
typedef struct josephus
{
int data[MAXSIZE];
int length;
}SeqList, * PSeqList;
int josephus_seqList(PSeqList, int, int);
void Delete_SeqList(PSeqList, int);
PSeqList init_SeqList();
int main(void)
{
int start;
int step;
PSeqList p;
p = init_SeqList();
printf("请输入起始位置:");
scanf("%d", &start);
printf("请输入步长:");
scanf("%d", &step);
josephus_seqList(p, start, step);
return 0;
}
/*求解约瑟夫问题的出列元素序列入口参数:已经存放数据的顺序表,起始位置s,数m。出口参数:1表示成功,0表示表中没有元素*/
int josephus_seqList(PSeqList josephus_seq, int s, int m)
{
int s1; //用来存储要出队元素的位置,最小位置为0,最大位置为length-1
int i; //循环变量
int w; //要出队元素的值
//如果表为空
if ( !josephus_seq->length )
{
printf("表中无元素\n");
return 0;
}
//因为数组的下标从0开始,s是位置从1开始,这样就将s1变成从0开始的位置
s1 = s - 1;
printf("输出约瑟夫序列:\n");
//表长等于0时,此时已经完成了全部的出队,终止循环
for(i = josephus_seq->length; i>0; i--)
{
// if(josephus_seq->length)
//找到下一个出列元素的下标
s1 = (s1 + m - 1) % josephus_seq->length;
//输出要出队的值
w = josephus_seq->data[s1];
printf("%d\t", w);
//将出队的元素删除
Delete_SeqList(josephus_seq,s1+1);
}
return 1;
}
void Delete_SeqList(PSeqList p, int pos)
{
int i; //循环变量
//如果顺序表为空
if( !p->length )
{
printf("顺序表为空,无法删除!\n");
return;
}
//如果删除位置有误
if(pos < 1 || pos > p->length)
{
printf("删除位置有错,无法删除!\n");
return;
}
//删除操作
for (i = pos; i < p->length; i++)
{
p->data[i - 1] = p->data[i];
}
//表长度减一
p->length--;
return;
}
//自动生成一个节点的数据域从一开始递增的顺序表
PSeqList init_SeqList()
{
int len;
int i;
int val = 1;
PSeqList p;
p = (PSeqList)malloc(sizeof(SeqList));
if(!p)
{
printf("分配失败!\n");
exit(-1);
}
p->length = 0;
printf("请输入你要生成的顺序表长度:(最大长度为100)\n");
while (true)
{
scanf("%d", &len);
if (100 < len)
{
printf("%d超出了可创建顺序表的最大长度!\n请重新输入!", len);
}
else
{
for (i = 0; i < len; i++)
{
p->data[i] = val;
p->length++;
val++;
}
break;
}
}
return p;
}