算法导论——优先队列(基于堆排序)
2018-03-17 12:50
253 查看
#include<stdio.h> #include<iostream> using namespace std; #define Length 10 void MaxHeapify(int num[], int i, int len);//堆调整 void BuildHeap(int num[], int len);//建立初始最大队 int Heapsort(int num[], int len);//堆排序 int HeapExtractMax(int num[], int len);//优先队列 利用堆排序 void HeapIncreaseKey(int num[], int i, int key);//增大堆中指定位置的关键字的值 void Output(int num[], int len); int main () { int num[Length] = {12, 2, 34, 56, 26, 8, 31, 6, 20, 3}; BuildHeap(num, Length); cout << "初始堆:" <<endl; Output(num, Length); cout << endl << "将指定位置的关键字的值增加并调整成新堆: " << endl; HeapIncreaseKey(num, 7, 99); Output(num, Length); int key = HeapExtractMax(num, Length);//与BuildHeap配套使用 printf("\n优先队列(最大值): %d\n", key); cout << "\n将最大值输出并调整成新堆: "<< endl; Output(num, Length - 1); } //因为某未知的关键字的值增大 因此可能会改变最大堆的性质 因此需要对堆进行调整 void HeapIncreaseKey(int num[], int i, int key)//见图IncreaseKey { int t; if (key < num[i]) { cout << "new key is smaller than current key"; return; } num[i] = key;//将指定位置的关键字的值进行增加 while(i > 0 && num[i / 2] < num[i]) //i/2代表的是i的双亲结点 因为本函数是进行关键只增加的操作 因此只需要逐级向上比较 {//最好是i>0因为i=0时以下操作都是对0自身的操作 无意义 t = num[i]; num[i] = num[i / 2]; num[i / 2] = t; i /= 2; } } int HeapExtractMax(int num[], int len) { if(len < 1) printf("error!!"); int max = num[0]; int t = num[0]; num[0] = num[len - 1]; num[len - 1] = t; len--; MaxHeapify(num, 0, len - 1); return max; } //堆排序的关键是一定要搞清楚len 在每个函数中的不同值 是长度还是下标 int Heapsort(int num[], int len)//此处的len代表的是实际长度 { int t; for(int i = len - 1; i >= 1; i--)//在堆排序的过程中0位存储的是最大值 因此每次进行排序的时候都将0位的元素和最后一位进行交换 { t = num[i]; num[i] = num[0]; num[0] = t; len--;//每执行一次就可以得到高位的一个元素 此时len应该-1 即每次执行的长度是递减的 MaxHeapify(num, 0, len - 1); //一定是len - 1!!! 因为在MaxHeapify中 第三个参数代表的是数组的角标 比实际长度小1 } } //BuildHeap只是用一次 即构建初始堆 因为之后的对调整函数需要在初始堆的基础上进行操作 void BuildHeap(int num[], int len)//建堆 len是长度 利用给定的数组num { for(int i = len/2; i >= 0; i--)//i的初始值是 len/2向下取整 利用的是二叉树中双亲结点与子节点之间的下标关系 { MaxHeapify(num, i, len - 1);//在MaxHeapify中 }//for循环结束后 就构建好了初始堆 } //这个函数的作用是调整堆 void MaxHeapify(int num[], int i, int len)//见图Heapsort { int left = 2 * i;//left是i的左孩子的下标 由二叉树的性质可以知道 int right = 2 * i + 1; int largest, t; //下面几行语句的作用是在i以及i的左右孩子中找到最大值 并将其位置保存在largest中 if(left <= len && num[left] > num[i]) largest = left; else largest = i; if(right <= len && num[right] > num[largest]) largest = right; if(largest != i)//满足if条件则说明 i的其中一个子节点大于它 并将出现交换的操作 { t = num[i]; num[i] = num[largest]; num[largest] = t; MaxHeapify(num, largest, len);//交换之后需要重新判断原i的值是否比原largest的全部子节点的值都大 } } void Output(int num[], int len) { for(int i=0; i<len; i++) { printf("%d ", num[i]); } cout << endl; }
相关文章推荐
- 算法导论(第三版)第六章 堆排序的全部实现(堆排序,优先队列)
- 算法导论-第六章-堆排序:基于最大堆的排序C++实现
- 《算法导论》堆排序和优先队列
- 基于堆得优先队列
- 改进基于优先队列的最短路径搜索『洪水流思想的体现』
- 用java实现一个基于堆排序的优先队列
- 【CLRS】《算法导论》读书笔记(一):堆排序(Heapsort)
- 《算法导论》读书笔记--堆排序
- Python实现冒泡排序、选择排序、插入排序、快速排序、归并排序、二分法查找算法(基于《算法导论》伪代码)
- 最小生成树之Prime算法(基于优先队列)
- 算法导论c++ 堆排序以堆类结构完整实现
- 算法导论 堆排序
- 算法导论—堆排序(python)
- 基于二叉树的堆排序、优先队列、二叉查找树、平衡查找树、B树详解
- 《算法导论》优先队列
- 算法导论习题6-堆排序
- 算法导论 第6章 堆排序(简单选择排序、堆排序)
- 算法导论 第六章:堆排序
- 堆、堆排序和优先队列
- 《算法导论》第六章“堆排序”习题解答