堆排序是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并且同时满足堆积的性质:即子节点的键值或者索引总数小于(或者大于)它的父节点。
- 算法描述
- 将初始待排序的序列构建成为大顶堆,此堆为初始的无序区;
- 将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,…Rn-1)和新的有序区(Rn),且满足R[1,2,…n-1]<=R[n];
- 由于交换后新的堆顶可能违反堆的性质,因此需要对当前无序区(R1,R2,…Rn-1)调整为新堆,然后再次将R[1]
- 代码实现:完全二叉树有个特性:左边子节点位置 = 当前父节点的两倍 + 1,右边子节点位置 = 当前父节点的两倍 + 2。
- 代码实现:
public class DuiPaiXu2 {
private static void daDingDui(int[] arrays, int start, int end) {
// 父节点
int curr = start;
// 左右节点
int left = curr * 2 + 1;
// int right = curr * 2 + 2;
// 父节点值
int temp = arrays[curr];
for (; left < end; curr = left, left = curr * 2 + 1) {// 将其左子节点变为父节点,将根据其变换后的父节点获取到左子节点
if (left < end && arrays[left] < arrays[left + 1]) {// 判断左右子节点谁最大
left++;// 变为右子节点为父节点,
}
if (arrays[left] > temp) {// 判断左右子节点的最大值与当前父节点的值谁大
arrays[curr] = arrays[left];
arrays[left] = temp;
}
}
}
private static void jiaoHuan(int[] arrays, int index1, int index2) {
int temp = arrays[index1];
arrays[index1] = arrays[index2];
arrays[index2] = temp;
}
private static void duiPaiXu(int[] arrays) {
int length = arrays.length;
int left;
// 从(n/2-1)--->0遍历,逐渐将待排序序列生成一个大顶堆
for (left = length / 2 - 1; left > 0; left--) {
daDingDui(arrays, left, length - 1);
}
// 从最后一个元素开始对序列进行调整,不断的缩小调整范围,直到缩小到只含有第一个元素
for (left = length - 1; left > 0; left--) {
// 交换第一个和左子节点元素后,左子叶节点就是序列中最大的元素。
jiaoHuan(arrays, 0, left);
// 调整剩下的堆序列,保证右子节点为剩下的堆序列中的最大值
daDingDui(arrays, 0, left - 1);
}
}
public static void main(String[] args) {
int arrays[] = { 20, 30, 90, 40, 70, 110, 60, 10, 100, 50, 80 };
System.out.println(Arrays.toString(arrays));
duiPaiXu(arrays);
System.out.println(Arrays.toString(arrays));
}
}