Python實現單連結串列

Dictator丶發表於2019-01-10
"""
 @Time    : 2019/1/9 16:05
 @File    : LinkList.py
"""

class Node(object):
    def __init__(self, data, next_node=None):
        self.data = data
        self.next = next_node


class LinkList(object):
    def __init__(self):
        self.head = None

    def is_empty(self):
        return self.head is None

    def len_list(self):
        i = 0
        node = self.head
        while node:
            i += 1
            node = node.next
        return i

    #開頭新增元素
    def prepend_list(self, item):
        node = Node(item)
        next_node = self.head
        self.head = node
        node.next = next_node

    # 末尾新增元素
    def append_list(self, item):
        node = Node(item)
        if self.is_empty():
            self.head = node
        else:
            p = self.head
            while p.next:
                p = p.next
            p.next = node

    # 列印連結串列
    def print_list(self):
        node = self.head
        # print(type(node))
        list = []
        while node:
            list.append(node.data)
            node = node.next
        print(list)

    # 插入元素
    def insert_list(self, index, item):
        len = self.len_list()
        if index < 0:
            print("ERROR!")
        if len == 0:
            print('LinkList is Empty!')
        if index == 0:
            self.prepend_list(item)
        elif index >= len:
            self.append_list(item)
        else:
            i = 0
            node = Node(item)
            next_node = self.head
            # 下面幾行每次迴圈都要進行if判斷,時間複雜度高
            # while next_node:
            #     if index == i+1:
            #         p = next_node.next
            #         next_node.next = node
            #         node.next = p
            #         break
            #     i += 1
            #     next_node = next_node.next
            while i+1 < index:
                i += 1
                next_node = next_node.next
            p = next_node.next
            next_node.next = node
            node.next = p

    # 刪除表中第一個元素
    def del_first(self):
        if self.is_empty():
            print("LinkList is Empty!")
        fist_node = self.head
        second_node = fist_node.next
        self.head = second_node

    # 刪除表中最後一個元素
    def del_last(self):
        if self.is_empty():
            print("LinkList is Empty!")
        node = self.head
        # 下面幾行每次迴圈都要進行if判斷,時間複雜度高
        # while node:
        #     if node.next.next is None:
        #         node.next = None
        #     node = node.next
        len = self.len_list()
        i = 0
        while i < len-2:
            i += 1
            node = node.next
        node.next = None

    # 刪除指定位置的元素
    def del_index(self, index):
        if self.is_empty():
            print("LinkList is Empty!")
        len = self.len_list()
        if index < 0:
            print("ERROR!")
        elif index >= len:
            print("index is larger than len of LinkList!")
        elif index == 0:
            self.del_first()
        elif index == len-1:
            self.del_last()
        else:
            i = 0
            node = self.head
            while i+1 < index:
                node = node.next
                i += 1
            node.next = node.next.next

    # 查詢某一元素
    def search_list(self, item):
        node = self.head
        i = 0
        while node:
            if node.data == item:
                return i
            i += 1
            node = node.next
        return -1

    # 翻轉列表
    '''
    實現方法:從一個表的首端不斷取下結點,將其加入另一個表的首端,就形成了反轉的過程。 時間複雜度 O(n)
    就像將一摞書一本本拿下來疊成另一摞
    '''
    def reverse_list(self):
        new_list = None
        while self.head is not None:
            node = self.head
            self.head = node.next
            node.next = new_list   # 摘下來的結點的next應該指向上一個摘下來的結點
            new_list = node        # 將摘下來的結點和之前結點 加入到 新的結點序列
        self.head = new_list       # 指向反轉後的表頭結點

    # 列表排序,使用插入排序
    '''
    連結串列的排序有兩種方法:
        1. 移動每個結點之間的元素
        2. 調整結點之間的連結關係
    sort_list1 採用的是第一種
    sort_list2 採用的是第二種
    '''
    def sort_list1(self):
        """
        1. 設定掃描指標 cur_node, 從首結點的第二個結點開始。
        2. 掃描指標前面的結點序列都已經是排序好的
        3. 將掃描指標的值依次與掃描指標前面的結點序列中的值相比,如果序列中的值比掃描指標中的值大,
        則將掃描指標中的值與序列中的值替換,繼續用替換後的值與序列中的值比較,由於該序列已經是排序好的,
        所以替換後的值肯定比該序列未比較的值都小,即進行一系列的替換,完成已排序序列中元素的後移。
        4. 若序列都已經比較一遍,則掃描指標下移。
        :return:
        """
        cur_node = self.head.next
        while cur_node is not None:
            cur_data = cur_node.data
            p = self.head
            # 若 已排序序列中的元素比掃描指標的元素小,則序列指標向後移動,直到p指標為掃描指標或p的data大於掃描指標的data
            while p is not cur_node and p.data <= cur_data:
                p = p.next
            # 替換大元素,完成插入
            while p is not cur_node:
                p_data = p.data
                p.data = cur_data
                cur_data = p_data
                p = p.next
            # 若進行了while p is not cur_node:這個迴圈,則cur_data已經插入到排序好的序列中,
            # 但排序好的序列的最後一個元素已經被倒數第二個元素的值替換,所以 cur_node.data 的值應該是新的排序好序列的最後一個元素,
            # 所以進行賦值,將排序的最後一個元素的值複製給cur_node,若放在迴圈裡面,則每次都換替換 cur_node.data,沒有必要,只需最後替換
            cur_node.data = cur_data
            cur_node = cur_node.next

    def sort_list2(self):
        last = self.head
        cur_node = last.next
        while cur_node is not None:
            p = self.head
            q = None
            while p is not cur_node and p.data <= cur_node.data:
                q = p
                p = p.next
            if p is cur_node:
                last = cur_node
            else:
                last.next = cur_node.next
                cur_node.next = p
                if q is None:
                    self.head = cur_node
                else:
                    q.next = cur_node
            cur_node = last.next

link = LinkList()
for i in range(5):
    link.append_list(i)
print(link.len_list())
link.print_list()
link.prepend_list(10)
link.print_list()
link.insert_list(3, 100)
link.print_list()
link.del_first()
link.print_list()
link.del_last()
link.print_list()
link.del_index(3)
link.print_list()
index = link.search_list(0)
print(index)
link.reverse_list()
link.print_list()
link.append_list(74)
link.append_list(20)
link.append_list(2)
link.sort_list2()
link.print_list()
複製程式碼

參考:

  1. Python 單向連結表反轉與排序
  2. “資料結構與演算法(Python 語言)”教學材料

相關文章