溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何使用python從三個角度解決josephus問題

發(fā)布時間:2021-04-14 10:03:08 來源:億速云 閱讀:124 作者:小新 欄目:開發(fā)技術(shù)

小編給大家分享一下如何使用python從三個角度解決josephus問題,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

0 寫在前面

josephus問題是數(shù)據(jù)結(jié)構(gòu)教材中的一個常見實例,其問題可以描述為:

設(shè)nnn個人圍坐一圈,現(xiàn)在要求從第kkk個人開始報數(shù),報到第mmm個的人退出。然后從下一個人開始繼續(xù)按照同樣規(guī)則報數(shù)并退出,直到所有人退出為止。要求按照順序輸出每個人的序列號。

1 基于數(shù)組概念的解法

首先考慮基于python的list和固定大小的數(shù)組概念,即將list看作元素個數(shù)固定的對象,只改變值而不刪除元素,相當于擺了一圈nnn把椅子,人雖然退出但是椅子還在,我們可以給每個人從111到nnn編號,沒有人的位置用000表示,思路如下:

初始

  • 建立包含nnn個人(編號)的list

  • 找到第kkk個人開始

運行

  • 從kkk的位置開始數(shù)到mmm,中間遇到000的就跳過

  • 數(shù)到mmm之后,將其值改為000

  • 然后繼續(xù)循環(huán),總共循環(huán)nnn次(因為每次循環(huán)就會退出一個人)

代碼如下:

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,真正記的數(shù)是i
    if num < n-1:
      print(end=",", )
    else:
      print(" ")

2 基于順序表的解法

順序表是線性表的一種,即表中元素放在一塊足夠大的連續(xù)存儲區(qū)里,首元素存入存儲區(qū)開始位置,其余元素依次存放。順序表在python中的也是list,跟第一種解法不同,當?shù)趍mm個人退出需要進行刪除元素的操作,才是順序表。而第一種解法的數(shù)組想要刪除并不是那么容易,這里是因為python中沒有內(nèi)置對數(shù)組的支持,所以用list代替,具體可以參照c++中的數(shù)組,如果要刪除中間的某個元素的話,必須對后面的元素重新編號。代碼實現(xiàn)如下:

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 基于循環(huán)單鏈表的解法

單鏈表即單向鏈接表,典型的就是c++中的鏈表,循環(huán)單鏈表就是頭尾相連的單鏈表,也是線性表的一種,這道題目使用循環(huán)單鏈表記錄nnn個人圍坐一圈最為契合。我們只需要數(shù)到第mmm個結(jié)點就刪除,刪除操作對于鏈表來說比較容易,而且不需要有i = (i+1) % n這樣的整除操作。但是問題在于python并沒有像c++那樣有內(nèi)置對鏈表的支持,因此需要建立一個鏈表的類,建立是比較麻煩的,但是操作比較簡單,如下:

class LNode: # 建立鏈表結(jié)點
  def __init__(self,elem,next_=None):
    self.elem=elem
    self.next=next_
class LCList: # 建立循環(huán)鏈接表
  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 # 建立一個結(jié)點的環(huán)
      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問題”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學習更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI