算法设计与分析之优先队列
算法设计与分析知到章节答案智慧树2023年天津大学

算法设计与分析知到章节测试答案智慧树2023年最新天津大学第一章测试1.下列关于效率的说法正确的是()。
参考答案:提高程序效率的根本途径在于选择良好的设计方法,数据结构与算法;效率主要指处理机时间和存储器容量两个方面;效率是一个性能要求,其目标应该在需求分析时给出2.算法的时间复杂度取决于()。
参考答案:问题的规模;待处理数据的初态3.计算机算法指的是()。
参考答案:解决问题的有限运算序列4.归并排序法的时间复杂度和空间复杂度分别是()。
参考答案:O(nlog2n);O(n)5.将长度分别为m,n的两个单链表合并为一个单链表的时间复杂度为O(m+n)。
()参考答案:错6.用渐进表示法分析算法复杂度的增长趋势。
()参考答案:对7.算法分析的两个主要方面是时间复杂度和空间复杂度的分析。
()参考答案:对8.某算法所需时间由以下方程表示,求出该算法时间复杂度()。
参考答案:O(nlog2n)9.下列代码的时间复杂度是()。
参考答案:O(log2N)10.下列算法为在数组A[0,...,n-1]中找出最大值和最小值的元素,其平均比较次数为()。
参考答案:3n/2-3/2第二章测试1.可用Master方法求解的递归方程的形式为()。
参考答案:T(n)=aT(n/b)+f(n) , a≥1, b>1, 为整数, f(n)>0.2.参考答案:对3.假定,, 递归方程的解是. ( )参考答案:对4.假设数组A包含n个不同的元素,需要从数组A中找出n/2个元素,要求所找的n/2个元素的中点元素也是数组A的中点元素。
针对该问题的任何算法需要的时间复杂度的下限必为。
( )参考答案:错5.使用Master方法求解递归方程的解为().参考答案:6.考虑包含n个二维坐标点的集合S,其中n为偶数,且所有坐标点中的均不相同。
一条竖直的直线若能把S集合分成左右两部分坐标点个数相同的子集合,则称直线L为集合S的一条分界线。
若给定集合S,则可在时间内找到这条分界线L。
《算法设计与分析》实验指导书_bfm(全)

《算法设计与分析》实验指导书本书是为配合《算法分析与设计实验教学大纲》而编写的上机指导,其目的是使学生消化理论知识,加深对讲授内容的理解,尤其是一些算法的实现及其应用,培养学生独立编程和调试程序的能力,使学生对算法的分析与设计有更深刻的认识。
上机实验一般应包括以下几个步骤:(1)、准备好上机所需的程序。
手编程序应书写整齐,并经人工检查无误后才能上机。
(2)、上机输入和调试自己所编的程序。
一人一组,独立上机调试,上机时出现的问题,最好独立解决。
(3)、上机结束后,整理出实验报告。
实验报告应包括:题目、程序清单、运行结果、对运行情况所作的分析。
本书共分阶段4个实验,每个实验有基本题和提高题。
基本题必须完成,提高题根据自己实际情况进行取舍。
题目不限定如下题目,可根据自己兴趣爱好做一些与实验内容相关的其他题目,如动态规划法中的图象压缩,回溯法中的人机对弈等。
其具体要求和步骤如下:实验一分治与递归(4学时)一、实验目的与要求1、熟悉C/C++语言的集成开发环境;2、通过本实验加深对递归过程的理解二、实验内容:掌握递归算法的概念和基本思想,分析并掌握“整数划分”问题的递归算法。
三、实验题任意输入一个整数,输出结果能够用递归方法实现整数的划分。
四、实验步骤1.理解算法思想和问题要求;2.编程实现题目要求;3.上机输入和调试自己所编的程序;4.验证分析实验结果;5.整理出实验报告。
一、实验目的与要求1、掌握棋盘覆盖问题的算法;2、初步掌握分治算法二、实验题:盘覆盖问题:在一个2k×2k个方格组成的棋盘中,恰有一个方格与其它方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。
在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
三、实验提示void chessBoard(int tr, int tc, int dr, int dc, int size) {if (size == 1) return;int t = tile++, // L型骨牌号s = size/2; // 分割棋盘// 覆盖左上角子棋盘if (dr < tr + s && dc < tc + s)// 特殊方格在此棋盘中chessBoard(tr, tc, dr, dc, s);else {// 此棋盘中无特殊方格// 用t 号L型骨牌覆盖右下角board[tr + s - 1][tc + s - 1] = t;// 覆盖其余方格chessBoard(tr, tc, tr+s-1, tc+s-1, s);}// 覆盖右上角子棋盘if (dr < tr + s && dc >= tc + s)// 特殊方格在此棋盘中chessBoard(tr, tc+s, dr, dc, s);else {// 此棋盘中无特殊方格// 用t 号L型骨牌覆盖左下角board[tr + s - 1][tc + s] = t;// 覆盖其余方格chessBoard(tr, tc+s, tr+s-1, tc+s, s);}// 覆盖左下角子棋盘if (dr >= tr + s && dc < tc + s)// 特殊方格在此棋盘中chessBoard(tr+s, tc, dr, dc, s);else {// 用t 号L型骨牌覆盖右上角board[tr + s][tc + s - 1] = t;// 覆盖其余方格chessBoard(tr+s, tc, tr+s, tc+s-1, s);}// 覆盖右下角子棋盘if (dr >= tr + s && dc >= tc + s)// 特殊方格在此棋盘中chessBoard(tr+s, tc+s, dr, dc, s);else {// 用t 号L型骨牌覆盖左上角board[tr + s][tc + s] = t;// 覆盖其余方格chessBoard(tr+s, tc+s, tr+s, tc+s, s);}}一、实验目的与要求1、熟悉二分搜索算法;2、初步掌握分治算法;二、实验题1、设a[0:n-1]是一个已排好序的数组。
《算法设计与分析》考试题目及答案(DOC)

《算法设计与分析》考试题目及答案(DOC)D. 预排序与递归调用7. 回溯法在问题的解空间树中,按(D)策略,从根结点出发搜索解空间树。
A.广度优先B. 活结点优先 C.扩展结点优先 D. 深度优先8. 分支限界法在问题的解空间树中,按(A)策略,从根结点出发搜索解空间树。
A.广度优先B. 活结点优先 C.扩展结点优先 D. 深度优先9. 程序块(A)是回溯法中遍历排列树的算法框架程序。
A.B.C.D. void backtrack (int t){if (t>n) output(x);elsefor (int i=t;i<=n;i++) {swap(x[t], x[i]);if (legal(t)) backtrack(t+1); swap(x[t], x[i]);}}void backtrack (int t){if (t>n) output(x);elsefor (int i=0;i<=1;i++) {x[t]=i;if (legal(t)) backtrack(t+1); }}10. 回溯法的效率不依赖于以下哪一个因素?(C )A.产生x[k]的时间;B.满足显约束的x[k]值的个数;C.问题的解空间的形式;D.计算上界函数bound的时间;E.满足约束函数和上界函数约束的所有x[k]的个数。
F.计算约束函数constraint的时间;11. 常见的两种分支限界法为(D)A. 广度优先分支限界法与深度优先分支限界法;B. 队列式(FIFO)分支限界法与堆栈式分支限界法;C. 排列树法与子集树法;D. 队列式(FIFO)分支限界法与优先队列式分支限界法;12. k带图灵机的空间复杂性S(n)是指(B)A.k带图灵机处理所有长度为n的输入时,在某条带上所使用过的最大方格数。
B.k带图灵机处理所有长度为n的输入时,在k条带上所使用过的方格数的总和。
C.k带图灵机处理所有长度为n的输入时,在k条带上所使用过的平均方格数。
数的顺序技巧

数的顺序技巧数的顺序技巧是指在进行数字排列或排序时,使用一些方法和技巧来使得数字的顺序更加有条理和合理。
这些技巧可以应用于不同领域和情境中,包括数学、编程、数据分析等等。
在数学领域中,常见的数的顺序技巧有以下几种:1. 升序和降序排列:升序指数字从小到大排列,降序指数字从大到小排列。
这是最基本的数的顺序技巧,通常可以通过比较数字的大小来实现。
2. 递增和递减排列:递增指数字按照一定的间隔逐渐增加,递减指数字按照一定的间隔逐渐减小。
例如,从1开始,每次加2排列得到的序列就是递增的。
递增和递减排列常常用于问题求解和模式发现。
3. 素数排列:素数是只能被1和自身整除的数,素数排列指将一组数字按照素数的大小进行排序。
由于素数的特殊性,素数排列可以帮助人们更好地理解素数的规律和性质。
4. 斐波那契数列排列:斐波那契数列是指从1、1开始,后面的每个数都是前面两个数之和的数列。
将一组数字按照斐波那契数列的规则进行排列,可以帮助人们更好地理解和应用斐波那契数列的性质。
在编程领域中,数的顺序技巧可以应用于算法和数据结构的设计和优化中。
以下是一些常见的数的顺序技巧在编程中的应用:1. 排序算法:排序算法是指将一组数字按照一定的规则进行排序的算法。
常见的排序算法有冒泡排序、插入排序、选择排序、快速排序等等。
通过选择合适的排序算法,可以使得数字的顺序更加有序,提高程序的效率。
2. 优先队列:优先队列是一种特殊的数据结构,它能够根据元素的优先级进行排序和访问。
通常优先队列使用堆这种数据结构来实现。
通过使用优先队列,可以使得数字按照一定的规则进行排序,提高程序的效率和准确性。
3. 二分查找:二分查找是一种高效的查找算法,它可以在有序数组中快速地找到某个元素的位置。
通过使用二分查找,可以使得数字按照一定的顺序进行查找,提高程序的效率。
在数据分析领域中,数的顺序技巧可以应用于对数据的整理和分析中。
以下是一些常见的数的顺序技巧在数据分析中的应用:1. 数据排序:将大量数据按照某个指标进行排序,可以帮助人们更好地理解数据的分布和规律。
算法设计与分析考试题及答案

一、填空题(20分)1.一个算法就是一个有穷规则的集合,其中之规则规定了解决某一特殊类型问题的一系列运算,此外,算法还应具有以下五个重要特性:_________,________,________,__________,__________。
2.算法的困难性有_____________和___________之分,衡量一个算法好坏的标准是______________________。
3.某一问题可用动态规划算法求解的显著特征是____________________________________。
4.若序列X={B,C,A,D,B,C,D},Y={A,C,B,A,B,D,C,D},请给出序列X和Y的一个最长公共子序列_____________________________。
5.用回溯法解问题时,应明确定义问题的解空间,问题的解空间至少应包含___________。
6.动态规划算法的基本思想是将待求解问题分解成若干____________,先求解___________,然后从这些____________的解得到原问题的解。
7.以深度优先方式系统搜寻问题解的算法称为_____________。
8.0-1背包问题的回溯算法所需的计算时间为_____________,用动态规划算法所需的计算时间为____________。
9.动态规划算法的两个基本要素是___________和___________。
10.二分搜寻算法是利用_______________实现的算法。
二、综合题(50分)1.写出设计动态规划算法的主要步骤。
2.流水作业调度问题的johnson算法的思想。
3.若n=4,在机器M1和M2上加工作业i所需的时间分别为a i和b i,且(a1,a2,a3,a4)=(4,5,12,10),(b1,b2,b3,b4)=(8,2,15,9)求4个作业的最优调度方案,并计算最优值。
4.运用回溯法解0/1背包问题:n=3,C=9,V={6,10,3},W={3,4,4},其解空间有长度为3的0-1向量组成,要求用一棵完全二叉树表示其解空间(从根动身,左1右0),并画出其解空间树,计算其最优值及最优解。
优先队列式分支限界法求解0-1背包问题

算法分析与设计实验报告第7 次实验}1、测试自己输入的小规模数据2、测试随机生成1003、随机生成1000数据4、随机生成1000数据附录:完整代码#include <iostream>#include<time.h>#include<algorithm>#include<fstream>using namespace std;ifstream in("input.txt");ofstream out("output.txt");typedef int Typew;typedef int Typep;//物品类class Object{friend Typep Knapsack(Typew *, Typep *, Typew, int, int *); public:int operator <= (Object a) const{return (d >= a.d);}private:int ID; //物品编号float d; //单位重量价值};//树结点类class bbnode{friend class Knap;friend Typep Knapsack(Typew *, Typep *, Typew, int, int *); private:bbnode *parent; //指向父节点的指针int LChild;};//堆结点类class HeapNode{friend class Knap;friend class MaxHeap;public:operator Typep()const{return uprofit;};private:Typep uprofit, //结点的价值上界profit; //结点所相应的价值Typew weight; //结点所相应的重量int level; //活结点在子集树中所处的层序号bbnode *elemPtr; //指向该活结点在子集树中相应结点的指针};//最大堆类class MaxHeap{public:MaxHeap(int maxElem){HeapElem = new HeapNode* [maxElem+1]; //下标为0的保留capacity = maxElem;size = 0;}void InsertMax(HeapNode *newNode);HeapNode DeleteMax(HeapNode* &N);private:int capacity;int size;HeapNode **HeapElem;};//0-1背包问题的主类class Knap{friend Typep Knapsack(Typew *, Typep *, Typew, int, int *); public:Typep MaxKnapsack();private:MaxHeap *H;Typep Bound(int i);void AddLiveNode(Typep up, Typep cp, Typew cw, int ch, int level);bbnode *E; //指向扩展结点的指针Typew c; //背包容量int n; //物品总数Typew *w; //物品重量数组(以单位重量价值降序)Typep *p; //物品价值数组(以单位重量价值降序)Typew cw; //当前装包重量Typep cp; //当前装包价值int *bestx; //最优解};void MaxHeap::InsertMax(HeapNode *newNode){int i = 1;for (i = ++size; i/2 > 0 && HeapElem[i/2]->uprofit < newNode->uprofit; i /= 2){HeapElem[i] = HeapElem[i/2];}HeapElem[i] = newNode;}HeapNode MaxHeap::DeleteMax(HeapNode *&N){if(size >0 ){N = HeapElem[1];int i = 1;while(i < size){if(((i*2 +1) <= size) && HeapElem[i*2]->uprofit > HeapElem[i*2 +1]->uprofit){HeapElem[i] = HeapElem[i*2];i = i*2;}else{if(i*2 <= size){HeapElem[i] = HeapElem[i*2];i = i*2;}elsebreak;}}if(i < size)HeapElem[i] = HeapElem[size];}size--;return *N;}Typep Knap::MaxKnapsack(){H = new MaxHeap(10000);bestx = new int [n+1];int i = 1;E = 0;cw = 0;cp = 0;Typep bestp = 0;Typep up = Bound(1);while (i != n+1){Typew wt = cw + w[i];if(wt <= c) {if(cp + p[i] > bestp)bestp = cp + p[i];AddLiveNode(up, cp + p[i], cw + w[i], 1, i);}up = Bound(i + 1);if(up >= bestp)AddLiveNode(up, cp, cw, 0, i);HeapNode* N;H->DeleteMax(N);E = N->elemPtr;cw = N->weight;cp = N->profit;up = N->uprofit;i = N->level + 1;}for (int i = n; i > 0; i--){bestx[i] = E->LChild;E = E->parent;}return cp;}Typep Knap::Bound(int i){Typew cleft = c - cw;Typep b = cp;while (i<=n && w[i] <= cleft){cleft -= w[i];b += p[i];i++;}if(i<=n) b += p[i]/w[i] * cleft;return b;}void Knap::AddLiveNode(Typep up, Typep cp, Typew cw, int ch, int level) {bbnode *b=new bbnode;b->parent=E;b->LChild=ch;HeapNode *N = new HeapNode;N->uprofit=up;N->profit=cp;N->weight=cw;N->level=level;N->elemPtr=b;H->InsertMax(N);}//Knapsack返回最大价值,最优值保存在bestxTypep Knapsack(Typew *w, Typep *p, Typew c, int n, int *bestx){Typew W = 0;Typep P = 0;Object *Q = new Object[n];for(int i =1; i<=n; i++){Q[i-1].ID = i;Q[i-1].d = 1.0*p[i]/w[i];P += p[i];W += w[i];}if (W <= c){for(int i =1; i<=n; i++){bestx[i] = p[i];}return P;}for(int i = 1; i<n; i++)for(int j = 1; j<= n-i; j++){if(Q[j-1].d < Q[j].d){Object temp = Q[j-1];Q[j-1] = Q[j];Q[j] = temp;}}Knap K;K.p = new Typep [n+1];K.w = new Typew [n+1];for(int i = 1; i<=n; i++){K.p[i] = p[Q[i-1].ID];K.w[i] = w[Q[i-1].ID];}K.cp = 0;K.cw = 0;K.c = c;K.n = n;Typep bestp = K.MaxKnapsack();for(int i = 1; i<=n; i++){bestx[Q[i-1].ID] = K.bestx[i];}delete [] Q;delete [] K.w;delete [] K.p;delete [] K.bestx;delete [] K.H;return bestp;}int main(){cout<<"请在input.txt文件中输入物品数量、背包容量"<<endl;int N ;in>>N;Typew c; //背包容量in>>c;int bestx[N+1]; //最优解int bestp; //最优值Typep p[N+1];//物品价值Typew w[N+1];//物品重量cout<<"在input.txt文件中读取的物品总数N = "<< N<<",背包容量C = "<< c<<endl; cout<<"请选择生成数据的规模大小:200请输入1,2000请输入2,20000请输入3"<<endl; int x;cin>>x;if(x==1){ofstream in1("input1.txt");srand(time(NULL));int n=200;int *a=new int[n];for(int i=0;i<n;i++){a[i]=rand()%91;in1<<a[i]<<" ";}cout<<"随机数已请生成到input1文件中,请将数据添加到input.txt文件中"<<endl; }else if(x==2){ofstream in1("input1.txt");srand(time(NULL));int n=2000;int *a=new int[n];for(int i=0;i<n;i++){a[i]=rand()%91;in1<<a[i]<<" ";}cout<<"随机数已请生成到input1文件中,请将数据添加到input.txt文件中"<<endl; }else if(x==3){ofstream in1("input1.txt");srand(time(NULL));int n=20000;int *a=new int[n];for(int i=0;i<n;i++){a[i]=rand()%91;in1<<a[i]<<" ";}cout<<"随机数已请生成到input1文件中,请将数据添加到input.txt文件中"<<endl;}cout<<"添加完毕后请输入1"<<endl;int m;cin>>m;clock_t start,finish;start=clock();for (int i = 1; i <= N; i++){in>>w[i];}for (int i = 1; i <= N; i++){in>>p[i];}cout<<"已在input文件中读取物品重量和价值。
算法设计与分析复习题目及答案 (3)

