大顶堆:顾名思义就是任何一个节点的值大于其左右孩子节点,大顶堆的数据是线性存储,假设父节点的坐标是 n ,可以得到左子节点的下标是 2*n+1 ,右节点的下标是 2*n+2,同理,知道任一节点的下标就可以知道其父节点的下标是(n-1)/2,有了上面这个概念我们就可以写出大顶堆的构建思路:
首先创建一个数组
int[] arr = new int[] {1,2,3,4,5,6,7,8,9,1,3,2,5};
然后将数组作为参数传入转换数组
public static void TraverseNodeNotLeave(int arr[],int size) { //首先从最后一个非叶子节点开始 int parents = (arr.length-2) /2; while(parents>=0) { changeToHeap(arr,size,parents--); } } //将数组转成大顶堆 public static void changeToHeap(int[] arr,int size,int start) { //找到左右两个孩子 int leftChild = start*2+1; int rightChild = start*2+2; if(leftChild>size || rightChild > size) return; //然后找到最大的数字 int max = start; if(leftChild<size && arr[max]<arr[leftChild]) { max = leftChild; } if(rightChild < size && arr[max]<arr[rightChild]) { max = rightChild; } //发生交换 if(max != start) { int temp = arr[max]; arr[max] = arr[start]; arr[start] = temp; changeToHeap(arr,size,max); } }
这样我们就将原来的数组转换成为了大顶堆
堆排序:堆排序的是每一次取出大顶堆的第一个元素,然后将剩下的元素重新向大顶堆转换
代码如下:
public static void HeapSort(int arr[]) { int size = arr.length; while(size>0) { //转换大顶堆 TraverseNodeNotLeave(arr,size); //取出最大元素 int temp = arr[0]; arr[0] = arr[size-1]; arr[--size] = temp; } }
以上就完成到了大顶堆的构建和堆排序工作