一、堆排序原理(从小到大)
1.堆排序特点
1)堆排序是利用堆这种数据结构而设立的一种排序算法
2)完全二叉树(从上到下,从左到右,每一层的节点都是满的,最下边一层所有的节点都是连续集中在最左边)。
3)二叉树每个结点的值都大于或者等于其左右孩子节点的值称之为大顶堆。
二叉树每个结点的值都小于或者等于其左右孩子节点的值称之为小顶堆。
将数组转换成堆后可以看出如下规律
N[i]的左节点:N[2i+1]
N[i]的右节点:N[2i+2]
N[i]的父节点:N[(i-1)/2)]
2.基本思想
1)将带排序的序列构造成一个大顶堆,根据大顶堆的性质,当前堆的根节点(堆顶)就是序列中最大的元素
2)将堆顶元素和最后一个元素交换,然后将剩下的节点重新构造成一个大顶堆
3)重复步骤2),从第一次构建大顶堆开始,每一次构建都能得到一个序列的最大值,让后把它放到堆尾部,最后得到一个有序序列
二、代码实现
public static void main(String[] args) {
int[] arr = new int[] {1,0,2,4,3,5,7,6};
//创建堆
for (int i = (arr.length-1)/2;i >= 0;i--){
//从第一个非叶子节点从上至下,从左至右调整结构
adjustHeap(arr,i, arr.length);
}
//调整堆结构并交换堆顶元素与末尾元素
for (int i = arr.length - 1;i > 0;i--){
//将堆顶元素与末尾元素进行交换
int temp = arr[i];
arr[i] = arr[0];
arr[0] = temp;
//重新对堆进行调整
adjustHeap(arr,0,i);
}
System.out.println(Arrays.toString(arr));
}
/**
* arr 待排序列
* parent 父节点
* length 待排序列尾元素索引
*/
public static void adjustHeap(int[] arr,int parent,int length){
//将temp作为父节点
int temp = arr[parent];
//左孩子
int lc = 2*parent + 1;
while (lc < length){
//右孩子
int rc = lc +1;
//如果右右孩子节点,并且右孩子节点的值大于左孩子节点,则选取右孩子节点
if (rc < length && arr[lc] < arr[rc]){
lc++;
}
//如果父节点的值已经大于孩子节点的值,则直接结束
if (temp >= arr[lc]){
break;
}
//把孩子的值赋给父节点
arr[parent] = arr[lc];
//选取孩子节点的左孩子节点,继续向下筛选
parent = lc;
lc = 2*lc + 1;
}
arr[parent] = temp;
}