数据结构
堆
-
优先队列:是支持插入元素和寻找最大值元素的数据结构。
普通队列(寻找最大值时需要搜索整个队列)排序数组(插入运算需要移动太多元素)优先队列的有效实现使用了一种称为堆的简单数据结构
-
堆运算
-
sift-up
用于修复H [i]的键值大于其父节点键值的情况
//输入:数组H[1...n]和和位于1和n之间的索引i //输出:上移H[i],以使它不大于父节点 done = flase if i=1 then exit {节点i为根节点} repeat if key(H[i])>key(H[i/2]) 互换H[i]和H[i/2] else done = true i=i/2 until i=1 or done
- sift-down
用于修复H[i]键值小于H[2i]和H[2i+1]中的最大键值的情况
//输入:数组H[1...n]和位于1和n之间的索引i //输出:下移H[i],以使它不小于子节点 done = false if 2i>n then exit {节点i是叶节点} repeat i = 2i if i+1<=n and key(H[i+1])>key(H[i]) i = i+1 {确保key(H[i])为子节点中的最大键值} if key(H[i])>key(H[i/2]) 互换key(H[i]) and key(H[i/2]) else done = true end if until done or 2i>n
- INSERT
- 先将堆的大小+1
- 将x添加至H的末尾
- 根据需要把x给sift-up,直到满足堆的特性
//输入:堆H[1...n]和元素x //输出:新的堆H[1,...n+1] n = n+1 { 增加H的大小 } H[n]=x SIFT-UP(H,n)
- DELETE
- 用H[n]替换H[i]
- 将堆的大小-1
- 根据键值大小关系进行sift-up or sift-down运算
//输入:非空堆H[1...n]和索引i //输出:删除H[i]之后的新堆H[1,...n-1] x=H[i]; y=H[n] n=n-1 {减少H的大小} if i=n+1 then exit{完成} H[i]=y if key(y)>=key(x) then SIFT-UP(H,i) else SIFT_DOWN(H,i) end if
-
MAKEHEAP1
从对应T中最后一个非叶子节点的数开始调整数组,即A[ n/2 ], A[ n/2 - 1 ],…A[1].
T 的叶子节点存储在H[ n/2 +1],H[n/2 + 2]…H[n]中
//输入:n个元素的数组A[1,...n] //输出:A转换成的堆 for i: n/2 downto 1 SIFT-DOWN(A,i) end for
- HEAPSORT2
- 先将A变成堆
- 将最大值也就是A[1]和A[n]交换,使得A[n]是数组的最大元素
- 此时A[1]的元素可能小于子节点,于是用SIFT-DOWN将A[1,…n-1]转换成堆
- 将A[1]与A[n-1]交换,调整数组A[1,…,n-2]为堆
- 交换和调整的过程不断重复,直至堆的大小变成1,此时A[1]是最小的
//输入:n个元素的数组A[1,...,n] //输出:以非降序排列的数组A MAKEHEAP(A) for j: n downto 2 互换A[1] and A[n] SIFT-DOWN(A[1,j-1],1) end for
-