数据结构实验(一)

1.实验题目

约瑟夫环

[问题描述]

约瑟夫(Joeph)问题的一种描述是:编号为1,2,…,n的n个人按顺时针方向围坐一圈,

每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始

按顺时针方向自1 开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新

的m值,从他在顺时针方向上的下一个人开始重新从1 报数,如此下去,直至所有人全部

出列为止。试设计一个程序求出出列顺序。

[基本要求]

利用单向循环链表存储结构模拟此过程,按照出列的顺序印出各人的编号。

[测试数据]

m的初值为20;密码:3,1,7,2,4,8,4(正确的结果应为6,1,4,7,2,3,5)。

[实现提示]

程序运行后首先要求用户指定初始报数上限值,然后读取各人的密码。设n≤30。

[选作内容]

向上述程序中添加在顺序结构上实现的部分。

2.需求分析

本演示程序用c++编写,完成单向循环链表的生成,向单向循环链表中插入元素,从单向循环链表中删除元素

 输入的形式和输入值的范围:需要输入初始报数上限值m,人数n,n个密码。在所有输入中,元素的值都是整数,n<=30.

② 输出的形式:输出最后出列的人的顺序。

③ 程序所能达到的功能:完成约瑟夫问题

④ 测试数据:

   输入m=20,n=7,密码依次为3,1,7,2,4,8,4

3.概要设计

1)为了实现上述程序功能,需要定义单链表的抽象数据类型:

typedef struct Node

{

    int password;//存储密码,即m

    int num;

    struct Node* next;

}Node, * Link;

基本操作:初始化循环链表

phead = NULL;

操作结果:循环链表为空,头指针指向空

基本操作:向循环链表中插入密码

void CreateList(int n, Link& L) {//初始化链表

    Link p, q;

    q = L;

    printf("请输入这%d个人的初始密码分别为:", n);

    for (int i = 1; i <= n; i++) {

         p = (Node*)malloc(sizeof(Node));

         if (!p)

             exit(1);

         scanf_s("%d", &p->password);

         p->num = i;

         L->next = p;

         L = p;

    }

    L->next = q->next;

    free(q);

}基本操作:找到需要出列的人

void PrintList(Link& L, int m, int n) {//找位置

    Link p, q;

    p = L;

    for (int i = 1; i <= n; i++) {

         for (int i = 1; i < m; i++)

             p = p->next;

         q = p->next;

         m = q->password;

         printf("%d ", q->num);

         p->next = q->next;

         free(q);

    }

}操作结果:将出列的人密码赋为0

4.详细设计

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

typedef struct Node
{
	int password;//存储密码,即m
	int num;
	struct Node* next;
}Node, * Link;

void InitList(Link& L) {//创建一个空的链表
	L = (Node*)malloc(sizeof(Node));
	if (!L)
		exit(1);
	L->password = 0;
	L->num = 0;
	L->next = L;
}
void CreateList(int n, Link& L) {//初始化链表
	Link p, q;
	q = L;
	printf("请输入这%d个人的初始密码分别为:", n);
	for (int i = 1; i <= n; i++) {
		p = (Node*)malloc(sizeof(Node));
		if (!p)
			exit(1);
		scanf_s("%d", &p->password);
		p->num = i;
		L->next = p;
		L = p;
	}
	L->next = q->next;
	free(q);
}
void PrintList(Link& L, int m, int n) {//找位置
	Link p, q;
	p = L;
	for (int i = 1; i <= n; i++) {
		for (int i = 1; i < m; i++)
			p = p->next;
		q = p->next;
		m = q->password;
		printf("%d ", q->num);
		p->next = q->next;
		free(q);
	}
}
int main() {
	Link L, p, q;
	int n, m;
	L = NULL;
	InitList(L);
	printf("初始密码为:");
	scanf_s("%d", &m);
	printf("总人数为:");
	scanf_s("%d", &n);
	CreateList(n, L);
	printf("正确的输出为:");
	PrintList(L, m, n);
	printf("\n");
	return 0;
}

5.调试分析

运行稳定,在建立链表的时候要细心,规范循环结构。对头节点的控制进行了多次的调试。对于数据的储存和删除也进行了多次的修改。

6.使用说明

先确定使用的人数范围,然后赋予每个人独自的密码,然后再规定起始读数范围。最后由程序作出最终的排序结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值