用python實現棧、單鏈表、雙鏈表

前言

推薦個網站,學習數據結構時可以到 visualgo這個網站,感受認識操作一些數據結構的整個動態執行過程,當我們在用代碼實現其數據結構的時候,它能給我們帶來一些code的思路

棧(stack),它是一種運算受限的線性表。其限制是僅允許在表的一端進行插入和刪除運算。

在這裏插入圖片描述

棧允許進行插入和刪除操作的一端稱爲棧頂(top),另一端爲棧底(bottom);棧底固定,而棧頂浮動;棧中元素個數爲零時稱爲空棧。插入一般稱爲進棧(PUSH),刪除則稱爲退棧(POP)。

python代碼實現

class Stack(object):
    def __init__(self,limit = 10):
        self.stack = []
        self.limit = limit
    def push(self,data):
        if len(self.stack) >= self.limit:
            raise IndexError("超出棧頂容量")
        #List append往左加元素
        self.stack.append(data) 
    def pop(self):
        if self.stack:
            return self.stack.pop()
        else:
            raise IndexError("已經空棧")
    def peek(self):
        if self.stack:
            return self.stack[-1]
    def is_empty(self):
        #bool()若沒有參數,返回False,判斷棧是否爲空
        return not bool(self.stack)

    def size(self):
        #查看棧中有幾個元素
        return len(self.stack)

    #以上即是實現一個棧的基本代碼

    #作業(用棧解決括號匹配問題)
    """算法思路,循環字符串的每一個字符("("或")"),如果是(,直接入棧
    如果是")",先判斷棧爲不爲空,若爲空,返回括號匹配錯誤,若不爲空,
    棧pop出一個元素,字符串的字符循環完之後,再判斷棧爲不爲空,若不爲空,
    返回括號匹配錯誤,若不爲空,返回括號匹配正確
    """
def balanced_parentheses(str):
    stack = Stack(len(str))
    for char in str:
        if char == "(":
            stack.push(char)
        elif char == ")":
            if stack.size() == 0:
                return False
            stack.pop()
    return stack.is_empty()

if __name__ == "__main__":
    examples  = ["(())","())","(()))"]
    for example in examples:
        print(balanced_parentheses(example))

單鏈表

鏈表(linked_list)是物理存儲單元上非連續的、非順序的存儲結構,數據元素的邏輯順序是通過鏈表的指針地址實現,每個元素包含兩個結點,一個是存儲元素的數據域 (內存空間),另一個是指向下一個結點地址的指針域。根據指針的指向,鏈表能形成不同的結構,例如單鏈表,雙向鏈表,循環鏈表等。而單鏈表中的每個節點只包含一個數據域和一個指針域(尾)。

在這裏插入圖片描述

想獲取對鏈表的更多認識可戳這篇文章數據結構中的鏈表,你知道多少?

python代碼實現

class Node:
    #初始化鏈點
    def __init__(self,data):
        self.data = data
        self.next = None

class Link_List:
    #初始化鏈表,注意初始化鏈表時head可能不存在
    def __init__(self,head = None):
        self.head = head

    #鏈表的添加功能
    def append(self,new_element):
        #current當前的
        current = self.head
        #當頭部節點存在
        if self.head:
            while current.next:
                current = current.next
            current.next = new_element
        #當頭部節點不存在
        else:
            self.head = new_element

    def is_empty(self):
        #判斷鏈表爲不爲空,只需要判斷head爲不爲空
        return not self.head

    def get_length(self):
        #求鏈表的長度
        temp  =self.head
        length = 0
        while temp != None:
            length = length + 1
            temp = temp.next
        return length
    
    def insert(self,position,new_element):
        #在鏈表指定索引處插入元素
        if position < 0 or position > self.get_length():
            raise IndexError("插入位置超出範圍")
        temp = self.head
        #當插入位置在第一位時候,把head變爲新節點
        if position == 0:
            new_element.next = temp
            self.head = new_element
            return
        i = 0
        while i < position:
            pre = temp
            temp = temp.next
            i+=1
        pre.next = new_element
        new_element.next = temp

    def remove(self,position):
        #刪除指定索引的鏈表元素
        if position < 0 or position > self.get_length():
            raise IndexError("要刪除的鏈表元素超出範圍")
        i = 0
        temp = self.head
        while temp != None:
            if position == 0:
                self.head = temp.next
                temp.next = None
                return

            pre = temp
            temp = temp.next
            i+=1
            if i == position:
                pre.next = temp.next
                temp.next = None
                return

    def print_list(self):
        #打印鏈表元素
        temp = self.head
        while temp is not None:
            print(temp.data)
            temp = temp.next

    def initlist(self,data_list):
        #將列表轉爲鏈表
        #創建頭結點
        self.head = Node(data_list[0])
        temp = self.head
        #逐個爲列表中的元素創建結點
        for i in data_list[1:]:
            node = Node(i)
            temp.next = node
            temp = temp.next
    def reverse(self):
        #將鏈表反轉
        """
        假設存在鏈表 1 → 2 → 3 → Ø,我們想要把它改成 Ø ← 1 ← 2 ← 3。
        在遍歷列表時,將當前節點的 next 指針改爲指向前一個元素。
        由於節點沒有引用其上一個節點,因此必須事先存儲其前一個元素。
        在更改引用之前,還需要另一個指針來存儲下一個節點。不要忘記在最後返回新的頭引用!
        """
        prev = None
        current = self.head
        while current:
            next_node = current.next
            current.next = prev #遍歷每一個結點,使其next指向前一個結點
            prev = current
            current = next_node
        self.head = prev

    #交換兩個數據特定的鏈表元素
    def swapNodes(self,node1,node2):
        #傳入的node1和node2是要交換的鏈表元素的數據,而不是鏈表元素

        prevD1 = None
        prevD2 = None

        #先判斷要實行元素交換的鏈表是否爲空,空退出
        if self.is_empty():
            return

        else:
            #判斷要交換的元素數據是否相同,相同退出
            if node1 == node2:
                return
            else:
                #根據node1和node2的值找出要交換的兩個鏈表元素
                D1 = self.head
                while D1 != None and D1.data != node1:
                    prevD1 = D1
                    D1 = D1.next
                D2 = self.head
                while D2 != None and D2.data != node2:
                    prevD2 = D2
                    D2 = D2.next
                
                #如果要交換的D1節點是head,做如下交換
                if prevD1 != None:
                    prevD1.next = D2
                else:
                    self.head = D2

                #如果要交換的D2節點是head,做如下交換
                if prevD2 != None:
                    prevD2.next = D1
                else:
                    self.head = D1

                #如果要交換的D1和D2均不是head,做如下交換
                temp = D1.next
                D1.next = D2.next
                D2.next = temp

