public static void main(String[] args) {
int[] arr={7,6,4,3,5,2,10,9,8};
System.out.println(Arrays.toString(arr));
heapSort(arr);
System.out.println(Arrays.toString(arr));
}
/**
* 堆树
* 一颗父节点都大于等于子节点或者小于等于子节点的完全二叉树
* 堆排序
* 从最后一个非叶子节点开始堆化,就是从最后一个非叶子节点开始把当前节点作为父节点的子树
* 向直属子节点交换比他大的数,当进行交换后,交换的子节点的子树会混乱,所以再对交换子节点的子树进行堆化,
* 以此类推
* 当完成堆化的时候,将根节点,也就是当前堆树最大的节点和尾结点交换,
* 对除去最后一个元素的堆树进行再次堆化,以此类推
* @param arr
*/
public static void heapSort(int[] arr){
//首先,对数组先进行初始堆化,我们从最后一个非叶子节点开始堆化
for(int i=data.length/2-1;i>=0;i--){
createHeap(data,i,data.length);
}
//此时已经构造出一个堆树,堆顶的元素就是整个数组中最大的元素
//我们通过将堆顶元素和尾节点交换,实现最大的元素放数组的最后
//再对除去最后元素的数组针对堆顶的节点进行堆化,再求出最大的再放当前堆树的后面,
//以此类推,每次都将当前堆树最大的值往后放,最后就可以得到从小到大的数组了
for(int i=data.length-1;i>0;i--){
int temp = data[i];
data[i] = data[0];
data[0] = temp;
createHeap(data,0,i);
}
}
/**
* 堆化,就是将当前节点和左右节点对比,拿出最大一个,如果是,直接跳出并赋值
* 如果不是,就将最大值赋予当前节点,并拿到最大值对应的节点的左右节点继续和最开始的节点的值进行比对
* 直到最开始节点的那个值比左右节点都大,那么停止比对,并将该值赋予当前循环到的节点
* 当然我们还要判断边界,如果到限制的位置了,也跳出并将值赋予最后的这个节点
* @param data
* @param i
* @param length
*/
private static void createHeap(int[] data, int i, int length) {
int temp = data[i];
int parent = i;
int child = 2*i +1;
while(child<length){
//拿到左右子节点中最大的那个节点的下标
if(child+1<length && data[child+1]>data[child]){
child++;
}
//和一开始要进行堆化的节点的值进行对比,如果该值大于左右节点的最大值了,那么 跳出循环,将值赋予当前节点
if(temp > data[child]){
break;
}
//将左右节点的最大值赋予当前节点
data[parent] = data[child];
//让父节点指针指向最大的那个子节点
parent = child;
//拿到父节点的子节点
child = 2*parent+1;
}
//跳出循环,证明已经拿到了一开始要堆化的节点的值已经到了大于左右节点的节点的位置
data[parent] = temp;
}
写一下堆排序
最新推荐文章于 2023-09-21 13:21:58 发布