优先队列
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
左高树定义
定义[高度优先左高树]: 当且仅当一棵二叉树的任一内部节点, 其左孩子的s 值大于等于右孩子的s 值, 该二叉树为高度优先左高树(heightbiased leftist tree, HBLT)
定理9-1
定理9-1 令x为一个HBLT的内部节点, 则
1源自文库 2) 3)
以x为根的子树的节点数目至少为2s(x)-1。 若子树x有m个节点,s(x)最多为log2(m+1)。 通过最右路径(即,此路径是从x开始沿右 孩子移动)从x到达外部节点的路径长度为 s(x)
最小树示例
堆的定义
定义[最大堆(最小堆)]: 最大(最小)的完全二叉树 上例
第一个最大树和第一个最小树是堆
堆的描述
特殊的完全二叉树 一维数组有效描述 父子节点位置关系——简单公式 n个元素,高度log2(n+1) 插入删除:若达到O(h) 则达到O(logn)
9.3.2 最大堆的插入操作
完全二叉树 插入后必然形如右图 但新元素放在阴影 位置,可能不符合 堆的特性
– 刚开始的i直至上一层,其子树均为单节点,肯定是 – 更高层节点,子树已经重整过——必然是堆!
整理堆——下降过程!
建堆实例
10
建堆实例(续)
35
建堆实例(续)
20
建堆实例(续)
9.3.5 MaxHeap类
template<class T> class MaxHeap { public: MaxHeap(int MaxHeapSize = 10); ~MaxHeap() {delete [] heap;} int Size() const {return CurrentSize;} T Max() {if (CurrentSize == 0) throw OutOfBounds(); return heap[1];}
MaxHeap类
MaxHeap<T>& Insert(const T& x); MaxHeap<T>& DeleteMax(T& x); void Initialize(T a[], int size, int ArraySize); void Deactivate() {heap = 0;} void Output() const; private: int CurrentSize, MaxSize; T *heap; // element array };
建堆函数(续)
// 从最后一个内部节点开始,一直到根,对每个子树进行堆重整 for (int i = CurrentSize/2; i >= 1; i--) { T y = heap[i]; // 子树根节点元素 // find place to put y int c = 2*i; // parent of c is target // location for y while (c <= CurrentSize) { // heap[c] should be larger sibling if (c < CurrentSize && heap[c] < heap[c+1]) c++;
插入函数
template<class T> MaxHeap<T>& MaxHeap<T>::Insert(const T& x) {// Insert x into the max heap. if (CurrentSize == MaxSize) throw NoMem(); // no space // 寻找新元素x的位置 // i——初始为新叶节点的位置,逐层向上,寻找最终 位置 int i = ++CurrentSize;
构造函数
template<class T> MaxHeap<T>::MaxHeap(int MaxHeapSize) {// Max heap constructor. MaxSize = MaxHeapSize; heap = new T[MaxSize+1]; CurrentSize = 0; }
插入函数(续)
while (i != 1 && x > heap[i/2]) { // i不是根节点,且其值大于父节点的值,需要继续 调整 heap[i] = heap[i/2]; // 父节点下降 i /= 2; // 继续向上,搜寻正确位置 } O(logn) heap[i] = x; return *this; }
无序线性表——最简单
公式化描述
插入操作:表尾,Θ(1) 删除操作:查找最大优先级元素, Θ(n)
链表描述
插入操作:链头, Θ(1);删除操作,Θ(n)
有序列表
公式化:递增,链表:递减 删除:Θ(1);插入:Θ(n)
9.3 堆
9.3.1 定义 [最大树(最小树)]:每个节点的值都 大于(小于)或等于其子节点(若存在) 值的树
例9-1 机器服务收费
用户付费相同,但所需服务时间不同
用户 最小优先队列,优先级——时间 新用户 加入优先队列 最大收益:机器可用 最少服务时间用户获 得服务
用户所需时间相同,愿意支付费用不同
支付费用作为优先级 机器可用 交费最多的用户最先得到服务
例9-2 工厂仿真
最小优先队列的应用
事件队列操作
建堆复杂性分析
内层循环O(logn),n/2次,O(nlogn) 实际上,Θ(n) 每次内层循环O(hi)
hi,子树高度,取值2~h 第j层节点数2j-1,以它们为根子树高度h-j+1 所以建堆时间
O ( ∑ 2 ( h − j + 1)) = O ( ∑ k 2
j −1 j =1 k =2
h −1
删除函数(续)
// y的值大于等于孩子节点吗? if (y >= heap[ci]) break; // 是,i就是y的正确位置,退出 // 否,需要继续向下,重整堆 heap[i] = heap[ci]; // 大于父节点的孩子节点上升 i = ci; // 向下一层,继续搜索正确位置 ci *= 2; } heap[i] = y; return *this; }
删除函数(续)
// 重整堆 T y = heap[CurrentSize--]; // 取最后一个节点,从根开始重整 // find place for y starting at root int i = 1, // current node of heap ci = 2; // child of i while (ci <= CurrentSize) { // 使ci指向i的两个孩子中较大者 if (ci < CurrentSize && heap[ci] < heap[ci+1]) ci++;
HBLT和WBLT的操作
查找、插入、删除与堆一样 初始化也可在线性时间内完成 两个优先队列合并:对数时间 这是堆达不到的
最大HBLT的插入、删除操作
插入操作可借助合并操作
元素x插入最大HBLT H
构造只有一个元素x的最大HBLT H’ H’与H合并
删除操作也可借助合并操作
删除根节点
两个子树L、R均为最大HBLT 合并L、R
第9章 优先队列
学习内容
优先队列:删除顺序——优先级 堆:完全二叉树 堆排序:O(nlogn) 应用
机器调度 霍夫曼编码
9.1 引言
抽象数据类型MaxPriorityQueue{ 实例 有限的元素集合,每个元素都有一个优先级 操作 Create():创建一个空的优先队列 Size():返回队列中的元素数目 Max():返回具有最大优先级的元素 Insert(x):将x插入队列 DeleteMax(x):从队列中删除具有最大优先级 的元素,并将该元素返回至x }
9.4.4 最大HBLT的合并操作
遍历右路径——O(logn) 递归,合并A、B
若一个为空,则另一个为合并结果 若都不空
比较两个根节点,较大者为新的根 假定A较大,左子树为L,右子树为R 递归方法将R与B合并为C 最终合并结果:A的根为根;L、C的s值较大者 为左子树,另一个为右子树
上移重整堆
新元素向上移动 (与父节点交换) 重复此过程,直到 到达某个位置时符 合堆的特性为止
最坏情况O(log2n) 平均情况O(1)
9.3.3 删除操作
删除根-最大优先级 保持完全二叉树结构 最后一个元素 根, 形如右图
可能不符合 堆的特性
下降过程
选取子节点中较大者与 父节点交换 重复,直至符合堆特性
最大(小)HBLT
定义[最大(小)HBLT]: 即同时又是最大(小)树的HBLT
重量
w(x):以x为根的子树的内部节点数目
外部节点:w(x)=0 内部节点:w(x)=w(L)+w(R)+1
重量优先左高树
定义[重量优先左高树]: 当且仅当一棵二叉树的任一内部节点, 其左孩子的w值大于等于右孩子的w值, 该二叉树为重量优先左高树(weightbiased leftist tree, WBLT) [最大(小)WBLT]: 即同时又是最大(小)树的WBLT
建堆函数
template<class T> void MaxHeap<T>::Initialize(T a[], int size, int ArraySize) {// Initialize max heap to array a. delete [] heap; heap = a; CurrentSize = size; MaxSize = ArraySize;
证明
由s(x) 定义 从x向下的s(x)-1层内没有外部节 点(否则s(x) 将更小) 子树第一层只有x,下一层有两个,..., 第s (x)-1层有个2s (x) - 1,节点数目至少为
s ( x ) −1 i =0
2i = 2 s ( x ) − 1 ∑
由1) 可得2) 根据s 的定义,及HBLT一个节点的左孩子的s 值总是大于等于其右孩子的s 值,可以推得3) 成立。
1) 查找最小完成时间的机器 2) 改变机器的完成时间
优先级——完成时间 修改完成时间——ADT增加一个操作
例9-2 工厂仿真(续)
最大优先队列的应用
当机器可用,选择优先级最大的任务执行 任务队列操作
1) 新任务到达,插入最大优先队列 2) 机器可用,选择最大优先级任务执行
9.2 线性表描述优先队列
删除函数
template<class T> MaxHeap<T>& MaxHeap<T>::DeleteMax(T& x) {// Set x to max element and delete // max element from heap. // check if heap is empty if (CurrentSize == 0) throw OutOfBounds(); // empty x = heap[1]; // 删除最大元素
没有明确的指针,没有存储结构信息 空间利用率最高 不适用所有优先队列应用——合并长度不等 的优先队列
左高树(leftist tree)适合此类应用
扩充二叉树
内部节点 外部节点
函数s(x)的定义
s(x):x到其子树外部节 点路径长度最短值 外部节点:s(x)=0 内部节点: s(x)=min{s(L), s(R)}+1 L、R——x的左右孩子
最坏情况O(log2n) 平均情况也是
9.3.4 最大堆的创建
n个元素——如何构成堆?
空堆,n次插入——O(nlogn) 更好的方法,Θ(n):n个元素构成完全二叉 树,可能不是堆,整理它
从最后一个内部节点(n/2)开始到根节点,将 每个节点i的子树(完全二叉树)整理为堆 重要特性——i的两个子树都已经是堆了
h
h −k
k ) = O (2 ∑ k ) = O (2h ) = O (n ) k =2 2
h
h
且循环执行n/2 Ω(n) Θ(n)
d-堆
多叉堆 优先队列无法全部装入内存 在实际应用中,4-堆可胜过二叉堆
9.4 左高树
9.4.1 高度与宽度优先的最大及最小左高树 堆——隐式(implicit)数据结构
建堆函数(续)
// can we put y in heap[c/2]? if (y >= heap[c]) break; // yes // no heap[c/2] = heap[c]; // move child up c *= 2; // move down a level } heap[c/2] = y; } }