python中棧的單鏈表實現

參考博客:https://www.cnblogs.com/stacklike/p/8284550.htmlhtml

基於列表的簡單實現

# 先進後出
# 以列表實現的簡單棧
class SimpleStack:
    # 特殊屬性,用以限制class可添加的屬性
    __slots__ = ('__items',)

    def __init__(self):
        self.__items = []

    def is_empty(self):
        return self.__items == []

    def peek(self):
        return self.__items[len(self.__items)-1]

    def size(self):
        return len(self.__items)

    def push(self, item):
        self.__items.append(item)

    def pop(self):
        self.__items.pop()
View Code

以單鏈表的形式實現棧

class StackFullException(Exception):  # 滿棧時要拋出的異常
    pass


class StackEmptyException(Exception):  # 空棧時要拋出的異常
    pass


class Node:
    def __init__(self, val=None, nxt=None):
        self.value = val  # 信息域
        self.next = nxt   # 指針域

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


class Stack:
    # 初始化一個空棧
    def __init__(self, max=0):
        self._top = None  # 棧的頂部元素
        self._max = 0  # 棧的最大高度
        self.max = max  # 用戶將設置的最大棧高度

    @property
    def length(self):
        if self._top is None:
            return 0
        node = self._top
        count = 1  # 只要不爲空,就至少有一個節點,所以由1開始
        # 藉由節點內的指針來判斷是否有下一個元素,只要就由當前節點跳到下一個節點,並將計數加1
        while node.next:
            node = node.next
            count += 1
        return count

    @property
    def is_empty(self):
        return self._top is None

    @property
    def is_full(self):
        # 滿棧的條件是棧的最大高度不是無限的(設置最大值時會將負數也轉爲0,0就表明了無限大小)
        # 並且當前棧高等於容許的最大棧高
        return bool(self._max and self.length == self._max)

    @property
    def max(self):
        return self._max

    @max.setter
    def max(self, m):
        m = int(m)  # 可能傳入值是str或float
        if m < self.length:  # 設置值是否小於當前棧的高度,是則要拋出異常
            raise Exception('Stack resize failed, please pop some elements first.')
        self._max = 0 if m < 0 else m  # 輸入值又是不是負數或0,是則都設置爲0,看成無限大小

    # 經過逐個壓入傳入的iterable,由空棧構建出一個棧
    def init(self, iterable=()):
        if not iterable:  # 傳入一個可迭代對象
            return
        self._top = Node(iterable[0])  # 將其起始元素設置爲棧頂
        for item in iterable[1::]:  # 將以後的元素也依次壓入棧中,每一次壓入棧定元素都會被替換
            node = self._top  # 原棧頂元素先儲存起來
            self._top = Node(item)  # 將當前元素設置爲棧頂
            self._top.next = node  # 將設置過的棧定的指針指向原來的棧頂

    """
    |   5   |
    |   4   |
    |   3   |
    |   2   |
    |   1   |  顯示的樣板
    """
    def show(self):
        # 定義的子函數是爲了遍歷棧,這裏用到了生成器
        def _traversal(self):
            node = self._top
            while node and node.next:
                yield node
                node = node.next
            # 這裏若是不yield,則棧底的元素會沒法被遍歷到,由於最後一個元素並不知足while循環的條件,會停止迭代
            yield node
        # <>^ 左/右/居中對齊
        # 生成器也是可迭代的,這裏用高階函數將字符串格式方法映射到每個元素上
        print('\n'.join(map(lambda x: '|{:^7}|'.format(str(x)), _traversal(self))) + '\n ' + 7 * '-')

    def push(self, item):
        # 若是棧已滿,則拋出異常
        if self.is_full:
            raise StackFullException('Error: trying to push an item into a full stack.')
        # 若是棧是空的,則直接將item設置爲棧頂,返回便可,由於不須要設置指針
        if not self._top:
            self._top = Node(item)
            return
        node = self._top  # 先取到原棧頂
        self._top = Node(item)  # 設置item爲棧頂
        self._top.next = node  # 將設置過的棧頂的指針指向原棧頂

    def pop(self):
        if self.is_empty:
            raise StackEmptyException('Error: trying to pop from an empty stack.')
        node = self._top  # 先取到原棧頂
        self._top = self._top.next  # 將棧頂設置爲原棧頂的下一個元素
        return node.value  # 返回原棧頂的值

    def top(self):
        return self._top.value if self._top else None

    def clear(self):  # 在已構造的方法上再構造新方法
        while self._top:
            self.pop()


s = Stack()
s.init([1, 2, 3, 4, 5])
s.show()
View Code
相關文章
相關標籤/搜索