if __name__ == "__main__":
    link_list = Link_List()
    link_list.append(Node(5))
    link_list.append(Node(4))
    link_list.append(Node(3))
    link_list.append(Node(2))
    link_list.append(Node(1))
    print("交換前")
    link_list.print_list()
    link_list.swapNodes(1,4)
    print("交換後")
    link_list.print_list()

雙鏈表

雙向鏈表(Double_linked_list)也叫雙鏈表,是鏈表的一種,它的每個數據結點中都有兩個指針,分別指向它的前一個結點和他的後一個結點。所以,從雙向鏈表中的任意一個結點開始,都可以很方便地訪問它的前驅結點和後繼結點。

在這裏插入圖片描述

python代碼實現

class Node():
    def __init__(self,data):
        #雙鏈表對比單鏈表,其中的元素多了一個頭指針(prev)
        self.data = data
        self.next = None
        self.prev = None


class DLinkList():

    """雙鏈表它不是循環鏈表"""    
    def __init__(self):
        self._head = None
    
    #判斷鏈表是否爲空
    def is_empty(self):
        return not self._head
    
    #獲取鏈表長度
    def get_length(self):
        count = 0
        current = self._head
        while current:
            count += 1
            current = current.next
        return count

    #打印鏈表中的元素
    def print_node(self):
        current = self._head
        while current != None:
            print(current.data)
            current = current.next
        print("到盡頭了")

    #鏈表頭部添加元素
    def add(self,data):
        new_node = Node(data)
        if self.is_empty():
            self._head = new_node
        else:
            new_node.next = self._head
            self._head.prev = new_node
            self._head = new_node

    #鏈表尾部插入數據
    def append(self,data):
        new_node = Node(data)

        #循環找到鏈表尾部元素
        current = self._head
        while current != None:
            current = current.next

        current.next = new_node
        new_node.prev = current

    #查詢特定數據的鏈表元素是否存在
    def search(self,data):
        current = self._head
        while current != None:
            if current.data == data:
                return True
            current = current.next
        return False

    #往特定位置插入鏈表元素
    def insert(self,position,data):
        #如果position <= 0,均往鏈表首插入
        if position <= 0:
            self.add(data)
        
        #如果position >= 鏈表長度,均往鏈表尾插入
        elif position >= self.get_length:
            self.append(data)
        
        #如果position既不 <= 0和 >= 0,則循環找到position-1的元素,讓其尾指針
        #指向插入的元素,讓其下一個節點頭指針指向插入的元素,而插入的元素的頭指針
        #指向位置position-1的元素,尾指針指向指向position-1的元素的下一個元素
        else:
            new_node = Node(data)
            current = self._head
            count = 0
            while count < (position-1):
                count += 1
                current = current.next
            new_node.prev =  current
            new_node.next = current.next
            current.next = new_node
            current.next.prev = new_node
    
    def remove(self,data):
        #刪除指定數據的鏈表元素

        #如果鏈表爲空則刪除錯誤
        if self.is_empty:
            return
        else:
            current = self._head
            if current.data == data:
                if current.next == None:
                    self._head = None
                else:
                    current.next.prev = None
                    self._head = current.next
                return
            while current != None:
                current = current.next
                if current.data == data:
                    current.prev.next = current.next
                    current.next.prev = current.prev
                    break
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章