一、堆排序的介绍
二、堆排序的思想
三、代码
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},而且与等号无关,因此堆排序是不稳定的。他之所以不稳定,因为在堆调整的过程中,在堆顶与堆尾交换的时候,两个相等的记录在序列中的相对位置可能发生变化,这就影响了排序算法的稳定性。
原文:https://www.cnblogs.com/xiazhenbin/p/14329583.html