在实现堆排序之前 我们先来介绍一下什么是最大堆与最小堆
最大堆 与最小堆 都是一个二叉树 也称为二叉堆
二叉堆的定义
每个节点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)
最大堆 : 当父节点的键值总是大于或等于每一个子节点 时被称为最大堆
最小堆 : 当父节点的键值总是小于或等于每一个子节点 时被称为最小堆
最小堆 :
1
2 3
17 19 36 7
25 100
最大堆:
100
98 97
67 63
45 23
一般的堆的存储都用数组来完成 ,所以一个节点的父节点就为 (节点下标-1)/2 他的左右子节点分别为2*i+1 和 2*i+2
例子 :
10
15 56
23 75 array[]={10.15,56.23.75};
15的父节点就为 (1-1)/2 =0 左右子节点为 array[2*1+1]=23 array[2*1+2]=75
我们已经理解了什么是最大堆 与最小堆了,现在我们来编写代码
/*
* *功能 快速排序
* *作者 blue
* *data 4.5
*
*/
public class MaxHeapsortDemo {
private static int[] sort = new int[]{1,0,10,10,3,5,6,4,9,8,12,17,34,11};
public static void main(String[] args) {
builddMaxHeapify(sort);
heapSort(sort);
Prtint(sort);
}
private static void Prtint(int[] sort2) {
for (int i = 0; i < sort2.length; i++) {
System.out.print(" "+sort2[i]);
}
}
private static void builddMaxHeapify(int[] data) {
int startIndex = (data.length-2)>>1;//得到数组最后一位的父节点
for (int i = startIndex; i>=0; i--) {
maxHeap(data, data.length, i);
}
}
private static void maxHeap(int[] data ,int heapSize,int index) {
int leftChildIndex = (index<<1)+1;//得到该节点的左子节点
int rightChildIndex = (index<<1)+2;//得到该节点的右子节点
int largest =index;
/*
* 找到当前节点与左右节点的的最大值
*/
if (leftChildIndex<heapSize&&data[index]<data[leftChildIndex]) {
largest = leftChildIndex;
}
if (rightChildIndex<heapSize&&data[largest]<data[rightChildIndex]) {
largest = rightChildIndex;
}
/*
* 如果当前的父节点不是最大点,就交换节点与最大节点的值,
*/
if (largest!=index) {
int temp = data[index];
data[index] =data[largest];
data[largest] =temp;
maxHeap(data, heapSize, largest);
}
}
/*
* *从第一父节点开始交换,把第一父节点交换给最后一个节点,然后再调用MaxHeap 从新排最大堆
*/
private static void heapSort(int[] data) {
for (int i = data.length-1; i >=0; i--) {
int temp = data[0];
data[0]=data[i];
data[i]=temp;
maxHeap(data, i, 0);
}
}
}
我们首先 将一个乱序的数组 排成了一个最大堆 ,
首先 找到一个父节点 ,然后找到左右子节点,判断三个节点的键值的最大,如果父节点不是最大就要与最大的子节点交换,交换 之后的子节点已经不满足最大堆 ,所以这个时候我们就需要递归来继续重排最大堆
意思就是 刚开始是 56|67 23 发现 56不是最大节点 然后把 67 和 56 换掉 这个时候 原先67的左右子节点就不满足56 了 所以就要重新构成最大堆
在构成最大堆后 ,我们就开始排序了
首先这个最大堆得最大父节点 与最后一位交换,交换之后 就又不满足最大堆的特性,所以这时候我们又要重新调用maxHeap 函数 来重新构成最大堆了
这个时候我们发现,最大父节点已经是上一个父节点的左子节点
如图所示 :
END!