(一) 栈
定义
栈是一种特殊的线性表,与数组和链表的不同之处体现在增加和删除操作。具体表现在栈的读取插入和删除操作只能在栈的末尾进行。栈是一种先进后出的线性表结构,用数组存储数据的栈叫顺序栈,用链表的形式存储数据的栈我们叫链栈。
栈的基本操作
对于栈来说,插入数据以及删除数据都只能在栈尾进行,在栈中增加数据我们叫压栈push,删除栈中的数据我们叫出栈pop。
接下来对于栈的基本操作,我们分别基于顺序栈和链栈来进行讨论。
顺序栈
class ArrayStack():
"""顺序栈"""
def __init__(self, length):
"""顺序栈的初始化
参数:
n: 栈的大小
"""
self.stack = []
self.top = 0
self.length = length
**查找数据:**顺序栈是用数组存储数据的栈,因此对于顺序栈的查找,与数组的查找相同,如果是根据下标随机访问,那么查找的时间复杂度为O(1);如果是查找满足特定条件的元素,需要遍历栈,那么时间复杂度为O(n)。
**插入数据:**由于栈的特性,我们要插入数据,只能在栈的末尾进行,不过需要注意的是,由于顺序栈是使用数组存储数据的,我们在定义一个顺序栈的时候必须指定栈的大小,那么插入数据的时候需要考虑栈是否满了,如果栈还有多余的空间, 那么插入数据只需要将数据插入栈的末尾,时间复杂度为O(1);如果栈满了,这时候需要考虑到扩容,跟数组是一样的情况,需要搬移数据,那么时间复杂度为O(n)。
def push(self, num):
"""入栈
参数:
num: 入栈的数值
"""
if self.top == self.length:
return False
self.stack.append(num)
self.top += 1
**删除数据:**删除栈中的数据,和插入数据一样只能在栈的末尾进行,不同的是,删除栈中的数据,我们不需要考虑栈是否有多余空间,不会涉及到内存申请和数据搬移,因此时间复杂度为O(1)。
def pop(self):
"""出栈
返回:
栈尾的值
"""
if not self.stack:
return None
num = self.stack[self.top - 1]
self.top -= 1
return num
链栈
class Node():
'''链表结构的Node节点'''
def __init__(self, val, next = None):
'''Node节点的初始化方法.
参数:
val:存储的数据
next:下一个Node节点的引用地址
'''
self.val = val
self.next = next
class LinkStack():
"""链栈"""
def __init__(self):
'''链栈的初始化方法.'''
self.top = None
**查找数据:**链栈是用链表存储数据的栈,与链表的查找相同,链栈的查找操作需要遍历栈,时间复杂度为O(n)。
**插入数据:**与顺序栈不同,链栈是一个动态的线性表,在初始化一个链栈的时候不需要指定栈的大小,因此在链栈中插入数据只需要直接在链栈的末尾插入数据,时间复杂度为O(1)。
def push(self, num):
"""入栈
参数:
num: 入栈的数值
"""
node = Node(num)
node.next = self.top
self.top = node
**删除数据:**删除链栈中的数据,只需要删除链栈末尾的节点,时间复杂度为O(1)。
def pop(self):
"""出栈
返回:
栈尾的值
"""
if not self.top:
return None
num = self.top.val
self.top = self.top.next
return num
应用
1、括号匹配
2、浏览器的前进后退功能