前言
- 有Python基础
- 有数据结构的基础的话那当然是再好不过了
原理
先进后出
- 初始化时,栈为空。
- 数据入栈时,第一个数据先进到栈底,此时栈顶也是这个元素(因为目前栈中只有一个元素)。第二个数据入栈,则处于栈顶,即在第一个元素的上面。后续加入的情况亦是如此,第三个在第二个的上面,第四个在第三个的上面…当然以上情况仅考虑入栈,中间不曾出栈。新的元素加入后都是处在当时情况下的栈顶。
- 出栈时,栈顶的元素先出。比如上图,栈顶的e(n-1)先出,之后e(n-2)才能出…最后,底层元素e(0)才能出栈。当然,这里也是仅考虑出栈的情况。动的元素照样是栈顶元素。
- 因此,栈只对栈顶元素进行操作。
- 一般考试的时候或者笔试的时候不会单纯地出只有入栈或者出栈的情况,一般会综合起来考察。可能会出这样的题,给定一组序列,比如1,2,…,10,期间可以有入栈和出栈,让你从选项中选出不可能出现的情况。比如下面的这道题(来自某度文库)。
实现
环境
Python3.7 + win10 + pycharm。重点是Python3,其他的事实上无所谓。
分析
- 在Python中选用类的方式来定义。注:在C/C++中用的比较多的是struct,当然,在C++中类的方式也是可以,关于struct和class的区别有兴趣的自己搜下,这个是C/C++的内容。
- 按照上面讲的初始化的时候栈是空的,因此在class Stack的构造函数中将属性items设置为空list。init这一块就是构造函数,不清楚的建议补下Python基础。
- 这里为什么选用list?栈可以存不少数据吧?那需要选个可以存很多数据的数据类型吧?用字典吧…还要键值对,麻烦。用set吧,emmm,set里面的元素是无序的,而且没有重复的元素,看看栈的元素,有序吧,有重复的元素吧?因此也不适用。tuple只读,也不合适。看来看去还是list最适合了。而且操作也方便是吧?
初始化
# 类的初始化
class Stack(object):
def __init__(self):
self.items = []
判空
初始化完之后看下其他的操作,一般来说都会有判空的操作,因此需要定义一个isEmpty的方法。原理也很简单,当items长度是0 的时候就是空的,return True即可。否则返回False。
def isEmpty(self):
return len(self.items) == 0
入栈
接下来说下入栈的方法。进来的数据是要加到items里面的,items是一个list,可以用append方法加入,append是把元素加到list的末尾,因此可以用items的尾部元素当做栈顶。当然,头部那就是底部了。这里是进行操作,可以没有返回值,由于是加入元素,因此需要有一个参数item,将要加入的元素带入item即可。
# 入栈
def push(self, item):
self.items.append(item)
出栈
依旧是对栈顶元素操作,将栈顶元素从items当中剔除即可,很容易想到list可以用pop()
# 删除栈顶元素(出栈)
def remove(self):
self.items.pop()
size
如若想知道大小,那么可以定义一个size方法,直接返回现在items的长度即可
def size(self):
return len(self.items)
遍历
此外还可以设计一个遍历的方法,以便于打印输出看效果。下面travel函数这么写是为了打印更好看点。
def travel(self):
for i in self.items:
print(i, end=' ')
print('')
取栈顶元素
如若是在C/C++里面,有可能会考虑栈满的情况,但是在Python中就没有什么必要了,list自己会扩张,用不着担心满的情况。在C里面,items用的一般是规定大小的数组,因此会有判满的操作。有的可能还会有取栈顶元素的操作。那可以实现下。直接读取items的最后一个元素即可。最后一个元素的下标是len(items) - 1,好写吧?
def get_top(self):
return self.items[len(self.items) - 1]
完整代码
- ok ,大致的方法有这些,写完之后需要加点东西测试一下。完整代码如下:
class Stack(object):
def __init__(self):
self.items = []
def isEmpty(self):
return len(self.items) == 0
# 栈的特点是先进后出,操作的都是栈顶元素
# 先定义入栈的方法
# self.items是一个list,利用append方法可以将加进来的item加到列表的末尾,items的末尾相当于栈顶,items的头部就当做栈的底部
def push(self, item):
self.items.append(item)
# 删除栈顶元素
def remove(self):
self.items.pop()
def travel(self):
for i in self.items:
print(i, end=' ')
print('')
def get_top(self):
return self.items[len(self.items) - 1]
def size(self):
return len(self.items)
st = Stack()
print(st.isEmpty()) # 刚初始化,应该是空栈,应return True
for i in range(5):
st.push(i) # 将 0-4几个数加入,此时size应为5
st.travel() # 遍历打印出来
st.remove() # 删除栈顶元素,size应为4
st.travel()
print(st.size()) # 预期结果4
print(st.get_top()) # 之前的栈顶元素4弹出去了,现在3是老大(栈顶),应打印3
- 结果