最大堆是父节点元素大于该父节点的左右儿子元素,具有这样性质的二叉树。
将序列构建成一个最大堆,则根节点(第一个元素序列)即为最大元素,最大元素与最后一个序列元素交换,则最大元素已放到最后,则可将序列长度减一,前n-1个元素再进行构建最大堆,交换元素;如此反复,直到剩余最后一个元素,即已排好顺序。
构建最大堆时,设序列为nums[],则所构成二叉树的第一个叶节点序号是n.length()/2;节点i的左儿子节点是2*i + 1,右儿子节点是2*i+2。所有在构造最大堆时,要检查父节点元素是否大于其左右儿子,若大于则不需要比较;若不大于,则要进行交换:将父节点元素与其左右儿子节点中最大的那一个交换位置。交换后,还要继续检查交换后的儿子节点是否大于儿子节点的儿子节点......以此做个比较,直到遍历到根节点,检查根节点与其儿子节点的大小,需不需要交换;将根节点及其子树遍历完后,则根节点就是这颗二叉树中最大的节点元素了,就构成了最大堆。
public static void goJianDun(int[] nums, int end) { //构建最大堆
for (int i = end /2 -1; i >= 0; i--) { //遍历所有非叶节点
int begin = i, high = end / 2;
while (begin < high) { //当begin等于或大于叶子节点下标时,停止循环
int lef = begin * 2 + 1; //找到节点begin的左儿子节点
int ri = lef + 1; //右儿子节点
if (ri < end && nums[lef] < nums[ri]) { //将左右儿子节点中的最大值给左儿子(若右儿子节点存在)
lef = ri;
}
if (nums[begin] > nums[lef]) { //父节点大于儿子节点,则不用再比较
break;
}
int temp = nums[begin]; //若父节点小于儿子节点,则交换
nums[begin] = nums[lef];
nums[lef] = temp;
begin = lef; //往下继续进行检查
}
}
}
public static void dun(int[] nums) {
for (int i = nums.length - 1; i >= 0; i--) {
goJianDun(nums, i + 1); //构建最大堆,将堆的根节点与最后一个元素互换,长度减一,再进行构建最大堆
int temp = nums[0];
nums[0] = nums[i];
nums[i] = temp;
}
}
本文介绍了最大堆的性质及如何构建最大堆。通过Java代码展示了如何进行堆排序,包括构建最大堆的过程和堆排序的完整步骤。堆排序算法通过交换根节点与最后一个元素并递归调整堆来实现升序排列。
31万+

被折叠的 条评论
为什么被折叠?



