「排序」堆排序不难!看完这篇你也能手写堆排序啦( 二 )
堆排序上面的一个堆建造完毕之后 , 我们怎么去利用这个堆实现排序呢?答案也是很简单的 , 我们知道堆有一个特性就是堆顶是最小(或最大) , 而我们建造这个如果去除第一个元素 , 剩余左右孩子依然满足堆的性质 。
文章插图
将最后一个元素放置堆顶 , 由于第一个元素的存在使得整个不满足堆的性质 。 分析这个结构 , 和我们前面构造堆的过程中构造到第一个元素的操作相同:
- 判断左右孩子 , 如果需要交换则交换 , 交换后再次考虑交换子节点是否需要交换 。 一直到不需要考虑 。
文章插图
这样到最后 , 堆排序即可完成 , 最终得到的序列即为堆排序序列 。
一个大根堆的排序过程如下:
文章插图
具体实现有了上述的思想之后 , 如何具体的实现这个堆排序的代码呢?从细致的流程来看 , 大概流程是如下的:
给定数组建堆(creatHeap)
- 从第一个非叶子节点开始判断交换下移(shiftDown) , 使得当前节点和子孩子能够保持堆的性值
- 如果交换打破子孩子堆结构性质 , 那么就要重新下移(shiftDown)被交换的节点一直到停止 。
- 所以索性把最后一个元素放到第一位 。 这样只需要判断交换下移(shiftDown),不过需要注意此时整个堆的大小已经发生了变化 , 我们在逻辑上不会使用被抛弃的位置 , 所以在设计函数的时候需要附带一个堆大小的参数 。
- 重复以上操作 , 一直堆中所有元素都被取得停止 。
具体实现的代码如下:
import java.util.Arrays;public class 堆排序 {static void swap(int arr[],int m,int n){int team=arr[m];arr[m]=arr[n];arr[n]=team;}//下移交换 把当前节点有效变换成一个堆(小根)static void shiftDown(int arr[],int index,int len)//0 号位置不用{int leftchild=index*2+1;//左孩子int rightchild=index*2+2;//右孩子if(leftchild>=len)return;else if(rightchild执行结果:
文章插图
当然 , 代码为了成章节我把它命名为中文 , 还有些不规范的地方请注意甄别 。
结语对于堆排序就先介绍到这里了 , 当然堆的强大之处不止这么一点 , 优先队列同样也是用到堆但是这里就不详细介绍了 , 我相信优秀的你肯定又掌握了一门O(nlogn)级别的排序算法啦 。 如果写的有啥不确切地方还请指正 。
最后 , 如果感觉不错一键三联哦! , 欢迎关注公众号:bigsai,更多精彩等你来看 。 期待你的关注 , 并且笔者也准备了一波pdf学习资源分享给你 。
文章插图
- 合并|Andre Cronje主导批量「合并」DeFi项目,是好事情吗?
- mini|电影、mini 与「当日完稿」工作流
- 字化转型|疫情重构经济,传统企业「数字化」的通关密码是什么?
- iPhone12|iPhone12「超大杯」拍照解禁:与Pro拉不开差距
- 供应链|一座快手「重镇」的货端升级
- 项目|DeFi「分叉运动」退潮,我们能从中学到什么?
- 纪念版|「同价选机」K30至尊纪念版 vs Note9 Pro,选谁
- 文案|「热点传递」为什么别人卖点写的“勾人”?
- 系列|OPPO Reno5 真机曝光, 「Reno Glow」晶钻设计再升级
- 烧钱|投资理想汽车赚 58 亿,美团还想继续「烧钱」押注新业务