python實現基本資料結構第二篇(順序棧、鏈棧,順序隊、鏈隊)

python小明發表於2020-10-23

棧(stack):是限定僅在表尾進行插入或刪除操作的線性表。表尾存在特殊含義,稱為棧頂,表頭稱為棧底,不含資料元素的空表稱為空棧。
棧用自己通俗的話講,其實類似一個圓桶,桶口相當於棧頂,桶底相當於棧底,往桶裡裝盤子就相當於往棧裡壓入資料,要取出第一壓入棧中的資料元素,就必須從桶口依次取出,這樣才能取出第一個放進桶裡的盤子,即第一入棧的資料元素,這就是所謂的先進後出原則。

順序棧的python實現:

class StackUnderflow(ValueError):   #定義空棧訪問時,棧下溢位
    pass

class sqStack():    #基於順序表實現的棧
    #建棧,初始化棧,底層使用的是python的list來實現
    def __init__(self):
        self._elems = []

    #判棧空
    def is_empty(self):
        return self._elems == []

    # 求棧頂元素
    def top(self):
        if self._elems == []:
            raise StackUnderflow("in sqStack.top()")
        else:
            return self._elems[-1]

    #壓棧
    def push(self,elem):
        self._elems.append(elem)

    #出棧
    def pop(self):
        if self._elems == []:
            raise StackUnderflow("in sqStack.top()")
        else:
            return self._elems.pop()

鏈棧的python實現:
鏈棧其實類似於順序棧,順序棧是在順序表的基礎上加了只能在順序表的表尾進行新增刪除操作,鏈棧是在連結串列的額基礎上增加了一些操作上的限制,只能在連結串列的表尾進行操作,即只能使用尾插法插入元素,也只能在表尾刪除元素。為了能夠不從表頭開始尋找才能找到表尾,節省時間,定義一個指標,每次壓棧或者出棧,指標始終指向的是表尾元素,這樣就實現了一個鏈棧。

class LNode():  #定義鏈棧中節點
    def __init__(self,elem,next_=None):
        self.elem=elem
        self.next=next_

    def __str__(self):
        return str(self.elem)

class StackUnderflow(ValueError):   #定義異常類
    pass

class LStack(): #基於連結串列技術實現的棧類,用LNode作為節點
    #建棧,初始化棧
    def __init__(self):
        self._top = None

    #判棧空
    def is_empty(self):
        return self._top is None

    #求棧頂元素
    def top(self):
        if self._top is None:
            raise StackUnderflow("in LStack.top()")
        else:
            return self._top.elem

    #壓棧
    def push(self,elem):
        self._top = LNode(elem,self._top)

    #出棧
    def pop(self):
        if self._top is None:
            raise StackUnderflow("in LStack.pop()")
        else:
            p=self._top
            self._top = p.next
            return p.elem

if __name__ == "__main__":
    #建立結點
    n1 = LNode(1)
    n2 = LNode(2)
    n3 = LNode(3)
    n4 = LNode(4)
    n5 = LNode(5)
    #例項化鏈棧
    mystack = LStack()
    # 壓棧
    mystack.push(n1)
    mystack.push(n2)
    mystack.push(n3)
    mystack.push(n4)
    mystack.push(n5)
    # 出棧
    print(mystack.pop())
    print(mystack.pop())
    print(mystack.pop())
    #求棧頂
    print("現在的棧頂元素為:",mystack.top())

順序佇列的python實現:

class my_queue1():
    #初始化
    def __init__(self,max_lenght):
        self.list = []
        self.max_lenght = max_lenght

    #入隊操作
    def put_in(self,data):
        #尾部進隊,頭部出
        self.list.append(data)

        #頭部進隊,尾部出
        # self.list.insert(0,data)

    # 出隊操作
    def put_out(self):
        # 頭部出
        return self.list.pop(0)

        #尾部出
        # return self.list.pop()

    #判斷佇列是否為空
    def is_empty(self):
        if self.list == []:
            return True
        else:
            return False

    #求佇列長度
    def get_lenght(self):
        return len(self.list)

    #判斷佇列是否為滿:
    def is_full(self):
        if len(self.list) < self.max_lenght:
            return False
        else:
            return True



