数据结构与算法学习-堆排序
2016-11-10 18:56
435 查看
堆排序:
堆的标准定义如下:
n个元素的序列{k1, k2, …, kn}当且仅当满足以下关系时,称为堆。
可以简单理解为就是一个完全二叉树,但是比较特殊,即完全二叉树中所有非终端结点的值均不大于(或不小于)其左、右孩子结点的值。
示例:
小顶堆:意思就是堆顶的值是最小的
大顶堆:意思就是堆顶的值是最大的
知道了堆的性质,我们自然可以推出怎么排序,首先需要把输入的数组构建成一个小顶堆/大顶堆,只需要每次把堆顶和无序的最后一个元素交换,然后更新堆,再交换,再更新。。。。就可以达到有序了。
具体步骤:
1. 先将输入的数据构建成小顶堆/大顶堆
2. 将堆顶a[1]和最后一个元素a[i]交换,i–
3. 更新堆,使其重新成为小顶堆/大顶堆
4. 一直重复第2步和第3步,直到i==1为止。
代码如下:
以该图为例:
第一步我们输入{13,38,27,49,76,65},希望输出升序排列,即{13,27,38,49,65,76}
第二步先构建成大顶堆。
第三步将76和27互换,
最后还有一点,堆排序适用于大文件,而不适用于小数据。
堆的标准定义如下:
n个元素的序列{k1, k2, …, kn}当且仅当满足以下关系时,称为堆。
(Ki<=K2i&&Ki<=K2i+1)或(Ki>=K2i&&Ki>=K2i+1)
(i = 1, 2, ..., n/2)
可以简单理解为就是一个完全二叉树,但是比较特殊,即完全二叉树中所有非终端结点的值均不大于(或不小于)其左、右孩子结点的值。
示例:
小顶堆:意思就是堆顶的值是最小的
大顶堆:意思就是堆顶的值是最大的
知道了堆的性质,我们自然可以推出怎么排序,首先需要把输入的数组构建成一个小顶堆/大顶堆,只需要每次把堆顶和无序的最后一个元素交换,然后更新堆,再交换,再更新。。。。就可以达到有序了。
具体步骤:
1. 先将输入的数据构建成小顶堆/大顶堆
2. 将堆顶a[1]和最后一个元素a[i]交换,i–
3. 更新堆,使其重新成为小顶堆/大顶堆
4. 一直重复第2步和第3步,直到i==1为止。
代码如下:
#include <iostream> using namespace std; #include <cstdio> int min(int x, int y) { if(x < y) return 0; return 1; } void HeapAdjust(int a[], int s, int m) //调整堆,使其有序 { int temp = a[s]; for(int j = 2*s; j <= m; j *= 2) { if(j < m && min(a[j+1], a[j])) { j++; } if(!min(a[j], temp)) break; a[s] = a[j]; s = j; } a[s] = temp; } void HeapSort(int a[], int len) { for(int i = len/2; i > 0; --i) //先将输入的乱序数组构建成堆,对应第1步 { HeapAdjust(a, i, len); } for(int i = len; i > 1; --i) //交换a[1]和a[i]的值,更新堆。对应第2,3步 { int temp = a[1]; a[1] = a[i]; a[i] = temp; HeapAdjust(a, 1, i-1); } } int main() { int a[11] = {0}; for(int i = 1; i <= 10; i++) { scanf("%d", &a[i]); } HeapSort(a, 10); for(int i = 1; i <= 10; i++) { printf("%d\n", a[i]); } return 0; }
以该图为例:
第一步我们输入{13,38,27,49,76,65},希望输出升序排列,即{13,27,38,49,65,76}
第二步先构建成大顶堆。
HeapAdjust(a, 3, 6),比较27和65的大小,27<65,则两者互换。
HeapAdjust(a, 2, 6),比较49和76的大小,再将其中的较大者和38比较,于是76和38互换。
HeapAdjust(a, 1, 6),比较76和65的大小,再将其中较大者和13比较,于是76和13互换,此时的13比它的子结点小,于是又进行了一次互换,将49和38的较大者和13互换了。此时就得到了一个大顶堆。
第三步将76和27互换,
HeapAdjust(a, 1, 6-1),将65和49做比较,取较大者和a[1]的27交换,完成了第一次更新。将65和38互换位置,
HeapAdjust(a, 1, 5-1),由于38比它的子结点小,于是又要做交换,将49和38做交换,完成了第二次更新。将49和13互换位置,
HeapAdjust(a, 1, 4-1),38和27做比较,将较大者和13互换位置,即38和13互换,完成了第三次更新。将38和27互换位置,此时27就是最大元素了,完成了第四次更新。将27和13交换,此时只剩下13最后一个元素,完成了第五次更新,达到有序。
最后还有一点,堆排序适用于大文件,而不适用于小数据。
相关文章推荐
- JAVA 数据结构与算法学习笔记一(转载)
- 在emacs中用gdb调试学习算法与数据结构基础(1)_猜价格游戏
- 算法学习之数据结构之单链表反转,两两反转
- 数据结构与算法学习笔记——堆栈及其应用(10以内简单四则计算器)
- [数据结构算法学习] 单向链表
- 数据结构与算法学习之队列及队列的相关操作
- 算法学习之数据结构之二叉查找树
- 数据结构及算法学习总结(一)
- 算法学习之数据结构之红黑树(一)
- 数据结构及算法学习——写在前面的话
- 要学习的数据结构与算法
- 转:C#数据结构和算法学习系列十二----散列HashTable类
- 数据结构与算法学习心得
- 算法学习之数据结构之链表是否相交,链表是否存在环
- c# 数据结构算法学习一:冒泡排序
- 转:C#数据结构和算法学习系列九----String类和StringBuilder类
- 转:C#数据结构和算法学习系列十一----构建字典DictionaryBase 类和SortedList 类
- 转:C#数据结构和算法学习系列十----正则表达式
- 数据结构与算法学习--链表
- 算法学习--数据结构2