環形單鏈表的約瑟夫問題 Python版
阿新 • • 發佈:2019-01-28
題目:
一個環形單鏈表,從頭結點開始向後,指標每移動一個結點,就計數加1,當數到第m個節點時,就把該結點刪除,然後繼續從下一個節點開始從1計數,迴圈往復,直到環形單鏈表中只剩下了一個結點,返回該結點。
這個問題就是著名的約瑟夫問題。
程式碼:
首先給出環形單鏈表的資料結構:
class Node(object):
def __init__(self, value, next=0):
self.value = value
self.next = next # 指標
class RingLinkedList(object):
# 連結串列的資料結構
def __init__(self):
self.head = 0 # 頭部
def __getitem__(self, key):
if self.is_empty():
print 'Linked list is empty.'
return
elif key < 0 or key > self.get_length():
print 'The given key is wrong.'
return
else :
return self.get_elem(key)
def __setitem__(self, key, value):
if self.is_empty():
print 'Linked list is empty.'
return
elif key < 0 or key > self.get_length():
print 'The given key is wrong.'
return
else:
return self.set_elem(key, value)
def init_list(self, data): # 按列表給出 data
self.head = Node(data[0])
p = self.head # 指標指向頭結點
for i in data[1:]:
p.next = Node(i) # 確定指標指向下一個結點
p = p.next # 指標滑動向下一個位置
p.next = self.head
def get_length(self):
p, length = self.head, 0
while p != 0:
length += 1
p = p.next
if p == self.head:
break
return length
def is_empty(self):
if self.head == 0:
return True
else:
return False
def insert_node(self, index, value):
length = self.get_length()
if index < 0 or index > length:
print 'Can not insert node into the linked list.'
elif index == 0:
temp = self.head
self.head = Node(value, temp)
p = self.head
for _ in xrange(0, length):
p = p.next
print "p.value", p.value
p.next = self.head
elif index == length:
elem = self.get_elem(length-1)
elem.next = Node(value)
elem.next.next = self.head
else:
p, post = self.head, self.head
for i in xrange(index):
post = p
p = p.next
temp = p
post.next = Node(value, temp)
def delete_node(self, index):
if index < 0 or index > self.get_length()-1:
print "Wrong index number to delete any node."
elif self.is_empty():
print "No node can be deleted."
elif index == 0:
tail = self.get_elem(self.get_length()-1)
temp = self.head
self.head = temp.next
tail.next = self.head
elif index == self.get_length()-1:
p = self.head
for i in xrange(self.get_length()-2):
p = p.next
p.next = self.head
else:
p = self.head
for i in xrange(index-1):
p = p.next
p.next = p.next.next
def show_linked_list(self): # 列印連結串列中的所有元素
if self.is_empty():
print 'This is an empty linked list.'
else:
p, container = self.head, []
for _ in xrange(self.get_length()-1): #
container.append(p.value)
p = p.next
container.append(p.value)
print container
def clear_linked_list(self): # 將連結串列置空
p = self.head
for _ in xrange(0, self.get_length()-1):
post = p
p = p.next
del post
self.head = 0
def get_elem(self, index):
if self.is_empty():
print "The linked list is empty. Can not get element."
elif index < 0 or index > self.get_length()-1:
print "Wrong index number to get any element."
else:
p = self.head
for _ in xrange(index):
p = p.next
return p
def set_elem(self, index, value):
if self.is_empty():
print "The linked list is empty. Can not set element."
elif index < 0 or index > self.get_length()-1:
print "Wrong index number to set element."
else:
p = self.head
for _ in xrange(index):
p = p.next
p.value = value
def get_index(self, value):
p = self.head
for i in xrange(self.get_length()):
if p.value == value:
return i
else:
p = p.next
return -1
然後給出約瑟夫演算法:
def josephus_kill_1(head, m):
'''
環形單鏈表,使用 RingLinkedList 資料結構,約瑟夫問題。
:param head:給定一個環形單鏈表的頭結點,和第m個節點被殺死
:return:返回最終剩下的那個結點
本方法比較笨拙,就是按照規定的路子進行尋找,時間複雜度為o(m*len(ringlinkedlist))
'''
if head == 0:
print "This is an empty ring linked list."
return head
if m < 2:
print "Wrong m number to play this game."
return head
p = head
while p.next != p:
for _ in xrange(0, m-1):
post = p
p = p.next
#print post.next.value
post.next = post.next.next
p = post.next
return p
分析:
我採用了最原始的方法來解決這個問題,時間複雜度為o(m*len(ringlinkedlist))。
但是實際上,如果確定了連結串列的長度以及要刪除的步長,那麼最終剩餘的結點一定是固定的,所以這就是一個固定的函式,我們只需要根劇M和N確定索引就可以了,這個函式涉及到了數論,具體我就不細寫了。