使用python从三个角度解决josephus问题的方法


Posted in Python onMarch 27, 2020

0 写在前面

josephus问题是数据结构教材中的一个常见实例,其问题可以描述为:

设nnn个人围坐一圈,现在要求从第kkk个人开始报数,报到第mmm个的人退出。然后从下一个人开始继续按照同样规则报数并退出,直到所有人退出为止。要求按照顺序输出每个人的序列号。

1 基于数组概念的解法

首先考虑基于python的list和固定大小的数组概念,即将list看作元素个数固定的对象,只改变值而不删除元素,相当于摆了一圈nnn把椅子,人虽然退出但是椅子还在,我们可以给每个人从111到nnn编号,没有人的位置用000表示,思路如下:

初始

  • 建立包含nnn个人(编号)的list
  • 找到第kkk个人开始

运行

  • 从kkk的位置开始数到mmm,中间遇到000的就跳过
  • 数到mmm之后,将其值改为000
  • 然后继续循环,总共循环nnn次(因为每次循环就会退出一个人)

代码如下:

def josephus_A(n, k, m):
  people = list(range(1, (n+1)))
  i = k-1
  for num in range(n):
    count = 0
    while count < m: 
      if people[i] > 0:
        count += 1
      if count == m:
        print(people[i], end=" ")
        people[i] = 0
      i = (i+1) % n # count只是flag,真正记的数是i
    if num < n-1:
      print(end=",", )
    else:
      print(" ")

2 基于顺序表的解法

顺序表是线性表的一种,即表中元素放在一块足够大的连续存储区里,首元素存入存储区开始位置,其余元素依次存放。顺序表在python中的也是list,跟第一种解法不同,当第mmm个人退出需要进行删除元素的操作,才是顺序表。而第一种解法的数组想要删除并不是那么容易,这里是因为python中没有内置对数组的支持,所以用list代替,具体可以参照c++中的数组,如果要删除中间的某个元素的话,必须对后面的元素重新编号。代码实现如下:

def josephus_L(n, k, m):
  people = list(range(1, (n+1)))
  i=k-1
  for num in range(n,0,-1):
    i=(i+m-1)%num
    print(people.pop(i),end=", " if num>1 else "\n")

3 基于循环单链表的解法

单链表即单向链接表,典型的就是c++中的链表,循环单链表就是头尾相连的单链表,也是线性表的一种,这道题目使用循环单链表记录nnn个人围坐一圈最为契合。我们只需要数到第mmm个结点就删除,删除操作对于链表来说比较容易,而且不需要有i = (i+1) % n这样的整除操作。但是问题在于python并没有像c++那样有内置对链表的支持,因此需要建立一个链表的类,建立是比较麻烦的,但是操作比较简单,如下:

class LNode: # 建立链表结点
  def __init__(self,elem,next_=None):
    self.elem=elem
    self.next=next_
class LCList: # 建立循环链接表
  def __init__(self):
    self._rear=None
  def is_empty(self):
    return self._rear is None
  def prepend(self,elem): # 前端插入
    p=LNode(elem)
    if self._rear is None:
      p.next=p # 建立一个结点的环
      self._rear=p
    else:
      p.next=self._rear.next
      self._rear.next=p
  def append(self,elem): # 尾端插入
    self.prepend(elem)
    self._rear = self._rear.next
  def pop(self): # 前端弹出
    if self._rear is None:
      raise LinkedListUnderflow("in pop of CLList")
    p = self._rear.next
    if self._rear is p:
      self._rear =None
    else:
      self._rear.next=p.next
    return p.elem
  def printall(self): # 输出表元素
    if self.is_empty():
      return
    p = self._rear.next
    while True:
      print(p.elem)
      if p is self._rear:
        break
      p=p.next
class LinkedListUnderflow(ValueError): # 自定义异常
  pass
class Josephus(LCList):
  def __init__(self,n,k,m):
    LCList.__init__(self)
    for i in range(n):
      self.append(i+1)
    self.turn(k-1)
    while not self.is_empty():
      self.turn(m-1)
      print(self.pop(),end=("\n" if self.is_empty() else ", "))
  def turn(self,m):
    for i in range(m):
      self._rear = self._rear.next

到此这篇关于使用python从三个角度解决josephus问题的方法的文章就介绍到这了,更多相关python josephus问题内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python 含参构造函数实例详解
May 25 Python
python验证码识别实例代码
Feb 03 Python
Python实现的HMacMD5加密算法示例
Apr 03 Python
在Python 中同一个类两个函数间变量的调用方法
Jan 31 Python
python+pyqt5编写md5生成器
Mar 18 Python
python中时间模块的基本使用教程
May 14 Python
python 实现在一张图中绘制一个小的子图方法
Jul 07 Python
python实现信号时域统计特征提取代码
Feb 26 Python
Python使用requests模块爬取百度翻译
Aug 25 Python
Django基于Models定制Admin后台实现过程解析
Nov 11 Python
python中用ggplot绘制画图实例讲解
Jan 26 Python
OpenCV图像变换之傅里叶变换的一些应用
Jul 26 Python
解决django接口无法通过ip进行访问的问题
Mar 27 #Python
Django 实现将图片转为Base64,然后使用json传输
Mar 27 #Python
python实现简单坦克大战
Mar 27 #Python
Django实现从数据库中获取到的数据转换为dict
Mar 27 #Python
Python生成器实现简单&quot;生产者消费者&quot;模型代码实例
Mar 27 #Python
python数据库编程 Mysql实现通讯录
Mar 27 #Python
python数据库编程 ODBC方式实现通讯录
Mar 27 #Python
You might like
第一个无线电台是由谁发明的
2021/03/01 无线电
PHP 批量删除数据的方法分析
2009/10/30 PHP
php获取从html表单传递数组的方法
2015/03/20 PHP
修改WordPress中文章编辑器的样式的方法详解
2015/12/15 PHP
JS+PHP实现用户输入数字后显示最大的值及所在位置
2017/06/19 PHP
laravel获取不到session的三种解决办法【推荐】
2018/09/16 PHP
PHP使用gearman进行异步的邮件或短信发送操作详解
2020/02/27 PHP
jquery使用ColorBox弹出图片组浏览层实例演示
2013/03/14 Javascript
为JS扩展Array.prototype.indexOf引发的问题探讨及解决
2013/04/24 Javascript
不同编码的页面表单数据乱码问题解决方法
2015/02/15 Javascript
js实现n秒倒计时后才可以点击的效果
2015/12/20 Javascript
BootStrap和jQuery相结合实现可编辑表格
2016/04/21 Javascript
JavaScript制作简单分页插件
2016/09/11 Javascript
JS双击变input框批量修改内容
2016/12/12 Javascript
jQuery与vue实现拖动验证码功能
2018/01/30 jQuery
vue使用better-scroll实现下拉刷新、上拉加载
2018/11/23 Javascript
JavaScript实现世界各地时间显示
2020/09/07 Javascript
[33:15]2018DOTA2亚洲邀请赛3月30日 小组赛B组 VP VS Mineski
2018/03/31 DOTA
python网络编程学习笔记(三):socket网络服务器
2014/06/09 Python
举例讲解Python面向对象编程中类的继承
2016/06/17 Python
python虚拟环境virualenv的安装与使用
2016/12/18 Python
利用Anaconda完美解决Python 2与python 3的共存问题
2017/05/25 Python
python版简单工厂模式
2017/10/16 Python
Django学习教程之静态文件的调用详解
2018/05/08 Python
python判断输入日期为第几天的实例
2018/11/13 Python
Python3按一定数据位数格式处理bin文件的方法
2019/01/24 Python
python opencv摄像头的简单应用
2019/06/06 Python
HTML5页面音视频在微信和app下自动播放的实现方法
2016/10/20 HTML / CSS
法国在线购买汽车轮胎网站:123pneus.fr
2019/02/25 全球购物
实习评语
2013/12/16 职场文书
关于元旦的广播稿
2014/02/16 职场文书
党校学习自我鉴定
2014/02/24 职场文书
买卖合同协议书范本
2014/10/18 职场文书
社区党的群众路线教育实践活动总结材料
2014/10/31 职场文书
Django + Taro 前后端分离项目实现企业微信登录功能
2022/04/07 Python
MySQL 数据库 增删查改、克隆、外键 等操作
2022/05/11 MySQL