堆排序前序-堆的创建

堆排序前序-堆的创建

什么是堆:

​ 堆其实就是一个特殊的完全二叉树(什么是二叉树…完全是啥…百度一下你就知道),那么他特殊在哪里呢。

在这里插入图片描述

看到上图这玩意没,这就是一个堆,准确的说是个小顶堆,简单点说小顶堆就是个父节点一定小于子节点的这么一颗完全二叉树。那么大顶堆呢?那当然就是父节点一定大于子节点的这么一颗完全二叉树。

​ 所以堆就是一个节点值总是不大于或者不小于父节点值的一颗完全二叉树。

​ 一般我们采用一个数组来描述一个堆,如上图我们数据存储即为{1,2,3,7,6,5,4},那么父节点的子节点即为 left=parent *2 +1 ,right=left+1 注意,左右节点不一定存在的可能性,算出来的值如果大于数组长度那么就不存在此节点。这里是以数组索引位为计算值 比如:1这个(0索引位)父节点他的两个子节点为 第1个和第2个(自己算下嘛)。

小顶堆的构建:

​ 初始数据:3,6,5,2,1,4,7

第一步:我们首先将初始数据直接放入一个完全二叉树中(其实就是构建一个一维数组)

在这里插入图片描述

第二步:采用自下而上的思想,从非叶节点的最后一个开始,遍历这个非叶节点的子节点是不是符合小顶堆特性。

为什么是从非叶节点开始,因为叶节点只有它一个,无论是小顶堆还是大顶堆它都满足,所以不用处理。

那么最后一个非叶节点是哪个呢,按照完全二叉树的特性即为(length-1)/2个为最后一个非叶节点,如上图所示即为5结点,然后对比其子节点判断左右节点那个最小,最小节点与父节点进行比较,如果子节点小于父节点那么进行一次交换。

在这里插入图片描述

如上图所示,第6节点4这个值与父节点进行了一次交换。

第三步:产生交换后,需要以交换的子节点为调整节点,进行一次是否为小顶堆条件判断,即在进行一次以交换节点为父节点判断其子节点是否满足小顶堆的逻辑处理。

然后当所有非叶节点循环判断完成后,此完全二叉树即为小顶堆。

大顶堆的构建

基本原理在小顶堆中已经讲述完毕,对应大顶堆仅仅只是判断条件变成了父节点要比子节点大,这里直接用代码实现。

``

public static void createHeap(int[] heap){

    int length=heap.length-1;
    for(int i=length/2;i>=0;i--){
        siftUp(i, heap,length);
    }
}

  //构建大顶堆
    public static void siftUp(int i,int[] data,int length){
    	int length=data.length-1;
        boolean isSwap=true;
        //i必须小于数组长度,并且一轮比较没有发生交换则证明已经完成一次构建
        while (i<=length && isSwap) {
            int nowIndex = i;
            //左孩子为当前节点*2+1 (但是并不一定存在)
            int leftIndex = i * 2 + 1;
            //右孩子为左节点+1 (但是并不一定存在)
            int rghitIndex = leftIndex + 1;
            //默认比较的节点为左孩子
            int selectChildIndex = leftIndex;

            //如果左孩子节点大于了数组长度那么就不用在继续了
            if(leftIndex>length) break;
            //左右孩子比较,确定最小的那个值与父节点比较
            if (rghitIndex <= length && data[leftIndex] < data[rghitIndex]) {
                selectChildIndex = rghitIndex;
            }

            //如果选择的子节点大于父节点那么就交换,然后以交换的节点处,继续往下调整交换后的堆
            if (data[nowIndex] < data[selectChildIndex]) {
                int temp = data[nowIndex];
                data[nowIndex] = data[selectChildIndex];
                data[selectChildIndex] = temp;
                i = selectChildIndex;
                isSwap = true;
            } else {
                //未发生交换则证明此区间的堆已经调整完成
                isSwap = false;
            }

    }

对应小顶堆的实现,只是换一个节点大小判断的改变即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值