分治法1、二分搜索算法是利用(分治策略)实现的算法。
9. 实现循环赛日程表利用的算法是(分治策略)27、Strassen矩阵乘法是利用(分治策略)实现的算法。
34.实现合并排序利用的算法是(分治策略)。
实现大整数的乘法是利用的算法(分治策略)。
17.实现棋盘覆盖算法利用的算法是(分治法)。
29、使用分治法求解不需要满足的条件是(子问题必须是一样的)。
不可以使用分治法求解的是(0/1背包问题)。
动态规划下列不是动态规划算法基本步骤的是(构造最优解)下列是动态规划算法基本要素的是(子问题重叠性质)。
下列算法中通常以自底向上的方式求解最优解的是(动态规划法)备忘录方法是那种算法的变形。
(动态规划法)最长公共子序列算法利用的算法是(动态规划法)。
矩阵连乘问题的算法可由(动态规划算法B)设计实现。
实现最大子段和利用的算法是(动态规划法)。
贪心算法能解决的问题:单源最短路径问题,最小花费生成树问题,背包问题,活动安排问题,不能解决的问题:N皇后问题,0/1背包问题是贪心算法的基本要素的是(贪心选择性质和最优子结构性质)。
回溯法回溯法解旅行售货员问题时的解空间树是(排列树)。
剪枝函数是回溯法中为避免无效搜索采取的策略回溯法的效率不依赖于下列哪些因素(确定解空间的时间)分支限界法最大效益优先是(分支界限法)的一搜索方式。
分支限界法解最大团问题时,活结点表的组织形式是(最大堆)。
分支限界法解旅行售货员问题时,活结点表的组织形式是(最小堆)优先队列式分支限界法选取扩展结点的原则是(结点的优先级)在对问题的解空间树进行搜索的方法中,一个活结点最多有一次机会成为活结点的是( 分支限界法).从活结点表中选择下一个扩展结点的不同方式将导致不同的分支限界法,以下除( 栈式分支限界法)之外都是最常见的方式.(1)队列式(FIFO)分支限界法:按照队列先进先出(FIFO)原则选取下一个节点为扩展节点。
(2)优先队列式分支限界法:按照优先队列中规定的优先级选取优先级最高的节点成为当前扩展节点。
《算法分析与设计》(李春葆版)课后选择题答案与解析

