算法-堆排序
开始撸常用算法
理解堆
堆(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树的数组对象。
堆总是满足下列性质:
- 堆中某个节点的值总是不大于或不小于其父节点的值;
- 堆总是一棵完全二叉树;
将根节点最大的堆叫做最大堆或大根堆(或者也可以叫做大顶堆)根节点最小的堆叫做最小堆或小根堆(小顶堆)
我们以一个常见数组为例,将转化为大顶堆:
数组5273614,红色为下标,
先直接按照普通树画堆图
3614因为没有子分支了,将其称为叶,那么527即为非叶节点;
大顶堆
将上面的普通堆转化为大顶堆,先取最后一个非叶节点,判断其左右两根是否大于自身,然后进行位置变换
如图
7比1、4都大,所以无需进行变换;然后取倒数第二个非叶节点进行判断,以此一次判断到跟节点5为止
236中,左节点3大于2,所以先进行变换
然后判断右节点,右节点6大于3所以进行变换
最后到达跟节点5
以上即为大顶堆
根叶互换
有了大顶堆后,进行根与最后一个叶子的对换,然后继续进行大顶根转换
7,4对换,此时7即为最后一个叶,将不参与大顶堆转化;为红色
然后将排除在外的堆456231进行大顶堆转化,最后得到
即为排序后的堆;
由此也可以看出,大顶堆对应增序算法,小顶堆对应降序算法;
贴出代码
public static int[] lagerDui(int[] nums) {
int length = nums.length;
if (length == 1)
return nums;
int index = length / 2 - 1;
//大顶堆
for (int i = index; i >=0; i--) {
buildLeftRight(nums, i, length);
}
for (int i = nums.length - 1; i >= 0; i--) {
swapChanger(i, 0, nums);
buildLeftRight(nums, 0, i);
}
return nums;
}
public static void buildLeftRight(int[] nums, int index, int length) {
int left =index*2+1;
int right =index*2+2;
int bigIndex=index;
if(left<length&&nums[left]>=nums[bigIndex]){
bigIndex=left;
}
if(right<length&&nums[right]>=nums[bigIndex]){
bigIndex=right;
}
if(bigIndex!=index){
swapChanger(index,bigIndex,nums);
buildLeftRight(nums,bigIndex,length);
}
}
public static void swapChanger(int index, int laget, int[] nums) {
int temp = nums[laget];
nums[laget] = nums[index];
nums[index] = temp;
}