问题:
约瑟夫环问题:
问题描述:设有编号为1,2,3……n的n个人顺时针方向围坐一圈,每人有一密码(正整数)。开始时给出一初始密码m,从编号为1的人开始报数,报m的人出列;以后将出列者的密码作为新的m,从顺时针方向紧挨着他的下一个人开始报数……直至所有人出列。试编算法,求出出列顺序。
要求:
- 用不带头结点的单向循环链表实现
- 从键盘输入n,m
- 各人的密码由计算机随机产生(1~10的正整数,也可以自己指定)
//使用循环链表来解决约瑟夫环问题
//需要对链表实现的功能:
//1. 初始化链表节点值
//2. 删掉对应元素
//3. 返回对应值和序号
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
typedef struct LinkNode{
int number;// 序号
struct LinkNode* next;// 指向下一个节点的指针
}LinkNode, *LinkList;// 指向结构体的指针
// 设立尾指针的单循环链表
Status ListInit_CL(LinkList &L, int given_people)
{
LinkList l = (LinkList)malloc(sizeof(struct LinkNode));
if (!l)
exit(OVERFLOW);
L = l;// L就当作首,方便最后传出时,L没有变化
int index;
for (index = 0; index < given_people - 1; index++)// 循环赋值
{
l->number = index + 1;
LinkList q = (LinkList)malloc(sizeof(struct LinkNode));// 临时存储
if (!q) // 分配失败
return OVERFLOW;
l->next = q;
l = q;// 移位,当在最后一次的循环中,l所在是空的
q = NULL;
free(q);
}
l->number = index + 1;
l->next = L;
return OK;
}
// 删除第i个元素,并由number返回其序号
Status ListDelete_CL(LinkList &L, int i, int &number)
{
LinkList q;
int j;
if (i > 1)
{
for (j = 0; j < i - 1; j++)// 移动i-1次,寻找后面第i-1个结点
L = L->next;
q = L->next;// q指向待删除结点
L->next = q->next;// L->next指向被删除节点的下一个
}
else if (i == 1)
{
q = L;//q指向第一个有效位
for (j = 0;; j++)// 移动到最后面,使最后指向第二个有效位,并移动过去
{
L = L->next;
if (L->next == q)
{
L->next = q->next;
break;
}
}
}
else
{
return ERROR;
}
//返回被删除节点序号
number = q->number;
free(q);
return OK;
}
int main()
{
int i, first_num, get_number, given_people, given_maxnum;
printf("请输入:初始人数n,初始密码m\n");
scanf("%d %d", &given_people, &first_num);
if (given_people <= 0 || first_num <= 0)
return ERROR;
LinkList L = NULL;
if (!ListInit_CL(L, given_people))
return ERROR;
given_maxnum = first_num == 1 ? 1 : (first_num - 1);
ListDelete_CL(L, given_maxnum, get_number);
printf("随机数-->%d,被剔除-->%d\n", first_num, get_number);
int index;
int rand_number;
srand((unsigned)time(NULL));
for (index = 0; index < given_people - 2; index++)// 只删除n-2个,除了前面删除的一个,最后剩下的就是没有删除的。
{
ListDelete_CL(L, rand_number = rand() % 10 + 1, get_number);
printf("随机数-->%d,被剔除-->%d\n", rand_number, get_number);
}
printf("被剩下-->%d\n", L->number);
return OK;
}