排序算法之堆排序

来源:互联网 发布:爱奇艺会员淘宝购买 编辑:程序博客网 时间:2024/06/17 07:19

解题思路:

要实现一个堆排序,需要三步操作:(1)堆调整heapify;(2)构建大顶堆build_max_heap;(3)利用前两部的操作一次次建堆,完成堆排序的操作。

1.堆调整heapify:给定数组中某个节点i,需要将其子树调整为父节点大于子节点。可以很明显的看出一个数组和一棵完全二叉树一一对应,索引值为i的节点,左子节点的索引为2*i+1,右子节点的索引为2*i+2。接下来需要找出三个节点中的最大值和根节点i进行交换,对交换后的影响到的节点继续进行堆调整操作,如此递归下去,直到下标超出数组范围。

2.构建大顶堆build_max_heap:较为简单的一种方法是从数组最后一个元素开始,不断地进行堆调整操作,直到数组第一个元素进行堆调整操作完成后,整个数组就成为一个大顶堆,数组的第一个元素即为最大元素。

3.完成堆排序:从数组的初始长度开始进行建堆操作,将第一个元素和当前数组的最后一个元素交换位置,即将最大元素交换至当前数组的最后。不断地缩小数组的长度,重复上述操作,直到数组长度为0为止。

public class Solution {/**进行堆调整 * @param arr * @param i * @param j * @param k */public void heapify(int[] arr, int i, int length) {//此函数是调整某个堆,让他满足父节点大于子节点,需要找出三个节点的最大值//同时还需要找到数组中被影响的那个节点,因为被影响的节点也需要调整//其实只是需要先找到三个数中的最大值,然后和根节点进行交换即可if (i < length) {//指向三个节点中的最大的那个int max = i;int leftIndex = 2 * i + 1;int rightIndex = 2 * i + 2;//左子元素索引未越界if (leftIndex < length) {if (arr[max] < arr[leftIndex]) {//如果最大值指向元素没有左子索引指向元素大,则max发生变化max = leftIndex;}}if (rightIndex < length) {if (arr[max] < arr[rightIndex]) {max = rightIndex;}}if (max != i){//现在的max肯定指向三个元素中最大的,如果他现在不指向根节点,则将max指向元素//和根节点指向元素交换,只是交换的元素,并没有交换索引,因此max现在指向的元素//受到影响,当它作为根的时候,需要继续进行堆调整的操作swap(arr,max,i);heapify(arr, max, length);}}}//建立一个大顶堆public void build_max_heap(int[] arr, int length) {//从最后一个元素开始,不停地进行堆调整,即可创建一个大顶堆for (int i = length - 1; i >= 0; i--) {heapify(arr, i, length);}}private void swap(int[] arr, int max, int i) {int temp = arr[max];arr[max] = arr[i];arr[i] = temp;}//最后一步进行堆排序public void heap_sort(int[] arr, int length) {if (arr == null || arr.length == 0) {return;}//将第一个元素和当前数组最后一个交换,因为此时最大元素已经到了数组的起始位置while (length > 0) {build_max_heap(arr, length);int temp = arr[0];arr[0]= arr[length - 1];arr[length - 1] = temp;length--;}}}


原创粉丝点击