堆排序笔记

堆排序

堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,他的最坏最好,平均时间复杂度为 O ( n ∗ l o g n ) O(n*logn) O(nlogn),堆排序也是不稳定的。

堆是具有以下以下性质的完全二叉树:

  1. 每个节点的值都大于或等于其左右孩子结点的值,称为大顶堆,这里不要求节点左孩子的值和右孩子的值的大小关系
  2. 每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆

大顶堆用于升序排序,小顶堆用于降序排序

注意:完全二叉树是指从满二叉树按顺序移去部分叶子节点,移去顺序必须先移除右子树才可以移除相应的左子树,也就是说一共k层的完全二叉树,那么从1到k-1层每层节点的个数一定是满的,只有第k层也就是最后一层可以出现不满的情况,并且要按照顺序先有左子树才能有右子树。

堆排序的思想:

  1. 先将一个长度为n的待排序序列构造成一个大顶堆,此时最大的元素就在根结点
  2. 将根结点与末尾元素进行交换,此时最大元素移到末尾
  3. 将剩余的n-1个元素重新构造成一个堆,这样会得到n个元素中第二大的值,反复执行就会将大的值移动到后方,形成一个有序序列

堆排序还运用到了顺序存储二叉树,也就是将二叉树进行编号,根结点为0,根的左子树为1,右子树为2,每层都按照从左到右进行编号,然后按照编号存入一个数组。节点n的左子树在数组中的位置为a[2n+1],右子树为a[2n+2]。

//堆排序算法
public static void heapSort(int arr[]) {
    int temp=0;
    //将无序的序列构建成一个大顶堆
    for(int i=arr.length/2 -1;i>=0;i--){
        adjustHeap(arr,i,arr.length);
    }
    //将堆顶的元素根末尾元素交换,并重新调整树的结构满足大顶堆,然后重复该操作
    for(int j=arr.length-1;j>0;j--){
        //交换
        temp=arr[j];
        arr[j]=arr[0];
        arr[0]=temp;
        adjustHeap(arr,0,j);
    }
}
/*
    arr表示传入的数组
    i表示非叶子节点在数组中的索引,刚开始是代表最后一个非叶子节点的位置
    length表示对多少个元素进行调整

    方法功能是将以i索引代表的非叶子节点的树调整成大顶堆
    也就是相当于把以这个非叶子节点为根,调整成一个大顶堆,此时局部成为一个大顶堆
    比如一开始4 6 8 5 9,最后一个非叶子节点索引i=1,此时意味着调整以6为根结点,左子树为5,右子树为9的一个小树为大顶堆
    调整过后数组为 4 9 8 5 6,调整完成之后将非叶子节点往前移,i=0,调整以4为根结点,左子树为9,右子树为8为大顶堆
    调整过后数组为 9 4 8 5 6,这时发现4的左子树为5,右子树为6,此时发现4小于左右子树不符合规则则继续调用以4为根结点调整为大顶堆
    调整过后数组为 9 6 8 5 4,此时符合大顶堆规定
 */
public static void adjustHeap(int arr[],int i,int length){
    int temp = arr[i];//先取出当前元素的值,也就是小树的根结点
    //开始进行调整
    //k为当前元素的左子树,执行一次循环后,让k为当前元素左子树的左子树,即k=2*k+1,方便判断交换后子树是否仍然满足大顶堆
    for (int k= i*2+1;k<length;k=k*2+1){
        if(k+1<length && arr[k]<arr[k+1]){//如果左子节点小于右子节点
            k=k+1;//让k指向右子节点
        }
        if(arr[k] > temp){//如果子节点大于父节点
            arr[i] = arr[k];//将较大值赋给当前节点
            i=k;//将i指向k,继续循环比较
        }else{//如果当前节点大,说明已经是大顶堆,直接break
            break;
        }
    }
    //for循环结束,说明以i为根结点的树的最大值已经放在了最开始i的这个位置
    //如果发生了交换那么在for循环中,因为我们将i指向了k,也就是子树中大于父节点的那个索引,因此我们要将最开始保存的根结点的值,赋给原本最大值的位置
    //如果没有交换,那么i还是最开始的位置,赋值并不影响值
    arr[i]=temp;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值