最大(小)堆和堆排序简介
2017-04-14 10:19
399 查看
(注:本文的相关叙述和图片摘自《数据结构与算法分析新视角》(周幸妮等),因此本文只是我的一个复习记录,详细的论述请参考该书。)
因此,对于堆排序来说,主要有两个问题:
一个无序序列的所有记录如何排列成一个堆?
在输出了堆顶记录后,如何将剩下的记录再排成一个堆?
以序列{49,38,65,97,76,13,27,49,55,04}为例,介绍生成最小堆的思路。我们知道一棵完全二叉树的最后一个非叶子结点的索引为[n/2],因此在本例中,选择第5个记录{76}作为初始筛选点。首先比较{76}与其左右孩子结点记录的大小,并按照筛选的结果进行交换,因此得到下图2的结果。接下来对倒数第二个非叶子结点进行处理,结果如下图3所示。重复这个步骤,可以得到一个结构完整的最小堆,如下图4所示。
(1)序列直接构成完全二叉树 (2)一次筛选之后的完全二叉树 (3)二次筛选之后的完全二叉树
(4)经过多次筛选之后的最小堆
堆排序
以序列{13,38,27,49,76,65,49,97}为例,介绍堆排序的思路。
初始堆 输出堆顶元素后的情形
最后一个记录暂放于堆顶 一次调整之后的情形
二次调整之后的情况 输出记录{27}之后再排成一个堆
重复上述步骤,最终就可以生成一个有序序列。
堆排序
验证
输出结果:
49 38 65 97 76 13 27 49 55 4
4 13 27 38 49 49 55 65 76 97
1. 最大(小)堆
对于一个完全二叉树来说,如果所有的结点(叶子结点除外)的值都大于(小于)其左右孩子结点的值,那么这个完全二叉树就被成为一个大(小)根堆。如下图所示。按照堆的定义可以发现,堆顶结点(二叉树的根结点)一定对应整个序列中的最大(小)记录。这样一来,可以设计一种排序思路,每次将堆的堆顶记录输出,同时调整剩余的记录,使它们从新排成一个堆。重复这个过程,就能最终得到一个有序的序列,完成排序的过程,这种方法称之为堆排序。因此,对于堆排序来说,主要有两个问题:
一个无序序列的所有记录如何排列成一个堆?
在输出了堆顶记录后,如何将剩下的记录再排成一个堆?
2. 堆排序
由无序序列生成堆以序列{49,38,65,97,76,13,27,49,55,04}为例,介绍生成最小堆的思路。我们知道一棵完全二叉树的最后一个非叶子结点的索引为[n/2],因此在本例中,选择第5个记录{76}作为初始筛选点。首先比较{76}与其左右孩子结点记录的大小,并按照筛选的结果进行交换,因此得到下图2的结果。接下来对倒数第二个非叶子结点进行处理,结果如下图3所示。重复这个步骤,可以得到一个结构完整的最小堆,如下图4所示。
(1)序列直接构成完全二叉树 (2)一次筛选之后的完全二叉树 (3)二次筛选之后的完全二叉树
(4)经过多次筛选之后的最小堆
堆排序
以序列{13,38,27,49,76,65,49,97}为例,介绍堆排序的思路。
初始堆 输出堆顶元素后的情形
最后一个记录暂放于堆顶 一次调整之后的情形
二次调整之后的情况 输出记录{27}之后再排成一个堆
重复上述步骤,最终就可以生成一个有序序列。
3. 相关代码
生成最大堆代码(最小堆类似)1 //调整堆结点 2 //arr:数组首地址;n:结点在数组中的位置;len:数组的长度 3 void adjust_node(int *arr, int n, int len) 4 { 5 int l, r, max, tmp; 6 l = 2 * n + 1; //左右孩子的索引,注意数组下标从0开始。 7 r = 2 * n + 2; 8 max = n; 9 10 if (l<len&&arr[l]>arr ) 11 max = l; 12 if (r<len&&arr[r]>arr[max]) 13 max = r; 14 15 if (max != n) 16 { 17 tmp = arr ; 18 arr = arr[max]; 19 arr[max] = tmp; 20 adjust_node(arr, max, len); //保证最大堆 21 } 22 }
堆排序
1 //堆排序(升序) 2 void sort_heap(int *arr, int len) 3 { 4 for (int i = len / 2; i >= 0; i--) 5 adjust_node(arr, i, len); 6 int tmp; 7 for (int i = len - 1; i >= 0; i--) 8 { 9 tmp = arr[0]; 10 arr[0] = arr[i]; 11 arr[i] = tmp; 12 adjust_node(arr, 0, i); 13 } 14 }
验证
1 #include <iostream> 2 using namespace std; 3 4 int main() 5 { 6 int arr[] = { 49,38,65,97,76,13,27,49,55,04 }; 7 int len = 10; 8 9 for (int i = 0; i < len; i++) 10 cout << arr[i] << ' '; 11 cout << endl; 12 15 sort_heap(arr, len); 16 17 for (int i = 0; i < len; i++) 18 cout << arr[i] << ' '; 19 cout << endl; 20 21 return 0; 22 }
输出结果:
49 38 65 97 76 13 27 49 55 4
4 13 27 38 49 49 55 65 76 97
相关文章推荐
- 第6章 堆排序 java实现 简单版 泛型版 最大优先级队列
- 最大堆排序
- c 最大堆排序
- 【算法导论】第六章 再谈 堆排序和最大优先级队列
- 算法设计之,堆,堆排序,基于最大堆的最大优先队列的实现(C++实现)
- 最大堆和堆排序
- 最大堆排序
- 最大的PHP开源网店系统ECShop简介
- 堆排序原理及算法实现(最大堆)
- 【数据结构】找出N个数据中最大的前k个数据(利用堆排序)
- 编程之美 -- 2.5 寻找最大的K个数(堆排序方法)
- C++实现数组最大堆排序
- 算法简介—堆与堆排序
- [151225] Python3 实现最大堆、堆排序,解决TopK问题
- CSS3 最小内容尺寸(min-content size)和最大内容尺寸(max-content size)简介
- 最大流-最小割简介
- 最大堆与堆排序
- 算法入门--堆排序(最大堆,从小到大排序)
- leetcode 628. Maximum Product of Three Numbers(C语言,堆排序,计算最大乘积)33
- 最大堆排序