• Python与数据结构[1] -> 栈/Stack[0] -> 链表栈与数组栈的 Python 实现


    / Stack


    目录

    1. 链表栈
    2. 数组栈

    栈是一种基本的线性数据结构(先入后出FILO),在 C 语言中有链表和数组两种实现方式,下面用 Python 对这两种栈进行实现。

    1 链表栈

    链表栈是以单链表为基础实现的栈数据结构,主要有以下几个关键点:

    1. 栈顶元素:栈顶元素即为链表的头结点
    2. 压栈:向链表的头结点插进入栈元素,无表头链表则替换插入元素为头结点
    3. 弹栈:弹出链表头结点,并将链表头结点替换为下一个元素
    Stack based on linked list:
            | item3 |
            |   |   |
            |   V   |
            | item2 |
            |   |   |
            |   V   |
            | item1 |
             -------

    完整代码

      1 class StackEmptyException(Exception): pass
      2 
      3 
      4 class StackFullException(Exception): pass
      5 
      6 
      7 class Node:
      8     def __init__(self, val=None, nxt=None):
      9         self.value = val
     10         self.next = nxt
     11 
     12     def __str__(self):
     13         return str(self.value)
     14 
     15 
     16 class Stack:
     17     """
     18     Stack based on linked list:
     19         | item3 |
     20         |   |   |
     21         |   V   |
     22         | item2 |
     23         |   |   |
     24         |   V   |
     25         | item1 |
     26          -------
     27     """
     28     def __init__(self, max=0):
     29         self._top = None
     30         self._max = 0
     31         self.max = max
     32 
     33     @property
     34     def max(self):
     35         return self._max
     36 
     37     @max.setter
     38     def max(self, m):
     39         m = int(m)
     40         if m < self.length:
     41             raise Exception('Resize stack failed, please pop some elements first.')
     42         self._max = m
     43         if self._max < 0:
     44             self._max = 0
     45 
     46     def init(self, iterable=()):
     47         if not iterable:
     48             return
     49         self._top = Node(iterable[0])
     50         for i in iterable[1:]:
     51             node = self._top
     52             self._top = Node(i)
     53             self._top.next = node
     54         
     55     def show(self):
     56         def _traversal(self):
     57             node = self._top
     58             while node and node.next:
     59                 yield node
     60                 node = node.next
     61             yield node
     62         print('
    '.join(map(lambda x: '|{:^7}|'.format(str(x)), _traversal(self)))+'
     '+7*'-')
     63 
     64     @property
     65     def length(self):
     66         if self._top is None:
     67             return 0
     68         node = self._top
     69         i = 1
     70         while node.next:
     71             node = node.next
     72             i += 1
     73         return i
     74 
     75     @property
     76     def is_empty(self):
     77         return self._top is None
     78 
     79     @property
     80     def is_full(self):
     81         return bool(self._max and self.length == self._max)
     82 
     83     def push(self, item):
     84         if self.is_full:
     85             raise StackFullException('Error: trying to push element into a full stack!')
     86         if not self._top:
     87             self._top = Node(item)
     88             return
     89         node = self._top
     90         self._top = Node(item)
     91         self._top.next = node
     92 
     93     def pop(self):
     94         if self.is_empty:
     95             raise StackEmptyException('Error: trying to pop element from an empty stack!')
     96         node = self._top
     97         self._top = self._top.next
     98         return node.value
     99 
    100     def top(self):
    101         return self._top.value if self._top else self._top
    102 
    103     def clear(self):
    104         while self._top:
    105             self.pop()
    106 
    107 
    108 def test(stack):
    109     print('
    Show stack:')
    110     stack.show()
    111 
    112     print('
    Init linked list:')
    113     stack.init([1, 2, 3, 4, 5])
    114     stack.show()
    115 
    116     print('
    Push element to stack:')
    117     stack.push(6)
    118     stack.push(7)
    119     stack.push('like')
    120     stack.show()
    121 
    122     print('
    Check top element:')
    123     print(stack.top())
    124 
    125     print('
    Pop element from stack:')
    126     e = stack.pop()
    127     print('Element %s popped,' % e)
    128     stack.show()
    129 
    130     print('
    Set stack max size:')
    131     try:
    132         stack.max = 1
    133     except Exception as e:
    134         print(e)
    135 
    136     print('
    Set stack max size:')
    137     stack.max = 7
    138     print(stack.max)
    139 
    140     print('
    Push full stack:')
    141     try:
    142         stack.push(7)
    143     except StackFullException as e:
    144         print(e)
    145 
    146     print('
    Clear stack:')
    147     stack.clear()
    148     stack.show()
    149 
    150     print('
    Stack is empty:')
    151     print(stack.is_empty)
    152 
    153     print('
    Pop empty stack:')
    154     try:
    155         stack.pop()
    156     except StackEmptyException as e:
    157         print(e)
    158 
    159 if __name__ == '__main__':
    160     test(Stack())
    View Code

    分段解释
    以链表为基础的栈实现,首先需要定义链表结点,以及栈满压栈和栈空弹栈的异常类,

     1 class StackEmptyException(Exception): pass
     2 
     3 
     4 class StackFullException(Exception): pass
     5 
     6 
     7 class Node:
     8     def __init__(self, val=None, nxt=None):
     9         self.value = val
    10         self.next = nxt
    11 
    12     def __str__(self):
    13         return str(self.value)

    定义栈类,主要包括两个属性,即栈顶元素和栈大小,

     1 class Stack:
     2     """
     3     Stack based on linked list:
     4         | item3 |
     5         |   |   |
     6         |   V   |
     7         | item2 |
     8         |   |   |
     9         |   V   |
    10         | item1 |
    11          -------
    12     """
    13     def __init__(self, max=0):
    14         self._top = None
    15         self._max = 0
    16         self.max = max

    定义栈最大容量max为属性方法,当设置栈的最大容量值时,若传入的大小小于当前栈大小则提示异常,若传入0或负数大小,则设为无限容量的栈。

     1     @property
     2     def max(self):
     3         return self._max
     4 
     5     @max.setter
     6     def max(self, m):
     7         m = int(m)
     8         if m < self.length:
     9             raise Exception('Resize stack failed, please pop some elements first.')
    10         self._max = m
    11         if self._max < 0:
    12             self._max = 0

    定义栈的init方法,用于初始化一个可迭代对象为栈结构,接受一个可迭代对象,当空栈时以第一个元素为栈顶,随后依次压栈,最后入栈的元素为栈顶元素。

    1     def init(self, iterable=()):
    2         if not iterable:
    3             return
    4         self._top = Node(iterable[0])
    5         for i in iterable[1:]:
    6             node = self._top
    7             self._top = Node(i)
    8             self._top.next = node

    定义栈的show方法,用于显示栈,首先遍历栈元素,然后依照格式化输出,当空栈时则栈顶/底元素为None。

    1     def show(self):
    2         def _traversal(self):
    3             node = self._top
    4             while node and node.next:
    5                 yield node
    6                 node = node.next
    7             yield node
    8         print('
    '.join(map(lambda x: '|{:^7}|'.format(str(x)), _traversal(self)))+'
     '+7*'-')

    定义栈的length属性方法,用于返回当前栈内元素数量,通过链表遍历计数实现(类似获取链表长度)。

     1     @property
     2     def length(self):
     3         if self._top is None:
     4             return 0
     5         node = self._top
     6         i = 1
     7         while node.next:
     8             node = node.next
     9             i += 1
    10         return i

    定义栈的is_empty属性方法,用于判断栈是否为空栈。

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

    定义栈的is_full属性方法,用于判断栈容量是否已满。

    1     @property
    2     def is_full(self):
    3         return bool(self._max and self.length == self._max)

    定义栈的push方法,用于实现压栈过程,即向栈链前端插入入栈元素,栈满压栈则提示异常。

    1     def push(self, item):
    2         if self.is_full:
    3             raise StackFullException('Error: trying to push element into a full stack!')
    4         if not self._top:
    5             self._top = Node(item)
    6             return
    7         node = self._top
    8         self._top = Node(item)
    9         self._top.next = node

    定义栈的pop方法,用于实现弹栈过程,弹出栈顶元素并替换栈顶元素为下一个元素,栈空弹栈则提示异常。

    1     def pop(self):
    2         if self.is_empty:
    3             raise StackEmptyException('Error: trying to pop element from an empty stack!')
    4         node = self._top
    5         self._top = self._top.next
    6         return node.value

    定义栈的top方法,用于获取栈顶元素,当栈顶元素为None时,返回None。

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

    定义栈的clear方法,用于清空栈,即依次弹栈至空栈。

    1     def clear(self):
    2         while self._top:
    3             self.pop()

    最后定义一个测试函数,用于对栈类进行操作测试。

    首先实例化一个栈,并将一个列表元素依次压入栈中,最后显示栈元素

    1 def test(stack):
    2     print('
    Show stack:')
    3     stack.show()
    4 
    5     print('
    Init linked list:')
    6     stack.init([1, 2, 3, 4, 5])
    7     stack.show()

    得到结果

     1 Show stack:
     2 | None  |
     3  -------
     4 
     5 Init linked list:
     6 |   5   |
     7 |   4   |
     8 |   3   |
     9 |   2   |
    10 |   1   |
    11  -------

    执行压栈操作,将元素压入栈中,

    1     print('
    Push element to stack:')
    2     stack.push(6)
    3     stack.push(7)
    4     stack.push('like')
    5     stack.show()

    得到结果

    Push element to stack:
    | like  |
    |   7   |
    |   6   |
    |   5   |
    |   4   |
    |   3   |
    |   2   |
    |   1   |
     -------

    检测栈顶元素并弹出栈顶元素

    1     print('
    Check top element:')
    2     print(stack.top())
    3 
    4     print('
    Pop element from stack:')
    5     e = stack.pop()
    6     print('Element %s popped,' % e)
    7     stack.show()

    得到结果

    Check top element:
    like
    
    Pop element from stack:
    Element like popped,
    |   7   |
    |   6   |
    |   5   |
    |   4   |
    |   3   |
    |   2   |
    |   1   |
     -------

    尝试修改栈的最大容量,当修改容量小于当前栈内元素数量时,将会触发异常

    1     print('
    Set stack max size:')
    2     try:
    3         stack.max = 1
    4     except Exception as e:
    5         print(e)
    6 
    7     print('
    Set stack max size:')
    8     stack.max = 7
    9     print(stack.max)

    得到结果

    Set stack max size:
    Resize stack failed, please pop some elements first.
    
    Set stack max size:
    7

    尝试对一个满元素栈进行压栈操作,将引发异常

    1     print('
    Push full stack:')
    2     try:
    3         stack.push(7)
    4     except StackFullException as e:
    5         print(e)

    得到结果

    Push full stack:
    Error: trying to push element into a full stack!

    随后清空栈,并检查栈是否为空,最后尝试对空栈进行弹栈操作,同样会引发一个异常

     1     print('
    Clear stack:')
     2     stack.clear()
     3     stack.show()
     4 
     5     print('
    Stack is empty:')
     6     print(stack.is_empty)
     7 
     8     print('
    Pop empty stack:')
     9     try:
    10         stack.pop()
    11     except StackEmptyException as e:
    12         print(e)

    得到结果

    Clear stack:
    | None  |
     -------
    
    Stack is empty:
    True
    
    Pop empty stack:
    Error: trying to pop element from an empty stack!

      

    2 数组栈

    数组栈是栈的另一种实现方式,在C语言中以数组的形式实现,而在Python中,则可以使用与数组类似的列表进行实现。

    Stack based on array/list:
            |   4   |
            |   3   |
            |   2   |
            |   1   |
             -------

    数组栈中需要实现的方法接口与链表栈相同。只是在数据存储时由链表变成了数组/列表。由于Python的列表本身即是一种很方便的线性结构,因此数组栈的实现十分简单。

    完整代码

     1 from linked_list_stack import StackEmptyException, StackFullException, test
     2 
     3 
     4 class Stack:
     5     """
     6     Stack based on array/list:
     7         |   4   |
     8         |   3   |
     9         |   2   |
    10         |   1   |
    11          -------
    12     """
    13     def __init__(self, max=0):
    14         self._array = []
    15         self._max = 0
    16         self.max = max
    17 
    18     @property
    19     def max(self):
    20         return self._max
    21 
    22     @max.setter
    23     def max(self, m):
    24         m = int(m)
    25         if m < self.length:
    26             raise Exception('Resize stack failed, please pop some elements first.')
    27         self._max = m
    28         if self._max < 0:
    29             self._max = 0
    30 
    31     def init(self, iterable=()):
    32         if not iterable:
    33             return
    34         for i in iterable:
    35             self._array.append(i)
    36         
    37     def show(self):
    38         def _traversal(self):
    39             if not self._array:
    40                 return [None]
    41             return self._array[::-1]
    42         print('
    '.join(map(lambda x: '|{:^7}|'.format(str(x)), _traversal(self)))+'
     '+7*'-')
    43 
    44     @property
    45     def length(self):
    46         return len(self._array)
    47 
    48     @property
    49     def is_empty(self):
    50         return self._array == []
    51 
    52     @property
    53     def is_full(self):
    54         return bool(self._max and self.length == self._max)
    55 
    56     def push(self, item):
    57         if self.is_full:
    58             raise StackFullException('Error: trying to push element into a full stack!')
    59         self._array.append(item)
    60 
    61     def pop(self):
    62         if self.is_empty:
    63             raise StackEmptyException('Error: trying to pop element from an empty stack!')
    64         return self._array.pop()
    65 
    66     def top(self):
    67         return self._array[-1]
    68 
    69     def clear(self):
    70         # self._array = []
    71         while self._array:
    72             self.pop()
    73 
    74 
    75 if __name__ == '__main__':
    76     test(Stack())
    View Code

    分段解释

    首先从链表栈中导入两个异常类和测试函数,

    1 from linked_list_stack import StackEmptyException, StackFullException, test

    然后定义栈类,与链表栈不同的地方在于,存储数据的方式换成了列表

     1 class Stack:
     2     """
     3     Stack based on array/list:
     4         |   4   |
     5         |   3   |
     6         |   2   |
     7         |   1   |
     8          -------
     9     """
    10     def __init__(self, max=0):
    11         self._array = []
    12         self._max = 0
    13         self.max = max

    与前面的链表栈一样,定义栈的容量。

     1     @property
     2     def max(self):
     3         return self._max
     4 
     5     @max.setter
     6     def max(self, m):
     7         m = int(m)
     8         if m < self.length:
     9             raise Exception('Resize stack failed, please pop some elements first.')
    10         self._max = m
    11         if self._max < 0:
    12             self._max = 0

    定义栈的init方法,添加入栈元素时只需要在列表末尾加入元素即可,

    1     def init(self, iterable=()):
    2         if not iterable:
    3             return
    4         for i in iterable:
    5             self._array.append(i)

    下面的几个方法与链表栈类似,只是操作时换成了对数组列表的检测,

     1     def show(self):
     2         def _traversal(self):
     3             if not self._array:
     4                 return [None]
     5             return self._array[::-1]
     6         print('
    '.join(map(lambda x: '|{:^7}|'.format(str(x)), _traversal(self)))+'
     '+7*'-')
     7 
     8     @property
     9     def length(self):
    10         return len(self._array)
    11 
    12     @property
    13     def is_empty(self):
    14         return self._array == []
    15 
    16     @property
    17     def is_full(self):
    18         return bool(self._max and self.length == self._max)

    定义栈的push方法,实现压栈操作,压栈只需要对列表进行append即可,

    1     def push(self, item):
    2         if self.is_full:
    3             raise StackFullException('Error: trying to push element into a full stack!')
    4         self._array.append(item)

    定义栈的pop方法,实现弹栈操作,弹栈只需要对列表进行pop即可,

    1     def pop(self):
    2         if self.is_empty:
    3             raise StackEmptyException('Error: trying to pop element from an empty stack!')
    4         return self._array.pop()

    定义栈的top方法,实现栈顶元素获取,返回列表最后一位元素即可,

    1     def top(self):
    2         return self._array[-1]

    定义栈的clear方法,实现栈的清空操作,可以直接清空数组列表或依次将栈内元素弹出栈,

    1     def clear(self):
    2         # self._array = []
    3         while self._array:
    4             self.pop()

    最后,利用测试函数对数组栈进行测试

    1 if __name__ == '__main__':
    2     test(Stack())

    得到结果与链表栈相同

    Show stack:
    | None  |
     -------
    
    Init linked list:
    |   5   |
    |   4   |
    |   3   |
    |   2   |
    |   1   |
     -------
    
    Push element to stack:
    | like  |
    |   7   |
    |   6   |
    |   5   |
    |   4   |
    |   3   |
    |   2   |
    |   1   |
     -------
    
    Check top element:
    like
    
    Pop element from stack:
    Element like popped,
    |   7   |
    |   6   |
    |   5   |
    |   4   |
    |   3   |
    |   2   |
    |   1   |
     -------
    
    Set stack max size:
    Resize stack failed, please pop some elements first.
    
    Set stack max size:
    7
    
    Push full stack:
    Error: trying to push element into a full stack!
    
    Clear stack:
    | None  |
     -------
    
    Stack is empty:
    True
    
    Pop empty stack:
    Error: trying to pop element from an empty stack!

    相关阅读


    1. 单链表

  • 相关阅读:
    改变网页字体的大小
    dom小练习
    各种交换机接口及连接方法介绍【详细图文】
    网线从路由器接出来, 再接一个路由器怎么设置?
    路由器后面再接一个路由器怎么设置(二级路由)
    设置无线路由器
    交换机与集线器的区别
    Java的位运算符具体解释实例——与(&amp;)、非(~)、或(|)、异或(^)
    无法识别的属性“targetFramework”。请注意属性名称区分大写和小写。错误解决的方法
    简单工厂模式
  • 原文地址:https://www.cnblogs.com/stacklike/p/8284550.html
Copyright © 2020-2023  润新知