《算法及其分析》课后选择题答案及详解第1 章——概论1.下列关于算法的说法中正确的有()。
Ⅰ.求解某一类问题的算法是唯一的Ⅱ.算法必须在有限步操作之后停止Ⅲ.算法的每一步操作必须是明确的,不能有歧义或含义模糊Ⅳ.算法执行后一定产生确定的结果A.1个B.2个C.3个D.4个2.T(n)表示当输入规模为n时的算法效率,以下算法效率最优的是()。
A.T(n)=T(n-1)+1,T(1)=1B.T(n)=2nC.T(n)= T(n/2)+1,T(1)=1D.T(n)=3nlog2n答案解析:1.答:由于算法具有有穷性、确定性和输出性,因而Ⅱ、Ⅲ、Ⅳ正确,而解决某一类问题的算法不一定是唯一的。
答案为C。
2.答:选项A的时间复杂度为O(n)。
选项B的时间复杂度为O(n)。
选项C 的时间复杂度为O(log2n)。
选项D的时间复杂度为O(nlog2n)。
答案为C。
第3 章─分治法1.分治法的设计思想是将一个难以直接解决的大问题分割成规模较小的子问题,分别解决子问题,最后将子问题的解组合起来形成原问题的解。
这要求原问题和子问题()。
A.问题规模相同,问题性质相同B.问题规模相同,问题性质不同C.问题规模不同,问题性质相同D.问题规模不同,问题性质不同2.在寻找n个元素中第k小元素问题中,如快速排序算法思想,运用分治算法对n个元素进行划分,如何选择划分基准?下面()答案解释最合理。
A.随机选择一个元素作为划分基准B.取子序列的第一个元素作为划分基准C.用中位数的中位数方法寻找划分基准D.以上皆可行。
但不同方法,算法复杂度上界可能不同3.对于下列二分查找算法,以下正确的是()。
A.intbinarySearch(inta[],intn,int x){intlow=0,high=n-1;while(low<=high){intmid=(low+high)/2;if(x==a[mid])returnmid;if(x>a[mid])low=mid;elsehigh=mid;}return –1;}B.intbinarySearch(inta[],intn,int x) { intlow=0,high=n-1;while(low+1!=high){intmid=(low+high)/2;if(x>=a[mid])low=mid;elsehigh=mid;}if(x==a[low])returnlow;elsereturn –1;}C.intbinarySearch(inta[],intn,intx) { intlow=0,high=n-1;while(low<high-1){intmid=(low+high)/2;if(x<a[mid])high=mid;elselow=mid;}if(x==a[low])returnlow;elsereturn –1;}D.intbinarySearch(inta[],intn,int x) {if(n>0&&x>=a[0]){intlow= 0,high=n-1;while(low<high){intmid=(low+high+1)/2;if(x<a[mid])high=mid-1;elselow=mid;}if(x==a[low])returnlow;}return –1;}答案解析:1.答:C。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
增加元素的键值/插入新元素
HEAP-INCREASE-KEY(A, i, key) 1 if key < A[i] 2 then error "new key is smaller than current key" 3 A[i] ← key 4 while i > 1 and A[PARENT(i)] < A[i] 5 do exchange A[i] ↔ A[PARENT(i)] i ← PARENT(i) 6 MAX-HEAP-INSERT(A, key) 1 heap-size[A] ← heap-size[A] + 1 2 A[heap-size[A]] ← -∞ 3 HEAP-INCREASE-KEY(A, heap-size[A], key)
11/13/2014 算法设计与分析-优先队列 5
建堆
BUILD-MAX-HEAP(A) 1 heap-size[A] ← length[A] 2 for i ← ⌊length[A]/2⌋ downto 1 3 do MAX-HEAPIFY(A, i) 总运行时间为O(n)。 合并堆的过程需要用 重建堆来实现。
11/13/2014
算法设计与分析-优先队列
6
取最大元素/取出最大元素
HEAP-MAXIMUM(A) 1 return A[1] HEAP-EXTRACT-MAX(A) 1 if heap-size[A] < 1 2 then error "heap underflow" 3 max ← A[1] 4 A[1] ← A[heap-size[A]] 5 heap-size[A] ← heap-size[A] - 1 6 MAX-HEAPIFY(A, 1) 7 return max
2 head[H] ← BINOMIAL-HEAP-MERGE(H1, H2) 3 free the objects H1 and H2 but not the lists they point to 4 if head[H] = NIL
5 then return H 6 prev-x ← NIL 7 x ← head[H] 8 next-x ← sibling[x] 9 while next-x ≠ NIL
• 设n = ∑0 ≤ i ≤ ⌊lgn⌋bi2i,因二项树Bk共有2k个结点,所以 • 二项树Bi出现于H中当且仅当位bi=1
11/13/2014
算法设计与分析-优先队列
13
二项堆的表示
11/13/2014
算法设计与分析-优先队列
14
创建一个空的二项堆
MAKE-BINOMIAL-HEAP () 1 head[H] ← NIL 2 return H 运行时间为O(1)
– 类似的,最小优先队列支持以下操作:
• INSERT(S, x)、MININUM(S) • EXTRACT-MIN(S)、DECREASE-KEY(S, x, k)
11/13/2014
算法设计与分析-优先队列
3
二叉堆
• 二叉堆是在一个数组上通过下标间关系维护父子结点关系 的一棵几乎满的二叉树 PARENT(i) return ⌊i/2⌋ LEFT(i) return 2i RIGHT(i) return 2i + 1
11/13/2014 算法设计与分析-优先队列 8
可合并堆
• 可合并堆(mergeable heaps)
– – – –
MAKE-HEAP() 创建一个空的堆 INSERT(H, x) 把具有键值key的结点x插入堆H. MINIMUM(H) 返回堆H 中具有最小键值的结点 EXTRACT-MIN(H) 删除堆H 中具有最小键值的结点并返回之
斐波那契堆* Θ(1) Θ(1) Θ(1) O(lg n) Θ(1) Θ(1) O(lg n)
注:二叉堆和二项堆都是最差情形下的开销,斐波那契堆则是平摊开销
11/13/2014
算法设计与分析-优先队列
10
二项树
• 二项堆是一组二项树的集合 • 二项树是一个递归定义的有序树
– 二项树B0包含一个结点;二项树Bk 由两棵二项树Bk-1链 接而成,其中一棵树的根是另一棵树的根的最左孩子
20
11/13/2014
算法设计与分析-优先队列
21
11/13/2014
算法设计与分析-优先队列
22
插入一个结点
BINOMIAL-HEAP-INSERT(H, x) 1 H′ ← MAKE-BINOMIAL-HEAP() 2 p[x] ← NIL 3 child[x] ← NIL 把新结点作为一个二项堆H′和H合并, 4 sibling[x] ← NIL 运行时间为O(lgn)
合并堆的运行时间为O(lgn)
BINOMIAL-LINK(y,z)把两个Bk-1 的二项树链接成一个Bk的二项树, z成为y的父结点。 合并操作是后面各种操作的基础
11/13/2014
算法设计与分析-优先队列
17
合并两个二项堆
BINOMIAL-HEAP-UNION(H1, H2) 1 H ← MAKE-BINOMIAL-HEAP()
算法设计与分析
讲授内容:优先队列 教 师:胡学钢、吴共庆
2014年11月13日
纲要
• 优先队列和二叉堆 • 二项树及二项堆 • 斐波那契堆
11/13/2014
算法设计与分析-优先队列
2
优先队列
• 优先队列
– 一种关于集合S的数据结构,集合中的元素都有键值key – 最大优先队列支持以下操作:
• • • • INSERT(S, x):把元素x插入集合S,可表示为S←S∪{x} MAXIMUM(S) :返回集合S中具有最大键值的元素 EXTRACT-MAX(S):去掉并返回集合S中具有最大键值的元素 INCREASE-KEY(S, x, k):将元素x的键值增加到k,这里要求k 不能小于x的原键值。
– UNION(H1, H2) 创建一个包含了堆H1和堆H2所有结点的 新堆,原来的堆H1和堆H2 被此操作“销毁” • 其他两个堆上的操作
– DECREASE-KEY(H, x, k) 给堆H中的结点x一个新键值k,新键值不 应比结点x原来的键值大 – DELETE(H, x) 删除堆H中的结点
11/13/2014
11/13/2014
算法设计与分析-优先队列
15
取最小键值的结点
BINOMIAL-HEAP-MINIMUM(H) 1 y ← NIL 2 x ← head[H] 3 min ← ∞ 二项堆是最小堆有序的,所以 最小键值必在某个二项树的根 4 while x ≠ NIL 结点中,只需遍历所有的根即 5 do if key[x] < min 可找到最小键值的根结点 then min ← key [ x ] 6 y←x 7 运行时间为O(lgn) x ← sibling[x] 8 9 return y
算法设计与分析-优先队列
9
不同堆上的操作开销比较
操作 MAKE-HEAP INSERT MINIMUM EXTRACT-MIN UNION DECREASE-KEY DELETE 二叉堆 Θ(1) Θ(lg n) Θ(1) Θ(lg n) Θ(n) Θ(lg n) Θ(lg n) 二项堆 Θ(1) O(lg n) O(lg n) Θ(lg n) O(lg n) Θ(lg n) Θ(lg n)
算法设计与分析-优先队列
12
二项堆
• 二项堆H由一组满足二项堆性质的二项树组成
1. H中的每个二项树遵循最小堆的性质;结点的键值大 于等于其父结点的键值(这种树为最小堆有序的)
2. 对任意非负整数k,在H中至多有一棵二项树的根具有 度数k• 由二项堆的性质,我们有
– 一棵最小堆有序的二项树的根包含了树中最小的键值 – 有n个结点的二项堆中,包含至多⌊lgn⌋+1棵二项树
11/13/2014 算法设计与分析-优先队列 24
11/13/2014
算法设计与分析-优先队列
25
减小一个结点的键值
BINOMIAL-HEAP-DECREASE-KEY(H, x, k) 1 if k > key[x] 2 then error "new key is greater than current key" 3 key[x] ← k 把减小了键值的结点在满足最小堆 有序的二 项树上向根结点方向交换移动 4y←x 运行时间为O(lgn) 5 z ← p[y] 6 while z ≠ NIL and key[y] < key[z] 7 do exchange key[y] ↔ key[z] ▸ If y and z have satellite fields, exchange them, too. 8 y←z 9 z ← p[y] 10
▹ Cases 1 and 2 ▹ Cases 1 and 2
▹ Case 3
▹ ▹ ▹ ▹
Case 3 Case 4 Case 4 Case 4
▹ Case 4 ▹ Case 4
11/13/2014
算法设计与分析-优先队列
19
把两二项堆的根列表合并为按度 数非递减的列表
11/13/2014
出现三个度数相同的 算法设计与分析-优先队列 根时,合并后面两个
• 二项树Bk的性质
1. 共有2k个结点(设二项树Bk包含n个结点,则k=lgn) 2. 树的高度为k 3. 4. 根的度数为k,它大于任何其他结点的度;并且根的 子女从左到右编号k-1,k-2,...,0,则子女i是子树Bi的根
11/13/2014
算法设计与分析-优先队列
11
二项树的例子