class my_queue2():
    #初始化
    def __init__(self):
        self.list = []
        self.front = 0
        self.rear = 0

    #判斷佇列是否為空
    def is_empty(self):
        if self.front == self.rear:
            return True
        else:
            return False

    #入隊
    def put_in(self,data):
        #隊尾進,隊頭出
        self.list.append(data)
        self.rear += 1
        #隊頭進,隊尾出
        # self.list.insert(0,data)

    #出隊
    def put_out(self):
        #隊尾進,隊頭出

        if self.rear > self.front:
            return self.list.pop(0)

        else:
            return 'this queue is empty'

        #隊頭進,隊尾出
        # self.list.pop()

    #求隊首元素
    def get_queue_front(self):
        if self.is_empty():
            return 'this queue is empty'
        return self.list[self.front]

    # 求隊尾元素
    def get_queue_rear(self):
        if self.is_empty():
            return 'this queue is empty'
        return self.list[self.rear-1]

    #求隊長
    def get_lenght(self):
        return self.rear - self.front

    def get_count(self):
        return len(self.list)

if __name__ == '__main__':
    # my_queue1 = my_queue1(100)
    # for i in range(10):
    #     #入隊
    #     my_queue1.put_in(i)
    #
    # #求隊長
    # print(my_queue1.get_lenght())
    #
    # #出隊
    # for i in range(my_queue1.get_lenght()):
    #     print(my_queue1.put_out())



    my_queue2 = my_queue2()
    for  j in range(10):
        #入隊
        my_queue2.put_in(j)
    #求隊長
    print(my_queue2.get_lenght())

    #出隊
    for j in range(my_queue2.get_lenght()):
        print(my_queue2.put_out())

鏈隊的python實現:

#方法一:
# 首尾指標實現
# 鏈隊 首尾指標實現鏈隊
class Node():
    def __init__(self, value=None):
        self.value = value
        self.next = None

class StcakQueue():
    def __init__(self):
        self.front = Node()
        self.rear = Node()
        self.size = 0

    def enqueue(self, value):
        node = Node(value)
        if self.size == 0:
            self.front = node
            self.rear = node
        else:
            self.rear.next = node
            self.rear = node
        self.size += 1

    def dequeue(self):
        if self.size == 0:
            raise Exception('queue is empty')
        else:
            temp = self.front.value
            self.front = self.front.next
            self.size -= 1
            return temp

    def is_empty(self):
        if self.size == 0 :
            return False
        else:
            return True

    def top(self):
        if self.size == 0 :
            raise LookupError('queue is empty')
        else:
            return self.front.value

    def size(self):
        return self.size

    def __str__(self):
        if self.size == 0:
            return None
        else:
            stack_list = []
            temp, count = self.front, self.size
            while count > 0 :
                stack_list.append(temp.value)
                temp = temp.next
                count -= 1
            return str(stack_list)
       

if __name__ == "__main__":
    i = StcakQueue()
    for x in range(0,6):
        i.enqueue(x)
        print(i)
    i.dequeue()
    print(i, i.size)
# 尾插有頭結點實現鏈隊
# 鏈隊 尾插法 有頭結點實現鏈隊
class Node(): #結點類
    def __init__(self,elem):
        self.elem = elem # 資料域,用來存放資料元素
        self.next = None # 指標域,指向下一個結點

    def __str__(self):
        return str(self.elem)


class Queue(): # 佇列
    def __init__(self): # 佇列初始化
        self.head = None # 構造私有頭結點
    
    def is_empty(self):
        return self.head == None

    def enqueue(self,elem): # 進佇列(正常向後填元素)
        node = Node(elem) # 建立新結點
        if self.is_empty(): # 如果為空, 新建head結點
            self.head = Node
            self.head.next = node
            node = self.head
        else:
            current = self.head
            while current.next is not None:
                current = current.next
            current.next = node

    def dequeue(self): # 出佇列(頭出)
        if not self.is_empty():
            current = self.head.next
            self.head.next = self.head.next.next
            return current.elem
        else:
            raise IndexError('pop from a empty stack')
    
    def size(self):
        current = self.head
        count = 0
        while current.next is not None:
            current = current.next
            count += 1
        return count

    def __repr__(self):
        stack_list = []
        current = self.head
        while current.next is not None:
            stack_list.append(current.next.elem)
            current = current.next
        return str(stack_list)

    __str__ = __repr__


if __name__ == "__main__":
    i = Queue()
    for x in range(0, 6):
        i.enqueue(x)
        print(i)

    i.dequeue()
    print(i, i.size())

本文通過自我總結完成,同時也借鑑了大佬文章

相關文章