堆和栈都是数据项按序排列的数据结构,栈是一种后进先出的数据结构,而堆是一种二叉树。
在讲解堆栈之前,先说下队列。

一、队列

(1)队列的概念

队列是一种列表,但是队列只能在队尾加入元素,队首删除元素(就跟排队是一个道理);由此看来,队列和栈刚好相反,是 先进先出(FIFO)。

python 构造大顶堆 python的堆和栈_删除操作


(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]
"""

在这里对弹出优先级最高元素后的排序操作进行图解:

python 构造大顶堆 python的堆和栈_python 构造大顶堆_02


二、栈(stack)

栈遵循的原则就是后进先出,它允许在一端进行插入和删除操作,允许执行插入和删除操作的一端称为栈顶,另一端为栈底;

python 构造大顶堆 python的堆和栈_优先级_03


插入操作为入栈,删除操作为出栈;

栈在存储结构上有两种形式,分别为顺序栈和链栈

顺序栈就是栈的顺序存储结构的简称,可以对照列表,在此不赘述;

链栈是栈的链式存储结构

示例:单链表方法实现栈

#定义节点
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
"""

总结:
堆实现数据的先进先出,可以用来实现优先级队列,本质上是一种二叉树
栈实现数据的后进先出,可分为顺序栈和链栈