排序——堆排序

1.  堆

是一棵顺序存储完全二叉树

其中每个结点的关键字都不大于其孩子结点的关键字,这样的堆称为小根堆

其中每个结点的关键字都不小于其孩子结点的关键字,这样的堆称为大根堆

对于 n 个元素的序列 {R0, R1, ... , Rn},当且仅当满足下列关系之一时,称之为堆:

(1) Ri <= R2i+1  Ri <= R2i+2 (小根堆)

(2) Ri >= R2i+1  Ri >= R2i+2 (大根堆)

 

                                

2.  堆排序

首先,按堆的定义将数组 R[0..n] 调整为堆(这个过程称为创建初始堆),交换R[0]和R[n];

然后,将R[0..n-1]调整为堆,交换R[0]和R[n-1];

如此反复,直到交换了R[0]和R[1]为止。

堆排序中的两个关键问题:

1. 根据初始数组建立初始堆

2. 输出堆顶后,如何“筛选”。

“筛选”:对一棵左、右子树均为堆的完全二叉树,“调整” 根节点使整个二叉树成为堆。

 

筛选过程:(以小顶堆为例)

 

 首先将该完全二叉树的根结点中的记录移出,该记录称为待 “调整” 的记录。此时根结点相当于空结点,从空结点的左、右孩子中选出一个关键字较小的记录,如果该记录的关键字小于待调整记录的关键字,则将该记录上移至空结点中。

此时,原来那个关键字较小的子结点相当于空结点,从空结点的左、右孩子中选出一个关键字较小的记录,如果该记录的关键字仍然小于待调整记录的关键字,则将该记录上移至空结点中。重复上述移动过程,直到空结点左右孩子的关键字均小于待调整记录的关键字。此时,将待调整的记录放人空结点即可。

 

建立初始堆:

首先将一个无序列表建立成一棵完全二叉树。然后每个叶子节点可以视为单个元素构成的堆,在利用“筛选”法,自底向上逐层把所有子树调整为堆,直到将整棵完全二叉树调整为堆。

package com.zth.sort;

import java.util.Arrays;

public class HeapSort {
    public static void main(String[] args){
        Integer [] array1 = {3,2,5,8,4,7,6,9};
        heapSort(array1);

        Double[] array2 = {3.3,2.3,5.3,8.3,4.3,7.3,6.3,9.3};
        heapSort(array2);

        System.out.println(Arrays.toString(array1));
        System.out.println(Arrays.toString(array2));
    }

    /**
     * used in deleteMax and buildHeap
     * @int parent the position from which to percolate down
     * @int length the logical size fo the binary heap
     */
    private static <AnyType extends Comparable<? super AnyType>>
    void heapAdjust(AnyType[] array,int parent,int length){

        int child = 2*parent+1;     // 获取左孩子
        AnyType temp = array[parent];       // 保存当前父节点

        while (child < length){
            // 如果有右孩子结点,并且右孩子结点的值大于左孩子结点,则选取右孩子结点
            if (child + 1 <length && array[child].compareTo(array[child + 1]) <0){
                child++;
            }
            // 如果孩子结点的值大于父结点的值,将孩子节点的值赋给父节点
            if (temp.compareTo(array[child]) <0){
                array[parent] = array[child];
            }else { // 如果父结点的值已经大于孩子结点的值,则直接结束
                break;
            }

            // 选取孩子结点的左孩子结点,继续向下筛选
            parent = child;
            child = 2 * child + 1;
        }
        array[parent] = temp;
    }

    public static <AnyType extends Comparable<? super AnyType>>
    void heapSort(AnyType[] array){
        // 建立初始堆
        for (int i = array.length/2 -1; i >=0; i--) {
            heapAdjust(array,i,array.length);
        }

        // 进行n-1次循环,完成排序
        for (int i = array.length-1;i>0;i--){
            // 最后一个元素和第一元素进行交换
            AnyType temp = array[i];
            array[i] = array[0];
            array[0]= temp;

            heapAdjust(array,0,i);
        }
    }
}
时间复杂度空间复杂度稳定性
平均情况最坏情况最好情况
o(n log n)o(n log n)o(n log n)o(1)不稳定

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值