堆排序

12 篇文章 0 订阅

堆排序是一种常用的高效排序方法,他的时间复杂度是O(lgn),是一种原地排序的算法。


堆是一种数组对象,它被视为一颗完全二叉树,如图 1所示,树的每个节点与数组中存放该节点值的那个元素对应,除最后一层外树的每一层都是满的,最后一层元素从左到右依次填入,。树的根为第1个元素,对于给定的下标i,其父节点parent(i)为i/2,左孩子left(i)为2i,右孩子right(i)为2i+1。


图 1

堆分为大根堆和小根堆;大根堆是指除根节点以外每个节点i都有A[parent(i)]>=A[i],即每个节点的值最多和父节点的值一样大,这样堆中的最大值就在根节点中,且以某个节点为根的子树中,各个节点的值都不大于该子树根节点的值,图 1就是一个大根堆。小根堆的刚好相反,每个节点的值都不小于其父节点。


堆的常用操作有三个


一、调整堆以使其保持大根堆的性质maxHeapify


maxHeapify是对大根堆进行操作的重要子程序,其输入为一个数组A和一个下标i,maxHeapify被调用时假定left(i)和right(i)都满足大根堆的性质,但是A[i]有可能小于其子女而违反了大根堆性质,maxHeapify使A[i]下降,使以A[i]为根的堆成为大根堆。其过程如图 2所示:


图二

二、建立大根堆buildMaxHeap


buildMaxHeap算法是利用maxHeapify算法来进行的。用数组存储一个有n个元素堆时,叶节点的下标是n/2+1、n/2+2……n(这里就不做证明了,有兴趣可以自己证明),建立大根堆就是利用这个性质。叶节点可以看做只有一个元素的堆,只有一个元素也就自然满足大根堆的性质,所以以叶节点为根的堆都是大根堆。但是以其它节点为根的堆就不一定是大根堆,为了使他们满足大根堆的性质,就在节点上调用maxHeapify(叶节点是大根堆就满足了函数输入时的条件)。所以建立大根堆的过程就是在除叶节点以为的节点上调用maxHeapify。

三、利用大根堆排序heapSort

heapSort也是利用maxHeapify算法来进行的。在一个大根堆中,最大元素就是堆的根。堆排序就是利用的这个性质。在一个含有n个元素的数组上调用buildMaxHeap,就能得到最大的元素,然后将最大的元素和数组的尾部,再将最大元素从堆中除去,此时堆的元素为n-1个,但是不满足大根堆的性质,就在根节点上调用maxHeapify使其成为大根堆。不断重复这个过程直到堆中只剩下一个元素,就完成了排序。


下边是三个程序的java实现,数组是从0开始计数的,而上述理论从1开始,在设计数据结构的时候堆的长度本应该是堆的固有属性,为了简便我把size单独提出来了,所以程序看起来有些怪异。

maxHeapify:
/*
 * @param A 待调整的堆
 * 
 * @param node 待调整的节点
 * 
 * @param size 堆的长度
 */
public void maxHeapify(int[] A, int node, int size) {
    int left = (node << 1) + 1;
    int right = left + 1;
    int max = 0;
              
    if (left <= size && A[left] > A[node]) {
        max = left;
    } else {
        max = node;
    }
    if (right <= size && A[right] > A[max]) {
        max = right;
    }
    if (max != node) {
        int temp = A[max];
        A[max] = A[node];
        A[node] = temp;
        maxHeapify(A, max, size);
    }
    System.out.println(Arrays.toString(A));
}

buildMaxHeap:
 * @param A 待建成大根堆的堆
 * @param size 堆的长度
 */
public void buildMaxHeap(int[] A, int size) {
    for (int i = size / 2; i >= 0; i--) {
        maxHeapify(A, i, size);
    }
}

heapSort:
/*
 * @param A 待排序的堆
 * @param size 堆的长队
 */
public void heapSort(int[] A, int size) {
    int temp = 0;
    buildMaxHeap(A, size);
    for (int i = size; i > 0; i--) {
        temp = A[0];
        A[0] = A[size];
        A[size] = temp;
        size -= 1;
        maxHeapify(A, 0, size);
    }
}


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值