一、实验目的
能够熟练掌握线性表的基本操作在顺序和链式两种存储结构上的实现,进一步理解线性表的逻辑结构和存储结构,提高使用理论知识指导解决实际问题的能力。
二、实验题目
约瑟夫问题的一种描述是:编号为1,2,,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。开始时任选一个整数作为报数上限值m,从第一个人开始顺时针自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有的人全部出列为止。试设计一个程序,求出出列顺序。
利用单向循环链表作为存储结构模拟此过程,按照出列顺序打印出各人的编号。
例如,m的初值为20;n=7,7个人的密码依次是3,1,7,2,4,8,4,出列的顺序为6,1,4,7,2,3,5。
三、问题分析
1.数据分析
利用单向循环链表存储结构模拟报数过程,按照出列的顺序打印出个人的编号。
- 正确的输入的形式和输入值的范围
- 输出格式
- 程序所能达到的功能
- 进行数据测试
2.运算分析
程序命令应包括:构造单循环链表,输入数据创建约瑟夫循环链表显示表中数据内容,元素依次随机输出。
用主函数在其中放这些所需功能的函数。
3.主要算法分析
形成约瑟环初始化,通过建立指针,用for循环进行遍历
void joseph_init(int n) /*约瑟夫环初始化*/
{
int i;
node *p = mk_node(1);
head = p;
tail = p;
for (i = 2; i <= n; i++)
{
p = mk_node(i);
tail->next = p;
tail = p;
}
tail->next = head;
traverse();
}
建立循环链表,逢m便将其剔除。报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数。
int joseph(int n) /*剔除算法*/
{
int total = 0;
node *p ;
node *pre;
int surv;
joseph_init(n);
p = head;
pre = tail;
while (p->next != p)
{
total++;
if (total == 3)
{
pre->next = p->next;
p->next = NULL;
printf("出列的序号是:%d\n", p->item);
free_node(p);
p = pre->next;
total = 0;
continue;
}
p = p->next;
pre = pre->next;
}
surv = p->item;
free_node(p);
return surv;
}
4.测试数据分析
包括正确的输入及其输出结果和含有错误的输入及其输出结果
输入:123456789
输出:369485271
四、源程序
#include <stdio.h>
#include <stdlib.h>
typedef struct node /*头指针型约瑟夫环*/
{
int item;
struct node *next;
}node;
node *head = NULL; /*头空*/
node *tail = NULL; /*尾空*/
node *mk_node(int item) //分配地址空间,创建节点
{
node *p = (node *)malloc(sizeof(node));
if (p == NULL)
{
printf("malloc failed\n");
exit(1);
}
p->item = item;
p->next = NULL;
return p;
}
void free_node(node *p) //释放节点
{
free(p);
}
void traverse() //遍历
{
node *p = head;
while (p->next != head)
{
printf("%d ", p->item);
p = p->next;
}
printf("将数据都输入约瑟夫循环中:%d ", p->item);
printf("\n");
}
void joseph_init(int n) /*约瑟夫环初始化*/
{
int i;
node *p = mk_node(1);
head = p;
tail = p;
for (i = 2; i <= n; i++)
{
p = mk_node(i);
tail->next = p;
tail = p;
}
tail->next = head;
traverse();
}
int joseph(int n) /*剔除算法*/
{
int total = 0;
node *p ;
node *pre;
int surv;
joseph_init(n);
p = head;
pre = tail;
while (p->next != p)
{
total++;
if (total == 3)
{
pre->next = p->next;
p->next = NULL;
printf("出列的序号是:%d\n", p->item);
free_node(p);
p = pre->next;
total = 0;
continue;
}
p = p->next;
pre = pre->next;
}
surv = p->item;
free_node(p);
return surv;
}
int main()
{int n;
printf(“input your numbers:\n”);
Scanf(“%d”,%n);
printf("the last is %d\n", joseph(n));
return 0;
}