堆排序

简介: 这是一篇自学文章,如果有错误地方请及时指出 堆排序...算法属实优秀,真是有点难理解,花了很长时间才能自己完全写出来,至此献上一个表情包 自己很喜欢李雪健老师 义正辞严!! 图如果有画错的地方请及时指正,谢谢 ,好了正文开始 堆排序 这个算法是基于选择排序思想的算法,其利用堆结构和二叉树的一些特.
  • 这是一篇自学文章,如果有错误地方请及时指出
  • 堆排序...算法属实优秀,真是有点难理解,花了很长时间才能自己完全写出来,至此献上一个表情包

41adfd667da0863e46f9dae90709e519

  • 自己很喜欢李雪健老师 义正辞严!!
  • 图如果有画错的地方请及时指正,谢谢 ,好了正文开始

堆排序

  • 这个算法是基于选择排序思想的算法,其利用堆结构和二叉树的一些特性来完成数据的排序

什么是堆结构

  • 是一种树结构,准确的说是一个完全二叉树,在这个树中每个节点对应于原始数据的一个记录,如图

markdown_img_paste_2018122210504436

markdown_img_paste_20181222105114280

大顶堆与小顶堆

  • 每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆
  • 每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆
  • 升序采用大顶堆,降序采用小顶堆

markdown_img_paste_20181222105717232

堆排序基本思想

  • 将待排序序列构造成一个大顶堆,此时整个序列的最大值就是堆顶的根节点.将其与末尾元素进行交换,此时末尾就为最大值.然后将剩余n-1个元素重新构造成一个堆(n-1就是将以确定的最大值排除在外的意思),这样会得到n个元素的次小值.如此反复执行.便能得到一个有序序列了

堆排序过程

  • 我们先看一张图,这是一张较为简单的构建过程

markdown_img_paste_20181222132916283

  • 然后再来一张比较复杂点的

markdown_img_paste_20181222133953196

markdown_img_paste_20181222134000492

  • 小总结

markdown_img_paste_20181222133005350

  • 到这我们就知道了构建顶堆的基本思想,那么他是怎么来进行排序输出的呢?

markdown_img_paste_20181222135604285

  • 上图说的交换首尾,意思是除了确定好的最大值的剩余序列的首尾,如上的数组结构示意图,72标红被确定了,所以下次有第二大的值就与41的位置处的数据进行交换
  • 代码分析

    • 我们看完了上面的图的流程,我们可以想到首先我们必须要将数据序列先构造成一次大顶堆,因为如果不这样,我们拿不到最大值也就没办法知道哪个值与那个值互换了
    • 之后就是交换数据首尾的值
    • 上面一步操作完毕后,我们的大顶堆就又乱掉了,所以还的需要重新构建
    • 总的说就是:先构建一次大顶堆 -> 交换首尾 -> 再次构建大顶堆
  • java代码实现

    import java.util.Arrays;
    
    public class SS {
        public static void main(String []args){
            //-1 不代表待排序的数字,无论是什么都不影响排序结果,只是一个站位的而已
            int []arr = {-1,41,34,56,33,36,45,72,30};
            heapSort(arr);
            System.out.println(Arrays.toString(arr));
        }
    
        private static void heapSort(int[] arr) {
            int len = arr.length;
            //第一个循环是从下到上的
            //i就是每个非叶结点
            for (int i = len / 2; i > 0; i --) {
                //将叶结点传入后,就是去比较叶结点与其子节点的关系了,而并非一下完成,
                // 而是一个个非叶结点传入,来判断父子关系,再决定交换
                build(arr,i,len);
            }
            //这个循环每循环一次都会挑出剩余最大的值
            for (int i = len - 1; i > 0 ; i --) {
                swap(arr,1,i);
                build(arr,1,i);
            }
        }
        /**
         * @param arr 待排数组
         * @param parent  即每一个非叶结点
         * @param len  数组长度,即从1到N需要排序,比如72确定了后,那么就是1到N-1个待排序
         */
        private static void build(int[] arr, int parent, int len) {
            //i初始化为 左结点 , i *= 2代表下一个非叶结点
            for (int i = parent * 2; i < len; i *= 2) {
                //i+1表示右结点,这就话的意思就是有右结点,并且这个右结点还是最大子节点
                if (i +1 < len && arr[i + 1] > arr[i]){
                    i ++;  //i原来指向了左结点,因为右结点大,所以指向右结点下标
                }
                //如果父节点比最大子节点还大或者相等,就不需要交换
                if (arr[parent] >= arr[i]){
                    break;
                }
                //到这就代表最大子节点比父节点大 ,那么就开始交换
                swap(arr,parent,i);
                //交换完毕后,我们在图中也遇到了就是图结构被破坏了,
                //也就是图四到图五的情况
                //这的赋值代表了,我们交换完成了,依旧要去重新判断一下刚刚交换的子节点是否符合结构
                //就比如图四到图五,72与41交换位置了,那么原来的parent是41,下标为1
                //而i是72,下标为3,由于他们两个交换位置了,所以导致结构乱掉了
                //我们可以将parent指向下标为3的位置,以下标为3作为parent节点,来判断其子节点是否符合结构
                parent = i;
            }
        }
        public static void swap(int []arr,int a ,int b){
            int temp=arr[a];
            arr[a] = arr[b];
            arr[b] = temp;
        }
    }
