python數據結構——鏈表及其實現

一、單向鏈表

(1) 鏈表的定義

鏈表是一種常見的數據結構,是一種線性表,但是不像順序表一樣連續存儲數據,而是再每一個節點(數據存儲單元)裏存放下一個節點的位置信息(即地址)。

"""
鏈表的實現: list = [100, 200, 300]
   | 內存 | 數據區| 下一個節點地址|
地址1:0x11   100  0x34
地址2:0x34   200  0x20
地址3:0x20   300  None
那麼列表實現就如圖所示:
"""

在這裏插入圖片描述

(2)爲什麼需要鏈表
  1. 順序表的構建需要預先知道數據大小來申請一塊連續的存儲空間,而在進行擴充時又需要進行數據的搬遷,所以使用起來不是很靈活,引入鏈表結構可以充分利用計算機內存空間,實現靈活的動態管理。
  2. 另外,如果現在需要存儲一個較大的數據,連續的內存不夠用,也可以採用鏈表進行分散的存儲,然後將數據鏈接在一起。
(3)單向鏈表
  1. 單向鏈表也叫單鏈表,是鏈表中最簡單的一種形式,它的每個節點包含兩個域,一個信息域(元素域)和一個鏈接域,最後一個節點的鏈表域則指向一個空值。
  2. 單向鏈表結點:
    在這裏插入圖片描述
  3. 單向鏈表:
    在這裏插入圖片描述
  4. 變量P指向鏈表的頭結點的位置,從P出發能找到表中的任意結點
(4)單向循環列表

單向循環鏈表是將單向鏈表尾結點的next 指向頭結點
在這裏插入圖片描述

(5)雙向鏈表
  1. 概述

雙向鏈表或者雙面鏈表,每個結點有兩個鏈表,一個指向前一個結點,當此結點爲第一個結點時,指向空,而另一個指向下一個結點,當此結點爲最後一個結點時指向空值。
2. 雙向鏈表結構 在這裏插入圖片描述其中:P爲前趨結點 N 爲後繼結點

二、單向鏈表實現

class Node(object):
    """節點"""
    def __init__(self, elem):
        super(Node, self).__init__()
        # 元素
        self.elem = elem
        # 下一個節點地址
        self.next = None


class SingleLinkList(object):
    """單鏈表:實現增、刪、改、查"""
    def __init__(self, node=None):
        self.__head = node
   
    def is_empty(self):
        """鏈表爲是否爲空 """
        return self.__head is None

    def length(self):
        """鏈表長度"""
        cur = self.__head  # 定義遊標cur,用來遍歷節點
        count = 0  # 統計節點個數
        while cur is not None:
            count += 1
            cur = cur.next
        return count

    def travel(self):
        """ 遍歷整個鏈表"""
        cur = self.__head
        while cur is not None:
            print("當前的節點是:%s" % cur.elem)
            cur = cur.next

    def add(self, item):
        """鏈表頭部添加元素,頭插法"""
        node = Node(item)
        node.next = self.__head
        self.__head = node

    def append(self, item):
        """鏈表尾部添加元素,尾插法"""
        node = Node(item)
        if self.is_empty():
            self.__head = node
        else:
            cur = self.__head
            while cur.next is not None:
                cur = cur.next
            cur.next = node

    def insert(self, pos, item):
        """
        指定位置添加元素 pos: 位置  item:元素
        pos: 從0開始
        """
        if pos <= 0:
            self.add(item)
        elif pos > (self.length() - 1):
            self.append(item)
        else:
            pre = self.__head  # 前一個位置
            count = 0
            while count < (pos - 1):
                count += 1
                pre = pre.next
            # 當循環退出後pre = pos -1 的位置
            node = Node(item)
            node.next = pre.next
            pre.next = node

    def remove(self, item):
        """
        刪除節點 : 考慮列表爲空,刪除列表的頭節點, 只有一個節點,尾部的節點
        """
        cur = self.__head
        pre = None
        while cur is not None:
            if cur.elem == item:
                # 判斷次節點是否爲頭節點
                if cur == self.__head:
                    self.__head = cur.next
                else:
                    pre.next = cur.next
                break
            else:
                pre = cur
                cur = cur.next

    def search(self, item):
        """查找節點是否存在"""
        cur = self.__head
        while cur is not None:
            if cur.elem == item:
                return True
            else:
                cur = cur.next
        return False


if __name__ == '__main__':
    ll = SingleLinkList()
    print(ll.is_empty())
    ll.append(1)
    ll.append(100)
    ll.append(200)
    ll.travel()
    ll.remove(1)
    ll.travel()

二、單向循環列表實現

class Node(object):
    def __init__(self, item):
        """結點"""
        self.elem = item
        self.next = None


