题目描述:
实现一个栈的数据结构 (Last In First Out,LIFO),使其具有以下方法:;压栈,弹栈,取栈顶元素,判断栈是否为空以及获取栈内元素个数。
方法:
- 数组实现
- 链表实现
1.数组实现
在采用数组来实现栈的时候,栈空间是一段连续的空间。实现思路如下图所示:
从上图中可以看出,可以把数组的首元素当作栈底,同时记录栈中元素的个数 size,假设数组首地址为 arr,从上图可以看出,压栈的操作其实是把待压栈的元素放到数组 arr[size]中,然后执行 size++;弹栈的操作是取数组 arr[size-1]元素,然后执行 size–;
代码实现:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time : 2020/1/20 15:02
# @Author : buu
# @Software: PyCharm
# @Blog :https://blog.csdn.net/weixin_44321080
class Mystack:
def __init__(self): # 模拟栈
self.items = [] # 用列表实现
def isEmpty(self): # 栈是否为空
return len(self.items) == 0
def size(self): # 栈的大小
return len(self.items)
def top(self): # 取栈顶元素
if not self.isEmpty():
return self.items[len(self.items) - 1]
else:
return None
def pop(self): # 弹栈
if len(self.items) > 0: # 先判断栈是否为空
return self.items.pop()
else:
print('stack is empty!')
return None
def push(self, item): # 入栈
self.items.append(item)
if __name__ == '__main__':
s = Mystack()
s.push(4)
print('top of the stack is ' + str(s.top()))
print('size of the stack is ' + str(s.size()))
if s.pop():
print('successfully pop!')
s.pop()
结果:
2.链表实现
在创建链表的时候经常采用一种从头结点插入新结点
的方法,可以采用这种方法来实现栈,最好使用带头结点的链表,这样可以保证对每个结点的操作都是相同的,实现思路如下图所示:
在上图中,在进行压栈操作的时候,先需要创建新的结点,把待压栈的元素放到新结点的数据域中,然后只需要 (1) 和 (2) 两步就实现了压栈
操作 (把新结点压到了链表首部);同理,在弹栈的时候,只需要进行 (3) 的操作就可以删除链表的第一个元素
,从而实现弹栈操作。(都是在链表头实现的)
代码实现:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time : 2020/1/20 15:20
# @Author : buu
# @Software: PyCharm
# @Blog :https://blog.csdn.net/weixin_44321080
class LNode():
def __init__(self, data=None, next=None):
self.data = data
self.next = next
class myStack(): # self 指向头结点
def __init__(self, data=None, next=None):
self.data = data
self.next = next
def isEmpty(self): # 判断是否为空
if self.next == None: # 若为空,返回True
return True
else:
return False
def size(self): # 栈的大小
size = 0
p = self.next
while p != None:
p = p.next
size += 1
return size
def push(self, e): # 入栈
p = LNode(e)
p.next = self.next
self.next = p
def pop(self): # 弹栈
tmp = self.next
if tmp != None:
self.next = tmp.next
return tmp.data
print('the stack is already empty!')
return None
def top(self): # 取栈顶元素
if self.next != None:
return self.next.data
else:
print('the stack is alreay empty!')
return None
if __name__ == '__main__':
stack = myStack()
stack.push(3)
print('top of the stack is ' + str(stack.top()))
print('size of the stack is ' + str(stack.size()))
if stack.pop():
print('pop successfully!')
if not stack.pop():
print('unable to pop!')
结果:
两种方法的对比:
采用数组实现栈的优点是:一个元素值占一个存储空间;缺点是:如果初始化申请的存储空间比较大,容易造成空间的浪费,如果申请存储的空间太小,后期会经常需要扩充存储空间,比较费时间,会造成性能的下降。
采用链表实现的优点是:使用灵活方便,只有在需要的时候才会申请空间,缺点是除了要存储元素外,还需要额外的存储空间存储指针信息。
这两种方法压栈与弹栈的时间复杂度都为O(1)
end