目录
相关文章
|
存储 缓存 文件存储
如何保证分布式文件系统的数据一致性
分布式文件系统需要向上层应用提供透明的客户端缓存,从而缓解网络延时现象,更好地支持客户端性能水平扩展,同时也降低对文件服务器的访问压力。当考虑客户端缓存的时候,由于在客户端上引入了多个本地数据副本(Replica),就相应地需要提供客户端对数据访问的全局数据一致性。
32698 79
如何保证分布式文件系统的数据一致性
|
前端开发 容器
HTML5+CSS3前端入门教程---从0开始通过一个商城实例手把手教你学习PC端和移动端页面开发第8章FlexBox布局(上)
HTML5+CSS3前端入门教程---从0开始通过一个商城实例手把手教你学习PC端和移动端页面开发第8章FlexBox布局
17751 20
|
设计模式 存储 监控
设计模式(C++版)
看懂UML类图和时序图30分钟学会UML类图设计原则单一职责原则定义:单一职责原则,所谓职责是指类变化的原因。如果一个类有多于一个的动机被改变,那么这个类就具有多于一个的职责。而单一职责原则就是指一个类或者模块应该有且只有一个改变的原因。bad case:IPhone类承担了协议管理(Dial、HangUp)、数据传送(Chat)。good case:里式替换原则定义:里氏代换原则(Liskov 
36682 19
设计模式(C++版)
|
存储 编译器 C语言
抽丝剥茧C语言(初阶 下)(下)
抽丝剥茧C语言(初阶 下)
|
机器学习/深度学习 人工智能 自然语言处理
带你简单了解Chatgpt背后的秘密:大语言模型所需要条件(数据算法算力)以及其当前阶段的缺点局限性
带你简单了解Chatgpt背后的秘密:大语言模型所需要条件(数据算法算力)以及其当前阶段的缺点局限性
24758 14
|
机器学习/深度学习 弹性计算 监控
重生之---我测阿里云U1实例(通用算力型)
阿里云产品全线降价的一力作,2023年4月阿里云推出新款通用算力型ECS云服务器Universal实例,该款服务器的真实表现如何?让我先测为敬!
36660 15
重生之---我测阿里云U1实例(通用算力型)
|
SQL 存储 弹性计算
Redis性能高30%,阿里云倚天ECS性能摸底和迁移实践
Redis在倚天ECS环境下与同规格的基于 x86 的 ECS 实例相比,Redis 部署在基于 Yitian 710 的 ECS 上可获得高达 30% 的吞吐量优势。成本方面基于倚天710的G8y实例售价比G7实例低23%,总性价比提高50%;按照相同算法,相对G8a,性价比为1.4倍左右。
|
存储 算法 Java
【分布式技术专题】「分布式技术架构」手把手教你如何开发一个属于自己的限流器RateLimiter功能服务
随着互联网的快速发展,越来越多的应用程序需要处理大量的请求。如果没有限制,这些请求可能会导致应用程序崩溃或变得不可用。因此,限流器是一种非常重要的技术,可以帮助应用程序控制请求的数量和速率,以保持稳定和可靠的运行。
29838 52

热门文章

最新文章

下一篇
开通oss服务