堆和栈都是数据项按序排列的数据结构,栈是一种后进先出的数据结构,而堆是一种二叉树。
在讲解堆栈之前,先说下队列。
一、队列
(1)队列的概念
队列是一种列表,但是队列只能在队尾加入元素,队首删除元素(就跟排队是一个道理);由此看来,队列和栈刚好相反,是 先进先出(FIFO)。
(2)Python语言中的队列 - - queue、deque
Python中可以通过queue模块实现队列的相关操作
而deque则是一个双端队列,可以在队尾、队首都可实现插入、和删除操作
(3)示例
from queue import Queue
from collections import deque
q = Queue()
#满足先进先出
q.put(1)
q.put(2)
q.put(3)
print(q.queue)
print(q.get())
print(q.get())
print(q.get())
#双端队列
dq = deque(["a","b","c"])
print(dq)
dq.append("d")
dq.appendleft("e")
print(dq)
#将循环右移两次
dq.rotate(2)
print(dq)
dq.pop()
dq.popleft()
print(dq)
"""
deque([1, 2, 3])
1
2
3
deque(['a', 'b', 'c'])
deque(['e', 'a', 'b', 'c', 'd'])
deque(['c', 'd', 'e', 'a', 'b'])
deque(['d', 'e', 'a'])
"""
(4)基于堆实现优先级队列
在python中可以用heapq模块实现优先级队列,在以前的文章中有所讲解,此处主要是自己用Python语言来实现,模拟堆实现优先级队列,此处模拟的堆为小根堆。
#创建堆队列对象
class Heapque():
def __init__(self, elems = []):
self.elems = elems
#构建一个小根堆
if self.elems:
self.buildheap()
#判断堆是否为空
def is_empty(self):
return self.elems is []
#查看堆顶元素,及优先级最高的元素
def peek(self):
if self.is_elems():
print("空堆")
return
return self.elems[0]
#将新的元素加入队列
def adding(self, e):
#在队尾添加一个元素None
self.elems.append(None)
#再对元素进行优先级排序
self.siftup(e, len(self.elems) - 1)
#加入元素后的排序函数,last是队列里最后一个元素的序号
def siftup(self, e, last):
#(last-1)//2
elems, i, j = self.elems, last, (last-1)//2
while i > 0 and e < elems[j]:
elems[i] = elems[j]
i, j = j, (j-1)//2
elems[i] = e
#弹出优先级最高的元素
def poping(self):
if self.is_empty():
print('空堆')
return
elems = self.elems
e0 = elems[0]
e = elems.pop()
if len(elems) > 0:
#弹出元素后,对队列进行排序
self.siftdown(e, 0, len(elems))
return e0
#删除元素后的排序
def siftdown(self, e, begin, end):
elems, i, j = self.elems, begin, begin*2+1
while j < end:
if j + 1 < end and elems[j] > elems[j+1]:
j += 1
if e < elems[j]:
break
elems[i] = elems[j]
i, j = j, j*2+1
elems[i] = e
#构建堆序
def buildheap(self):
end = len(self.elems)
for i in range((end-1)//2,-1,-1):
self.siftdown(self.elems[i], i, end)
hq = Heapque([4,3,6,9,2,1,13,8,7,6,16,5])
print(hq.elems)
hq.adding(0)
print(hq.elems)
hq.poping()
print(hq.elems)
"""
运行结果
[1, 2, 4, 7, 3, 5, 13, 8, 9, 6, 16, 6]
[0, 2, 1, 7, 3, 4, 13, 8, 9, 6, 16, 6, 5]
[1, 2, 4, 7, 3, 5, 13, 8, 9, 6, 16, 6]
"""
在这里对弹出优先级最高元素后的排序操作进行图解:
二、栈(stack)
栈遵循的原则就是后进先出,它允许在一端进行插入和删除操作,允许执行插入和删除操作的一端称为栈顶,另一端为栈底;
插入操作为入栈,删除操作为出栈;
栈在存储结构上有两种形式,分别为顺序栈和链栈
顺序栈就是栈的顺序存储结构的简称,可以对照列表,在此不赘述;
链栈是栈的链式存储结构
示例:单链表方法实现栈
#定义节点
class Node():
def __init__(self, elem, _next = None):
self.elem = elem
self.next = _next
#链表实现栈
class Lstack():
def __init__(self):
#初始化栈顶元素
self._top = None
#判断是否为空
def is_empty(self):
return self._top is None
#查看栈顶元素
def top(self):
if self.is_empty():
print("空栈")
return
return self._top.elem
#入栈
def push(self,elem):
self._top = Node(elem, self._top)
#出栈
def pop(self):
if self.is_empty():
print("空栈")
return
re = self._top.elem
self._top = self._top.next
return re
s = Lstack()
s.push(2)
s.push(5)
s.push(7)
print(s.pop())
"""
结果为7
"""
总结:
堆实现数据的先进先出,可以用来实现优先级队列,本质上是一种二叉树
栈实现数据的后进先出,可分为顺序栈和链栈