1. 程式人生 > >環形單鏈表的約瑟夫問題 Python版

環形單鏈表的約瑟夫問題 Python版

題目
一個環形單鏈表,從頭結點開始向後,指標每移動一個結點,就計數加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確定索引就可以了,這個函式涉及到了數論,具體我就不細寫了。