1. 程式人生 > 其它 >學習筆記——連結串列的建立、增、刪、查(python實現)

學習筆記——連結串列的建立、增、刪、查(python實現)

技術標籤:連結串列python資料結構

這篇文章其實應該出在棧和佇列之前…咳 但是由於種種原因,我這個小白還是先接觸的棧和佇列(最初沒想用連結串列實現,後來發現python中連結串列實現棧和佇列更簡單,果斷選擇了連結串列實現)但是好處也是有的!!在瞭解完棧和佇列的後,我驚喜的發現連結串列也變得更易理解了(這算是意外驚喜吧)好了好了,廢話不多說,正式進入今天的主題——單向連結串列的實現(其他連結串列結構陸續更新)
依舊是老套路,首先了解其原理(呃…有關連結串列的概念網上有太多,我就直接搬過來一下),在加上一些自己的理解。
連結串列是由多個節點連結而成,每個節點又分為資料域和指向域。在這裡插入圖片描述
這裡我們可以注意到,尾結點指向域為(None),是它區分其他節點的標誌。

所以我們要想實現一個連結串列,需要定義其資料域(Data)、指向域(next)
原理到這裡就已經很清楚了,難點來了,如何在計算機中實現呢?答案肯定是運用“指標”,具體過程如下。
機器實現:
一、建立:
1.定義節點。
2.定義一個連結串列的頭指標head,便於操作此連結串列。
二、增加
3.頭插法建立連結串列(或者建立好後也可以呼叫此方法再新增元素):先判斷其是否為空,若為空則直接讓頭指標指向它;否則將頭部結點指標修改為新結點。
4.尾插法建立連結串列(或者建立後也可以呼叫此方法再新增元素):先判斷其是否為空,若為空則直接讓頭指標指向它;若它不為空,則我們要定義一個“尾指標”,即讓其從頭開始移動,移動到none則確定“尾”位置,此時再讓其指向新節點。
5.指定位置新增節點:實現此方法前,需要判斷一下指定位置在哪?若指定位置在0節點前,則採用頭插法;指定位置若在尾結點後,則呼叫尾插法;指定位置在中間時,定義一個遊標cur讓其從頭結點位置開始向後移動,知道指定位置,然後將新節點指向現在遊標的指向域,再讓遊標的指向域指向新節點。
三、刪除
刪除的過程在連結串列中實現算是比較難的一部分,根據我們定義了一個pre(當前指標所指的前一個元素)它可以分為兩種情況,一種是要刪除的元素就是頭節點,此時pre==None;第二種就是要刪除的元素為中間元素,此時pre不為空。具體實現是:定義一個遊標=head節點,當這個遊標所指的值等於要刪除的值時,則判斷它屬於那兩種情況中的哪一種,為第一種情況時,則直接讓頭節點指向當前遊標所指位置的下一個節點;第二種情況時,則讓pre=當前遊標所指位置,然後然當前遊標=當前遊標.next。如果此遊標值不等於要刪除的值時,則移動遊標。
四、查詢
傳入一個值,然後遍歷此連結串列看齊是否與此值相等,相等則返回True.
該過程的核心在於如何實現遍歷此連結串列,依舊是萬年不變的從頭節點開始移動指標,注意此時要返回可迭代的物件,才可方便實現查詢
具體程式碼實現如下:


class Node(object):
    """單鏈表的結點"""

    def __init__(self, item):
        # item存放資料元素
        self.item = item
        # next是下一個節點的標識
        self.next = None
class SingleLinkList(object):
    """單鏈表"""

    def __init__(self):
        self._head = None

    def is_empty(self):
        """判斷連結串列是否為空"""
        return self._head is None

    def length(self):
        """連結串列長度"""
        # 初始指標指向head
        cur = self._head
        count = 0
        # 指標指向None 表示到達尾部
        while cur is not None:
            count += 1
            # 指標下移
            cur = cur.next
        return count

    def items(self):
        """遍歷連結串列"""
        # 獲取head指標
        cur = self._head
        # 迴圈遍歷
        while cur is not None:
            # 返回生成器
            yield cur.item
            # 指標下移
            cur = cur.next

    def add(self, node):
        """向連結串列頭部新增元素"""
        node = Node(node)
        # 新結點指標指向原頭部結點
        if self.is_empty():
            # 空連結串列,_head 指向新結點
            self._head = node
        else:
            node.next = self._head
            # 頭部結點指標修改為新結點
            self._head = node

    def append(self, node):
        """尾部新增元素"""
        node = Node(node)
        # 先判斷是否為空連結串列
        if self.is_empty():
            # 空連結串列,_head 指向新結點
            self._head = node
        else:
            # 不是空連結串列,則找到尾部,將尾部next結點指向新結點
            cur = self._head
            while cur.next is not None:
                cur = cur.next
            cur.next = node

    def insert(self, index, item):
        """指定位置插入元素"""
        # 指定位置在第一個元素之前,在頭部插入
        if index <= 0:
            self.add(item)
        # 指定位置超過尾部,在尾部插入
        elif index > (self.length() - 1):
            self.append(item)
        else:
            # 建立元素結點
            node = Node(item)
            cur = self._head
            # 迴圈到需要插入的位置
            for i in range(index - 1):
                cur = cur.next
            node.next = cur.next
            cur.next = node

    def remove(self, item):
        """刪除節點"""
        cur = self._head
        pre = None
        while cur is not None:
            # 找到指定元素
            if cur.item == item:
                # 如果第一個就是刪除的節點
                if not pre:
                    # 將頭指標指向頭節點的後一個節點
                    self._head = cur.next
                else:
                    # 將刪除位置前一個節點的next指向刪除位置的後一個節點
                    pre.next = cur.next
                return True
            else:
                # 繼續按連結串列後移節點
                pre = cur
                cur = cur.next

    def find(self, item):
        """查詢元素是否存在"""
        return item in self.items()
if __name__ == '__main__':
        link_list = SingleLinkList()
    # 向連結串列尾部新增資料

        for i in range(5):
            link_list.append(0)
    # 向頭部新增資料
        link_list.add(6)
    # 遍歷連結串列資料
        for i in link_list.items():
            print(i, end='\t')
    # 連結串列資料插入資料
        link_list.insert(3, 9)
        print('\n', list(link_list.items()))
    # 刪除連結串列資料
        link_list.remove(0)
        for i in link_list.items():
            print(i, end='\t')
    # 查詢連結串列資料
        print(link_list.find(0))

PS:這裡yield返回的是可迭代的物件,即可直接用於for迴圈的物件,其類似於return,但區別在於其物件可迭代。