约瑟夫问题

本文介绍了约瑟夫问题的背景及解决思路,通过分析问题性质,将其转化为线性表问题。文章详细阐述了ADT定义、数据存储、算法描述,并提供了JavaScript实现的完整代码,展示了在队列长度小于KEY值时使用求余处理的方法。最后,作者强调了问题解决中思维的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  数据结构老师布置的作业,感觉学着有点意思,虽然上课经常睡觉,但不能反应我学习的态度不端正尴尬


  言归正传,问题如下:


  

一、约瑟夫问题

  假设n个依次顺序编号1,2,…,n的竞赛者排成一个环形队列。每人均持有一个密码m,从第1个人开始,从1开始循环计数,每数到第m时,则让让其出队列。然后从下一个人开始重新从1开始计数,继续进行下去。这个过程一直进行到所有的人都出队列为止。最后出列者为优胜者。请输出给定条件下出队列的顺序。

二、题目要求

    请结合第二章节:线性表相关内容,分析问题性质和操作方法,并完成代码编写。具体请完成如下内容:

    1.分析问题,问题实质可以理解为何种数据结构问题(逻辑结构问题)。

    2.根据分析,写出问题的ADT定义。

 3.确定数据的存储方法,并定义相关数据类型。

 4.描述实现的操作算法。

 5.写出完整代码,运行调试输出结果。

    必要时加上适当的图示。


  问题的分析:

  1.所有人排成一列,然后不断的踢出KEY值位置的人,然后踢出位置后的人依次前移补充空位。可以抽象为一维数组(这一章就学的线性表么,所以用膝盖想都知道抽象成什么的委屈),然后不断的删除特定位置的元素,后面的元素依次补充空位。(实现方法见我另一篇博客《顺序表插入算法》)。

  2.当踢出的人很多以后,列队的长度小于KEY值时如何处理?求余!(当时写的时候条件反射般的写了个%,后面想想确实如此),列如KEY等于4,列队长度是3,要删除第四个必然要对列队重复计数。 


  实现如下:

  1.生成队列

  

var arr = [];
for ( i =0; i < n;i++ ) {
	arr.push(i);
	inner.innerHTML += "队列有" + i + "号<br>";
}

 2.当KEY值大于队列长度时踢人


for (; j < arr.length; j++ ) {
	arr[j - 1] = arr[j];
}

  3.当KEY值小于队列长度时踢人


w= key % arr.length; 
if ( arr.length < key ) {
	for (; w < arr.length; w++ ) {
		arr[w - 1] = arr[w];
	}
	arr.length - 1;
}

  运行截图


  初始化如图




  运行结果如图

  



  完整代码如下(没有优化难过

  

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
		<title>New Web Project</title>
		<script>
		window.onload = function () {
			
			function $ (id) {
				return 	document.getElementById(id);
			}
			
			function question (n, k, inner) {
				var arr = [];
				for ( i =0; i < n;i++ ) {
					arr.push(i);
				   	inner.innerHTML += "队列有" + i + "号<br>";
				}
			
				var key = k;
				for ( i = 0; i < key; i++ ) {
					if ( i == key-1 ) {
						var j = i + 1;
						for (; j < arr.length; j++ ) {
							arr[j - 1] = arr[j];
						}
						
						i = 0;
						w= key % arr.length; 
						if ( arr.length < key ) {
							for (; w < arr.length; w++ ) {
								arr[w - 1] = arr[w];
							}
							arr.length - 1;
						}
						if ( arr.length > 1 ) {
								arr.length -=1;
						} else if ( arr.length <= 1 ) {
							inner.innerHTML += "<b>最后留有" + arr[i]  + "</b>号<br>";
							return 1;
						}
					}			
				}
			}
			
			$('btn').addEventListener('click', function(){
				question($('num').value, $('key').value, $('result'));
			},false);
		}
		
		</script>
		<style>
			#content {
				position:absolute;
				margin-left: 500px;;
			}
			#result {
				position:absolute;
				margin-top: 30px;
			}
		</style>
	</head>
	<body>
		<div id="content">
			<div>请输入人数:</div>
			<input type="text" id="num">
			<div>请输入KEY:</div>
			<input type="text" id="key">
			<input type="button" id="btn" value = "确认">
			<div id="result"></div>
		</div>
		
	</body>
</html>

  

  总结

  用到了线性表的知识,代码本身没什么花哨的语法,但是思想值得学习。(PS,还好昨天看了顺序表的简单算法今天就用到了偷笑

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值