【python鏈表】之單向鏈表詳解


參考學習視頻

python03-04-01單向鏈表

一、單向鏈表介紹

鏈表(Linked list)是一種常見的基礎數據結構,是一種線性表,但是並不會按線性的順序存儲數據,而是在每一個節點裏存到下一個節點的指針(Pointer)。像鎖鏈一樣,由一節節節點連在一起,組成一條數據鏈。

1.1 鏈表節點結構:

在這裏插入圖片描述

1.2 單向鏈表的結構

img

1.3 單鏈表和單向循環鏈表

  1. 單鏈表:每個節點只有一個屬性.next,用於存放其後繼節點;尾節點的後繼爲None;若鏈表爲空,則頭節點.head爲None。
  2. 單向循環鏈表:每個節點只有一個屬性.next,用於存放其後繼節點;由於循環,故尾節點的後繼爲頭節點;若鏈表爲空,則頭節點.head爲None。

二、操作單鏈表

2.1 常用方法(自己定義的)

方法 作用
is_empty() 鏈表是否爲空
length() 鏈表長度
travel() 遍歷整個鏈表
add(item) 鏈表頭部添加元素
append(item) 鏈表尾部添加元素
insert(pos, item) 指定位置添加元素
remove(item) 刪除節點
search(item) 查找節點是否存在

2.2 單向鏈表的實現

1、單節點類結構
class SingleNode(object):
    """單鏈表的結點"""
    def __init__(self,item):
        # item存放數據元素
        self.item = item
        # next是下一個節點的標識
        self.next = None
2、單鏈表的增刪改查
# #
class Node():
    """表節點結構實現  私有屬性__next是指向下個節點的指針,__value爲此節點的值"""
    def __init__(self, value=None, next=None, ):
        self._value = value
        self._next = next

    # 將方法封裝
    def getValue(self):
        return self._value

    def getNext(self):
        return self._next

    def setvalue(self, value):
        self._value = value

    def setNext(self, next):
        self._next = next
        
        

class SingleLinkList(object):
    """操作單鏈表的方法"""
    def __init__(self, Node=None):
        """設置一個頭節點"""
        self.head = Node

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

    def add(self, node):
        """向鏈表頭添加輸入"""
        # 將插入元素實例化
        tmp = Node(node)
        # 如果鏈表爲空,則讓頭指針指向實例化的節點
        if self.is_empty():
            self.head = tmp
        else:
            # 如果鏈表不爲空,則先將頭部節點指向的節點(內存地址),賦值給要插入節點的指針域
            # 然後將頭部節點指針域指向要插入的節點
            tmp.setNext(self.head)
            self.head = tmp

    def append(self, node):
        """向鏈表尾添加數據"""
        end_Node = Node(node)
        cursor = self.head
        # 判斷列表是否爲空,如果爲空,則頭部插入
        if self.is_empty():
            self.add(end_Node)
        else:
            # 如果不爲空,
            while cursor.getNext() is not None:
                cursor = cursor.getNext()
            cursor.setNext(end_Node)

    def tarver(self):
        """遍歷整個鏈表"""
        cur = self.head
        while cur is not None:
            print(cur.getValue(), end=" ")
            cur = cur.getNext()
        print()  # 換行

    def length(self):
        """鏈表長度"""
        cur = self.head
        count = 0
        while cur is not None:
            count += 1
            cur = cur.getNext()
        return count

    def insert(self, index, node):
        """指定位置插入鏈表"""
        tmp = Node(node)
        if self.is_empty():
            print("鏈表爲空")
            return
        elif index <= 0:
            # 如果在頭部直接插入
            self.add(node)

        elif index > self.length():
            # 如果大於鏈表長度,則在尾部插入
            self.append(node)

        else:
            count = 0
            cur = self.head
            while count < (index - 1):
                count += 1
                cur = cur.getNext()
            tmp.setNext(cur.getNext())
            cur.setNext(tmp)

    def remove(self, index):
        """通過索引 刪除節點"""
        if self.is_empty():
            print("鏈表爲空")
            return

        if index < 0 or index > self.length()-1:
            print("索引範圍超出鏈表長度!")
            return

        # 刪除索引爲0的元素
        elif index == 0:
            self.head = self.head.getNext()
        else:
            cur = 0  # 索引
            pre = self.head
            while cur < index-1:
                cur += 1
                pre = pre.getNext()
            pre.setNext(pre.getNext().getNext())


    def search(self, value):
        """鏈表查找節點是否存在,並返回True或者False"""
        cur = self.head
        if self.is_empty():
            print("鏈表爲空!")
            return
        while cur != None:
            if cur.getValue() == value:
                return True
            cur = cur.getNext()
        return False
        
    def change(self, index, value):
        """鏈表內容替換"""
        if self.is_empty():
            print("鏈表爲空!")
            return

        if index < 0 or index > self.length()-1:
            print("索引範圍超出鏈表長度!")
            return
        
        node = self.head
        for i in range(self.length()):
            if i == index:
                node.setvalue(value)
                return
            node = node.getNext()


if __name__ == '__main__':
    obj = SingleLinkList()
    obj.add(1)
    obj.tarver()
    obj.append(2)
    obj.append(4)
    obj.add(7)
    obj.tarver()
    obj.insert(3, 5)
    obj.tarver()
    obj.remove(1)
    obj.tarver()
    print(obj.search(2))
    obj.tarver()
    obj.change(2, 55) 
    obj.tarver()



3、反轉單鏈表

"""
 翻轉一條單鏈表
Input: 1->2->3->4->5->NULL
Output: 5->4->3->2->1->NULL

"""

class ListNode:
    def __init__(self, x, Next=None):
        self.val = x
        self.next = Next

# 遍歷替換法
def ReverseList(head):
    if head == None or head.next == None:
        return head

    last = None  # 前置節點
    while head:
        tmp = head.next  # 保存當前節點的下一個節點,不可缺,因爲後面更改了當前節點的next指向
        head.next = last  # 更改當前節點的next爲上一個節點
        last = head  # 將上一個節點移動到當前節點
        head = tmp   # 當前節點移動到下一個節點
        # head.next, last, head = last, head, head.next 可以簡寫成
    return last


if __name__ == '__main__':
    # 創建一個1-5的鏈表
    a = ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5,)))))
    Node = ReverseList(a)

    while Node:
        print(Node.val)
        Node = Node.next

結果:

5
4
3
2
1
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章