class SingleLinkCircle(object):
    """單向循環鏈表"""

    def __init__(self, node=None):
        self.__head = node
        if node:
            node.next = node

    def is_empty(self):
        """判斷是否爲空"""
        return self.__head is None

    def length(self):
        """判斷鏈表長度"""
        if self.is_empty():
            return 0
        else:
            cur = self.__head
            count = 1
            while cur.next != self.__head:
                count += 1
                cur = cur.next
            return count

    def travel(self):
        """遍歷鏈表"""
        if self.is_empty():
            print("")
        else:
            cur = self.__head
            while cur.next != self.__head:
                print(cur.elem, end=" ")
                cur = cur.next
            # 循環結束打印最後一個結點
            print(cur.elem)

    def add(self, item):
        """在頭部添加結點"""
        node = Node(item)
        if self.is_empty():
            self.__head = node
            node.next = node
        else:
            cur = self.__head
            while cur.next != self.__head:
                cur = cur.next
            node.next = self.__head
            self.__head = node
            cur.next = node

    def append(self, item):
        """在尾部添加結點"""
        node = Node(item)
        if self.is_empty():
            self.__head = node
            node.next = self.__head
        else:
            cur = self.__head
            while cur.next != self.__head:
                cur = cur.next
            node.next = self.__head
            cur.next = node

    def insert(self, pos, item):
        """在特定位置插入結點"""
        if pos <= 0:
            self.add(item)
        elif pos > (self.length() - 1):
            self.append(item)
        else:
            pre = self.__head
            count = 0
            while count < (pos - 1):
                count += 1
                pre = pre.next
            node = Node(item)
            node.next = pre.next
            pre.next = node

    def remove(self, item):
        """刪除指定結點"""
        cur = self.__head
        pre = None
        if self.is_empty():
            return
        while cur.next != self.__head:
            if cur.elem == item:
                # 頭結點
                if cur == self.__head:
                    # 找到尾結點
                    finall = self.__head
                    while finall.next != self.__head:
                        finall = finall.next
                        # 將尾結點的地址指向要刪除結點的下一個結點
                    finall.next = cur.next
                    self.__head = cur.next
                else:
                    # 中間結點
                    pre.next = cur.next
                return    #  這裏注意,刪除完成後讓程序直接退出,不用break
            else:
                pre = cur
                cur = cur.next
        # 判斷刪除的是尾結點
        if cur.elem == item:
            if cur == self.__head:
                self.__head = None
            else:
                pre.next = self.__head

    def search(self, item):
        """查找結點"""
        if self.is_empty():
            return False
        else:
            cur = self.__head
            while cur.next != self.__head:
                if cur.elem == item:
                    return True
                cur = cur.next
            if cur.elem == item:
                return True
            return False


if __name__ == '__main__':
    ll = SingleLinkCircle()
    ll.add(3)
    ll.add(4)
    print("test add()\n")
    ll.travel()
    ll.append(5)
    ll.append(6)
    print("test append()\n")
    ll.travel()
    ll.insert(2, 9)
    ll.insert(3, 0)
    print("test insert()\n")
    ll.travel()
    ll.remove(4)
    ll.remove(6)
    print("test remove()\n")
    ll.travel()
    print("test search()\n")
    ll.search(5)
    print(ll.length())

三、雙向鏈表實現

class Node(object):
    """node"""
    def __init__(self, item):
        self.elem = item
        self.prev = None
        self.next = None


class DoubleLinkList(object):
    def __init__(self, node=None):
        self.__head = node

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

    def length(self):
        cur = self.__head
        count = 0
        while cur is not None:
            count += 1
            cur = cur.next
        return count

    def travel(self):
        cur = self.__head
        while cur is not None:
            print(cur.elem, end=" ")
            cur = cur.next
        print("")

    def add(self, item):
        node = Node(item)

        """method one"""
        # node.next = self.__head
        # self.__head = node
        # node.next.prev = node

        """method two"""
        self.__head.prev = node
        self.__head = node

    def append(self, item):
        node = Node(item)
        if self.is_empty():
            self.__head = node
        else:
            cur = self.__head
            while cur.next is not None:
                cur = cur.next
            cur.next = node
            node.prev = cur

    def insert(self, pos, item):
        node = Node(item)
        if pos <= 0:
            self.add(item)
        elif pos > (self.length()-1):
            self.append(item)
        else:
            cur = self.__head
            count = 0
            while count < pos:
                count += 1
                cur = cur.next
            # node.prev = cur
            # node.next = cur.next
            # cur = node
            # cur.next = node
            """ method"""
            node.next = cur
            node.prev = cur.prev
            cur.prev = node
            node.prev.next = node

    def remove(self, item):
        cur = self.__head
        while cur is not None:
            if cur.elem == item:
                if cur == self.__head:
                    self.__head = cur.next
                    if cur.next:
                        # only one node
                        cur.next.prev = None
                else:
                    cur.prev.next = cur.next
                    if cur.next:
                        # finally node
                        cur.next.prev = cur.prev
                break
            else:
                cur = cur.next

    def search(self, item):
        cur = self.__head
        while cur is not None:
            if cur.elem == item:
                return True
            else:
                cur = cur.next
        return False


if __name__ == '__main__':
    lk = DoubleLinkList()
    lk.append(2)
    lk.append(3)
    lk.insert(1, 0)
    lk.append(4)
    lk.append(5)
    lk.add(6)
    lk.travel()
    lk.remove(6)
    lk.travel()
    print(lk.length())
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章