/* 堆是一棵完全二叉树,底层可以用数组实现,若根节点的index是0,那么若一个节点的index是i,它的父节点的index就是(i-1)/2, 左右子节点的index是i*2+1和i*2+2。 若是升序排列,就存储为最大堆,即任意节点都要比它的子节点要大。降序则存储为最小堆。 步骤: 1.构建最大堆,构建最大堆和每次调整最大堆都是把数组中最大元素调整到树顶 2.顶元素和最后元素交换,相当于把顶元素排除 3.调用adjust函数调整堆以还原为最大堆(此时不考虑已经排除的元素),重复步骤2,3直到结束 构建最大堆: 从最后一个非叶子节点(下标从0开始的情况下index是(n-2)/2)开始调用adjust函数,从下往上调整 */ public class Main { public static void main(String[] args) { int[] data = new int[]{2,8,4,3,1,6,9,7,10,-2,65}; Main main = new Main(); main.heapSort(data); for (int i = 0; i < data.length; i++) { System.out.println(data[i]); } } //堆排序主函数 public void heapSort(int[] data) { if (data == null || data.length <= 1) return; //记录当前heap的size int heapSize = data.length; //1.构建最大堆函数 //从最后一个非叶子节点开始 int index = (heapSize-2)/2; for (int i = index; i >=0 ; i--) { adjust(i,heapSize,data); } //2.交换最后元素和顶元素(相当于取出顶元素(最大)到最后) while (heapSize > 1) { change(0,heapSize-1,data); heapSize--; //3.调整堆 adjust(0,heapSize,data); } } //调整最大堆函数 public void adjust(int index,int heapSize,int[] data){ //左右子节点的index int left = index*2+1; int right = index*2+2; //记录此次比较的三个节点中最大的节点的index int biggest = index; //判断左子节点是否存在且是否比当前最大值大 if (left < heapSize && data[left] > data[biggest]) { biggest = left; } //判断右子节点是否存在且是否比当前最大值大,注意这里都是和biggest,不是index.因为是找出最大值,出错过一次 if (right < heapSize && data[right] > data[biggest]) { biggest = right; } //判断最大值的index是否还是当前节点index,不是的话:交换,递归,是的话(本来就是最大或者这是个叶节点)就会返回 if (biggest != index) { change(index,biggest,data); adjust(biggest,heapSize,data); } } //交换函数 public void change(int index1,int index2,int[] data) { int temp = data[index1]; data[index1] = data[index2]; data[index2] = temp; } }