堆排序

1.大顶堆与小顶堆

大顶堆所有父节点元素不小于其左右孩子节点,小顶堆所有父节点元素不大于其左右孩子节点

2.堆排序介绍

堆排序是指利用堆积树这种数据结构所设计的一种排序算法,是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆与小根堆,是完全二叉树
堆排序是将数据看成完全二叉树进行排序的

3.堆排序过程示意

对数组a进行堆排序:
数组a
1.数组a的堆结构
数组a堆结构
2.构造大顶堆
父节点的数组下标i与左右孩子节点的数组下标关系
左孩子下标 2i + 1
右孩子下标 2
i +2
对数组元素从后往前,也就是堆从下向上进行大顶堆的构造,即从a.length/2 - 1节点开始,也就是数组a[2]开始。a[2]为父节点的子树符合大顶堆,继续检查a[1]节点的子树:也就是在a[1],a[12+1],a[12+2]中选择最大的元素
在a[1]子树中,父节点与孩子节点进行对比,max指向最大元素右子树
右子树与父节点,即a[1]与a[4]置换,此子树大根堆构造完毕
在这里插入图片描述
继续到a[0]为父节点的子树
在这里插入图片描述
置换:
在这里插入图片描述
每一个置换之后都要递归重新构建新子树大顶堆
至此对于a数组,大顶堆构造完毕,数组结构:
数组a构造大顶堆

3.大顶堆排序
排序过程:每一次将堆顶的最大元素,与堆底即数组最后一位元素置换,即完成一次排序,去除最后一位元素的新数组再次进行建堆,将堆顶与最后一位元素继续置换,直到仅剩堆顶一个元素。数组排序即完成。
第一次堆顶与数组最后元素置换
新数组a[0-5]重新重复建堆过程:
新大顶堆
再次使堆顶与最后一位元素置换
在这里插入图片描述
重新建堆
在这里插入图片描述
堆顶与最后一个元素置换
在这里插入图片描述
重新建堆
在这里插入图片描述
堆顶置换
在这里插入图片描述
最后达到
在这里插入图片描述
排序完成

4.堆排序数据结构实现

数组a[]
对于元素a[i]
左孩子节点 a[i2+1]
右孩子节点啊a[i
2+2]

5.java代码

构建大顶堆:

void heapify(int[]a, int currentRootNode, int size){
        if(currentRootNode < size){
            int left = 2 * currentRootNode + 1; //左孩子节点
            int right = 2 * currentRootNode + 2; //右孩子节点
            
            int max = currentRootNode; //此子数最大元素节点下标,初始值为父亲节点下标
            
            if(left < size){ //如果当前节点存在左孩子
                if(a[max] < a[left])
                    max = left;
            }

            if(left < size){ //如果当前节点存在右孩子
                if(a[max] < a[left])
                    max = right;
            }
            //如果最大元素非父亲节点,则置换
            if(max != currentRootNode){
                int temp = a[max];
                a[max] = a[currentRootNode];
                a[currentRootNode] = temp;
                //置换后的左(右)节点的子树重新构建大顶堆
                heapify(a, max, size);
            }
        }
    }

建堆过程时从后向前的:

void maxHeapify(int[] a, int size){
        for(int i = size/2 - 1; i >= 0; i--)
            heapify(a, i, size);
    }

排序,每次构建好的大顶堆堆顶元素与堆底元素置换,不断缩小需要排序数组范围直至仅剩一个堆顶元素。

for(int i = 0; i < a.length; i++){
            maxHeapify(a, a.length - i); //构建去除已排好序的数组后i位剩余数组的新堆
            //堆顶与堆底置换
            int temp = a[0];
            a[0] = a[a.length - 1 - i];
            a[a.length - 1 - i] = temp;
        }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值