堆排序
一、堆排序的介绍
- 堆排序是利用堆这种数据结构而进行设计的一种排序算法,堆排序是一种选择排序。它最好、最坏、平均的时间复杂度均为O(nlogn),并且是不稳定的。
- 堆是具有如下性质的完全二叉树:每个节点的值都大于或等于其左右孩子节点的值,称为大顶堆;每个节点的值都小于或等于其左右孩子节点的值,称为小顶堆。注意:节点的左孩子和右孩子的值的大小关系没有要求。
- 大顶堆$arr[i] >= arr[2*i+1]并且arr[i] >= arr[2*i+2]$;小顶堆$arr[i] <= arr[2*i+1]并且arr[i] <= arr[2*i+2]$
- 一般要求结果升序的序列采用大顶堆;而降序的序列采用小顶堆。
二、堆排序的思想
- 将待排序的序列构成一个大顶堆;
- 此时,整个序列的最大值就是堆顶的根节点;
- 将其与末尾元素进行交换,此时末尾就是最大值;
- 然后将剩余n-1个元素重新构成一个堆,同样的方法得到这n个元素的次小值。如此反复执行,便能得到一个有序序列。
三、代码
import java.util.Arrays; public class HeapSort { public static void main(String[] args) { int[] arr = {6,5,4,3,2,1}; heapSort(arr); } public static void heapSort(int[] arr) { System.out.println("堆排序"); //build heap,共有(n/2-1)非叶子节点,从下往上,从左往右建立大根堆 for (int i = arr.length/2 -1; i >= 0; i--) { adjustHeap(arr, i, arr.length); } //将堆顶元素与莫为元素交换,最大值“沉”到数组末端 int cnt = 0; for (int j = arr.length - 1; j > 0; j--) { swap(arr, j, 0); adjustHeap(arr, 0, j); } System.out.println("数组 = " + Arrays.toString(arr)); } /**升序排列,构建大根堆 * @param arr: 待调整的数组 * @param i: 非叶子节点在数组中的索引 * @param length: 表示待调整的元素的数量 */ public static void adjustHeap(int[] arr, int i, int length) { int temp = arr[i]; //k=2*i+1是第i个节点的左子节点;k+1是第i个节点的右子节点 for (int k = 2 * i + 1; k < length; k = k * 2 +1) { if (k+1 < length && arr[k] < arr[k+1]) { k += 1; } if (arr[k] > temp) { //如果子节点k大于父节点i arr[i] = arr[k]; i = k; } else { //如果当前节点i已经最大,则不用交换(注意,由于是从左到右、从下到上调整大根堆) break; } } //当for循环结束,我们将以i为父节点的最大值,放在了最顶端(局部大顶堆) arr[i] = temp; //将temp放到最终的位置 } //交换函数 public static void swap(int[] arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } }
堆排序
数组 = [1, 2, 3, 4, 5, 6]
四、关于堆排序的几点说明
1、堆排序是基于完全二叉树实现的,在将一个数组调整成一个(小根堆、大根堆)堆的时候,关键之一的是确定最后一个非叶子节点的序号。而完全二叉树的最后一个非叶子节点的序号是n/2-1,然后从左到右,从下至上,对二叉树进行调整。
2、排序的稳定性指的是,对于两个关键字相等的记录,他们在序列中的相对位置,在排序前后没有发生改变。排序算法是稳定的,那么第一个排序结果可以为另一个排序继续使用,即稳定的排序算法可以用于两个关键字的排序。比如,现在要根据英语成绩排一下大家的成绩,然后在根据数学成绩排一下大家的成绩,如果用的是稳定排序的话,就可以保证数学成绩相同的人里英语分高的人排在更前面。
3、堆排序是不稳定的:考虑序列{9,5A,7,5B},按照堆排序的算法走一遍(算法导论中用的是最大堆,这个序列也是用最大堆来设计的),输出序列为{5B,5A,7,9},而且与等号无关,因此堆排序是不稳定的。他之所以不稳定,因为在堆调整的过程中,在堆顶与堆尾交换的时候,两个相等的记录在序列中的相对位置可能发生变化,这就影响了排序算法的稳定性。
作者:Ryanjie
出处:http://www.cnblogs.com/ryanjan/
本文版权归作者和博客园所有,欢迎转载。转载请在留言板处留言给我,且在文章标明原文链接,谢谢!
如果您觉得本篇博文对您有所收获,觉得我还算用心,请点击右下角的 [推荐],谢谢!