public class HeapSort { public static void main(String[] args) { int[] arr = {4, 1, 3, 2, 16, 9, 10, 14, 8, 7}; heapSort(arr); printHeap(arr); } //堆排序函数 public static void heapSort(int[] arr) { int len = arr.length; buildHeap(arr, len); //首次建堆,建成一个完整的大顶堆(根节点为最大值) for (int i = 0; i < len; i++) { swap(arr, 0, len - 1 - i); //将堆顶元素(通过调整堆获得的最大值)和最后一个交换(剩余未排好序部分的最后一个) adjustHeap(arr, len - 1 - i, 0); //之后每次从堆顶开始调整,最大的值将上升到根节点 } } //第一次建堆的过程 public static void buildHeap(int[] arr, int maxlen) { int len = maxlen / 2 - 1; //完全二叉树的最后一个非叶子结点 for (int i = len; i >= 0; i--) { adjustHeap(arr, maxlen, i); } } /** * maxlen 此次调整堆的最大元素个数(因为堆排序过程中,后面已经调整好的就不需要调整了) * i 表示此次调整堆的父节点 * */ public static void adjustHeap(int[] arr, int maxlen, int i) { int left = 2 * i + 1; //获得该父节点的左孩子 int right = 2 * i + 2; //获得该父节点的右孩子 int maxpos = i; while (left < maxlen) { if (right < maxlen && arr[maxpos] < arr[right]) { maxpos = right; } if (arr[maxpos] < arr[left]) { maxpos = left; } if (maxpos != i) { swap(arr, i, maxpos); i = maxpos; //继续向下调整,因为此次调整可能会破坏原来下面的堆 left = 2 * i + 1; right = 2 * i + 2; } else { break; } } } //交换堆中任意两个数 public static void swap(int[] arr, int from, int to) { int temp = arr[from]; arr[from] = arr[to]; arr[to] = temp; } //打印堆中的数据 public static void printHeap(int[] arr) { int len = arr.length; for (int i = 0; i < len; i++) { System.out.print(arr[i] + " "); } System.out.println(); } }
package Sort; import java.util.Arrays; /** * Created by ZihanCong on 16/9/9. */ public class HeapSort { public static void main(String[] args) { HeapSort hs = new HeapSort(); hs.heapSort(new int[]{1,3,5,4,7,2,9}); } public void heapSort(int[] data) { int arrayLength = data.length; for (int i = 0; i < arrayLength - 1; i++) { //构建最大堆 buildMaxHeap(data, arrayLength - i - 1); swap(data, 0, arrayLength - i - 1); System.out.println(Arrays.toString(data)); } } public void buildMaxHeap(int[] data, int lastIndex) { //从lastIndexc处的父节点开始 for (int i = (lastIndex - 1) / 2; i >=0 ; i--) { int k = i; while (k * 2 + 1 <= lastIndex) { int bigger = k * 2 + 1; //如果右节点较大,bigger引用总是指向较大的对象 if (bigger < lastIndex && data[bigger] < data[bigger + 1]) bigger++; if(data[k] < data[bigger]){ swap(data,k,bigger); //开始遍历下层的k k = bigger; } else break; } } } public void swap(int[] data, int begin, int end) { int temp = data[begin]; data[begin] = data[end]; data[end] = temp; } }
堆排序原理
堆排序就是把最大堆堆顶的最大数取出,将剩余的堆继续调整为最大堆,再次将堆顶的最大数取出,这个过程持续到剩余数只有一个时结束。在堆中定义以下几种操作: