排序算法之堆排序
2017-02-10 19:38
204 查看
堆排序比一般的排序算法略为复杂。
1.什么是二叉堆?
2.如何用数组描述一个二叉堆?
3.如果构建最大堆或最小堆
4.构建好最大堆或最小堆后,对堆的排序
1.什么是二叉堆?
二叉堆是完全二叉树或近似完全二叉树。而且任何父节点的键值都大于等于(或小于等于)任何一点子节点的兼职。
父节点键值大等于他的子节点的键值为最大堆,父节点键值小于等于他的子节点的键值为最小堆。
如下图,是一个二叉堆:
2.用数组描述一个二叉堆
如上面的二叉堆,用数组表示就是A[ 6 ] = {16,7,3,20,17,8};
这个方法跟描述树的方法是一样的。
3.构建最小堆(最大堆)
(以最大堆为例)
从堆 最后一个有叶子结点的结点 开始,设堆有 n 个元素,则该节点序号为:(n/2) -1,上图中该节点就是 3,也就是 A[ 6/2 -1 ] = A[2 ]
构建最大堆的过程:
原始堆。
先从 最后一个有叶子结点的结点(A[ 2 ]) 开始,8比3大,因此 位置互换。
然后到A[ 1 ] ,首先选出比较大的孩子结点,再跟父节点比,看哪个大。大的跟父节点换位置
然后到A[ 0 ].同上
把16换下来后,会发现红色圈的三个里面是 17 最大,因此把 17和 16的位置互换。
这就完成了最大堆了。可以开始排序
下面给出最大堆的构建代码:(最小堆就是找最小的)
4.对堆的排序
最小堆排序后得到的数组是 从大到小的。
最大堆排序后得到的数组是 从小到大的。
思路:若堆有 n 个元素。从A[0]入手,把A[0] 跟堆的最后一个元素A[n-1]互换,然后不管A[0]了,(因为构成了最大堆后,A[0]一定是堆中最大的),然后堆的总长度减去一,变成 n-1,然后继续A[0]跟最后一个元素(A[n-2])互换, 跟插入排序有点相似。
代码:
1.什么是二叉堆?
2.如何用数组描述一个二叉堆?
3.如果构建最大堆或最小堆
4.构建好最大堆或最小堆后,对堆的排序
1.什么是二叉堆?
二叉堆是完全二叉树或近似完全二叉树。而且任何父节点的键值都大于等于(或小于等于)任何一点子节点的兼职。
父节点键值大等于他的子节点的键值为最大堆,父节点键值小于等于他的子节点的键值为最小堆。
如下图,是一个二叉堆:
2.用数组描述一个二叉堆
如上面的二叉堆,用数组表示就是A[ 6 ] = {16,7,3,20,17,8};
这个方法跟描述树的方法是一样的。
3.构建最小堆(最大堆)
(以最大堆为例)
从堆 最后一个有叶子结点的结点 开始,设堆有 n 个元素,则该节点序号为:(n/2) -1,上图中该节点就是 3,也就是 A[ 6/2 -1 ] = A[2 ]
构建最大堆的过程:
原始堆。
先从 最后一个有叶子结点的结点(A[ 2 ]) 开始,8比3大,因此 位置互换。
然后到A[ 1 ] ,首先选出比较大的孩子结点,再跟父节点比,看哪个大。大的跟父节点换位置
然后到A[ 0 ].同上
把16换下来后,会发现红色圈的三个里面是 17 最大,因此把 17和 16的位置互换。
这就完成了最大堆了。可以开始排序
下面给出最大堆的构建代码:(最小堆就是找最小的)
/*若有结点 i,它的父结点为 (i/2) -1,其左结点是 2*i +1,右结点是 2*i +2*/ void MaxHeapFixdown(int a[], int i, int n) { int j, temp; temp = a[i]; //a[i] 相当于当前要处理的值 j = 2 * i + 1; //左子结点 while (j < n) //若 i 为叶子结点则退出循环 { if (j + 1 < n && a[j + 1] > a[j]) //在左右孩子中找最小的 ,若是构建最小堆,第二个大于号变成小于号 j++; if (a[j] <= temp) //若是构建最小堆,小于号变成大于号 break; a[i] = a[j]; //把较小的子结点往上移动,替换它的父结点 i = j; j = 2 * i + 1; //继续往下找出结点i 的左子节点 } a[i] = temp; } void MakeMaxHeap(int a[], int n) { int i; for( i = n / 2 - 1; i >= 0; i--) //从最后一个有叶子的结点 开始往根结点A[0],调整 { MaxHeapFixdown(a, i, n); } }
4.对堆的排序
最小堆排序后得到的数组是 从大到小的。
最大堆排序后得到的数组是 从小到大的。
思路:若堆有 n 个元素。从A[0]入手,把A[0] 跟堆的最后一个元素A[n-1]互换,然后不管A[0]了,(因为构成了最大堆后,A[0]一定是堆中最大的),然后堆的总长度减去一,变成 n-1,然后继续A[0]跟最后一个元素(A[n-2])互换, 跟插入排序有点相似。
代码:
void Sort(int a[], int n) { int i; for ( i = n - 1; i >= 1; i--) { swap(&a[i], &a[0]); //a[0]和最后一个元素交换 MaxHeapFixdown(a, 0, i); } }
相关文章推荐
- 排序算法思想——归并排序、堆排序、shell排序
- 【排序算法】堆排序的分析
- 排序算法(五) —— 堆排序
- 排序算法总结-插入排序、希尔排序、堆排序、快速排序
- C++编程练习(13)----“排序算法 之 堆排序“
- 排序算法总结(5)--堆排序
- 排序算法第六篇——堆排序
- 排序算法之(7)——堆排序
- 【排序算法】堆排序
- 排序算法——堆排序
- 常见的排序算法五——堆排序
- 排序算法之堆排序(Heap Sort)
- 排序算法(堆排序)
- 【排序算法】之堆排序
- 【算法之常用排序算法(一)】八大常用内部排序算法(快排、冒泡、希尔、堆排序等)
- Java排序算法:堆排序
- 排序算法之堆排序
- 排序算法总结---树形选择排序,堆排序
- PHP实现排序算法----堆排序(Heap Sort)
- 排序算法——堆排序