保证一周更两篇吧,以此来督促自己好好的学习!代码的很多地方我都给予了详细的解释,帮助理解。好了,干就完了~加油!
声明:本python数据结构与算法是imooc上liuyubobobo老师java数据结构的python改写,并添加了一些自己的理解和新的东西,liuyubobobo老师真的是一位很棒的老师!超级喜欢他~
如有错误,还请小伙伴们不吝指出,一起学习~
No fears, No distractions.
一、链表栈
由于在链表头处的插入与删除操作的时间复杂度都是O(1)的,因此可以被用作栈来使用。具体实现也很简单。
二、链表栈的实现
# -*- coding: utf-8 -*-
# Author: Annihilation7
# Data: 2018-09-28
# Python version: 3.6
import linkedlist # LinkedList类写在这个py文件中了
class LinkedListStack:
def __init__(self):
self.stack = linkedlist.LinkedList() # 初始化一个链表就好
# 这时就不需要self._capacity了,因为并不需要扩容/缩容神马的
def getSize(self):
"""
获得栈内有效元素的个数
:return: 有效元素的个数
"""
return self.stack.getSize() # 直接调用链表的getSize方法
def isEmpty(self):
"""
判断栈是否为空
:return: bool值,空为True
"""
return self.stack.isEmpty() # 调用链表的isEmpty方法
def push(self, elem):
"""
入栈操作
tip:在这里我们将链表的表头当做栈顶,因为此时栈顶的入栈与出栈操作的时间复杂度都是O(1)的
时间复杂度:O(1)
:param elem: 将要入栈的元素
"""
return self.stack.addFirst(elem) # 调用链表的addFirst方法
def pop(self):
"""
栈顶元素的出栈操作,同理,也在表头进行出栈操作
时间复杂度:O(1)
:return: 出栈的元素
"""
return self.stack.removeFirst() # 调用链表的removeFirst方法
def peek(self):
"""
看一眼栈顶元素是谁
时间复杂度:O(1)
:return: 栈顶的元素
"""
return self.stack.getFirst() # 调用链表的getFirst方法
def printLinkListStack(self):
"""对链表栈进行打印操作"""
print('Stack: Top--- ', end=' ') # 左边为栈顶
cur = self.stack._dummyhead.next
while cur != None:
cur.printNode()
cur = cur.next
print('---bottom') # 右边为栈底
print('Size: ', self.getSize()) # 有效元素数目
三、测试
import linkedlistStack # 链表栈写在这个Py文件中
import numpy as np
np.random.seed(7)
a = linkedlistStack.LinkedListStack()
print(a.getSize())
print(a.isEmpty())
for i in range(15): # 入栈15次
a.push(np.random.randint(10))
a.printLinkListStack()
for i in range(4): # 出栈4次
a.pop() # 就不用pop函数的返回值了
a.printLinkListStack()
print(a.peek())
四、输出
0
True
Stack: Top--- 4 6 7 8 9 8 7 9 7 7 3 3 6 9 4 ---bottom
Size: 15
Stack: Top--- 9 8 7 9 7 7 3 3 6 9 4 ---bottom
Size: 11
9
五、与数组栈的性能比较
数组栈就是我们前面实现的那个栈哦,它是基于我们的Arr类实现的栈。
测试代码
from Stack.arrayStack import ArrayStack # 数组栈
from linklist.linkedlistStack import LinkedListStack # 链表栈
from queue.testQueueAndLoopqueue import count_time # 运行时间测试函数
import numpy as np
np.random.seed(7)
nums = 200000 # 入/出栈次数
arrayStack = ArrayStack() # 数组栈对象
linkedlistStack = LinkedListStack() # 链表栈对象
@count_time
def compute_arrayStack():
global nums, arrayStack
for i in range(nums):
arrayStack.push(np.random.randint(10))
for i in range(nums):
arrayStack.pop() # 两个操作都是O(1)的
@count_time
def compute_linkedlistStack():
global nums, linkedlistStack
for i in range(nums):
linkedlistStack.push(np.random.randint(10))
for i in range(nums):
linkedlistStack.pop()
if __name__ == '__main__':
print('总操作数:%d' % (nums))
print('数组栈:', end=' ')
compute_arrayStack()
print('链表栈:', end=' ')
compute_linkedlistStack()
输出结果
总操作数:200000
数组栈: 共用时: 1.717325 秒
链表栈: 共用时: 1.300426 秒
总操作数:10000000
数组栈: 共用时: 76.546684秒
链表栈: 共用时: 82.714655秒
可以看到总共测试两次,操作数分别为200000和10000000次,用时几乎相差无几。在操作数较少的情况下,数组栈需要不停的拓展存储空间、转移元素,这样消耗时间比较多。在操作数较大的情况下,链表栈需要不停的创建存储Node的内存空间,相对耗时(注意数组栈的扩容方式是乘以2哦),所以此时链表栈用时稍多。不过这些差别可以忽略不计啦,都是O(1)的时间复杂度。
当然这些在你的机器上进行测试可能与我的结果不一致,这是很正常的,因为测试结果与很多因素有关呢。
若有还可以改进、优化的地方,还请小伙伴们批评指正!