【排序算法】 堆排序 heap sort(选择类排序)
2017-06-22 22:17
274 查看
【排序算法】 堆排序 heap sort(选择类排序)
堆排序的过程
创建最大堆:
从最后一个非叶子结点到根结点(从下向上,这点非常关键)调整每一个子堆,使子堆有序化。最开始的子堆的根结点是最后一个非叶子结点,它有一个或者两个孩子,它与较大者交换位置即可实现子堆有序化。
底部的子堆有序化,是其上面的堆进行调整的前提条件。
也即是,如果子堆是无序的,那么包含它的一个更大的堆就无法进行调整操作,
所以需要从最后一个非叶子结点到根结点(从下向上,这点非常关键)调整每一个子堆,使子堆有序化。。
调整最大堆(有序化堆):
(只有一个或者零个父结点相对孩子是无序)如果当前结点有孩子结点,
如果当前结点的孩子结点的较大者比当前结点大,则交换两者位置,
否则调整结束,退出,
继续比较当前结点与其新的孩子结点
堆排序的步骤:
初始化最大堆(使堆有序化,可能所有的子堆都是无序的,需要调整所有的子堆)将最大堆的第一个元素和最后一个元素交换位置;
使堆的长度减 1;
最大堆调整(使堆有序化,只有第一个元素相对于它的孩子是无序的,不断调整此元素和其后代的相对位置即可);
重复以上三步,直到堆的长度为 1。
索引关系
使用数组存储完全二叉树(堆),则结点下标关系是:父结点 i 的左子结点是 2 * i + 1;
父结点 i 的右子结点是 2 * i + 2;
子结点 i 的父结点是 floor((i-1)/2)
后一个非叶子结点是 floor(N/2)-1
时间复杂度
expense:时间复杂度 O(N*log(N))
应用场景
堆排序实现
package algorithm.algorithm4.ch02_sort; import org.junit.Test; import java.util.Arrays; import java.util.Random; /** * algorithm: heap sort,堆排序 */ public class Heap { public static void sort (Comparable[] arr){ if (arr == null || arr.length < 2) return; // 1. 创建堆 // 从下向上使每一个有孩子的结点都成为一个有序堆(宏观角度) // 多次堆化,从下到上不断新加元素,因为单次堆化要求最多只有根结点相对于孩子结点是无序的,所以需要从后往前添加元素 // 具体的堆化操作是从上到下完成的,而且一次堆化要求最多只有根结点相对于孩子结点是无序的,此外所有的子堆都是有序的 for (int i = arr.length/2-1; i >= 0; i --) // 完全二叉树中最后一个有孩子的结点是 N/2-1 maxHeapify(arr, i, arr.length); // 2. 堆排序 for (int j = arr.length - 1; j > 0; j --) { swap(arr, 0, j); // 堆首元素不断和堆尾元素交换位置,堆的大小减 1 maxHeapify(arr, 0, j); // 将去掉一个元素的新堆调整为最大堆(有序堆) } } /** * 从上到下有序化堆,使小于孩子的父结点下沉(sink) * @param arr 二叉堆 * @param index 待调整的子堆的根结点 * @param newSize 除了排序后的元素外,堆中剩余元素的个数 */ // 具体的堆化操作是从上到下完成的,而且一次堆化要求最多只有根结点相对于孩子结点是无序的,此外所有的子堆都是有序的 private static void maxHeapify (Comparable[] arr, int index, int newSize){ while (2 * index + 1 < newSize){ // 当前结点至少有左孩子 int childIdx = 2 * index + 1; // index 左孩子的下标 // 存在右孩子,且右孩子比左孩子更大,则记录右孩子的下标 if (childIdx + 1 < newSize && arr[childIdx].compareTo(arr[childIdx+1]) < 0) childIdx ++; if (arr[childIdx].compareTo(arr[index]) <= 0) break; // 两个孩子均小于等于当前元素,则退出循环 swap(arr, index, childIdx); index = childIdx; // 当前不断跟新的孩子比较,跟其中一个较大的孩子交换位置 } } private static void swap(Comparable[] arr, int i, int j){ Comparable tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } @Test public void test(){ Random random = new Random(); int N = 20; Integer[] arr = new Integer ; for (int i = 0; i < N; i ++) arr[i] = random.nextInt(100); System.out.println(Arrays.toString(arr)); Heap.sort(arr); System.out.println(Arrays.toString(arr)); } }
相关文章推荐
- 排序算法之堆排序(Heapsort)解析
- 常见的五类排序算法图解和实现(选择类:简单选择排序,锦标赛排序,树形选择排序,堆排序)
- 排序算法总结之堆排序 Heap Sort
- 选择排序之堆排序(HeapSort)
- 排序1+4:归并排序(MergeSort)和堆排序(HeapSort)
- 排序——堆排序(HeapSort)
- 堆积排序-堆排序-heap sort
- PHP实现排序算法----堆排序(Heap Sort)
- 一天一排序之“堆排序(heapsort)”
- 排序算法 之 堆排序 HeapSort
- 排序算法 之 堆排序(heapsort)
- PHP实现排序堆排序(Heap Sort)算法
- PHP排序算法之堆排序(Heap Sort)实例详解
- 排序算法之堆排序(Heap Sort)
- 排序算法之堆排序 Heap Sort
- 八大排序算法之四选择排序—堆排序(Heap Sort)
- 浅析各类排序算法(七) 选择类排序之堆排序
- 常见的五类排序算法图解和实现(选择类:简单选择排序,锦标赛排序,树形选择排序,堆排序)
- 排序1+4:归并排序(MergeSort)和堆排序(HeapSort)
- 排序算法系列:堆排序(heapsort)(C语言)