树结构的实际应用

news2024/11/13 19:44:13

堆排序

堆排序的介绍

  • 堆排序利用这中数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它是不稳定排序
  • 堆是具有以下性质的完全二叉树:每个节点的值都大于或等于其它左右孩子节点的值,称为大顶堆,注意:没有要求节点的左孩子和右孩子的值的大小关系.
  • 每个节点的值都小于或等于其左右孩子节点的值,称为小顶堆
  • 大顶堆举例说明
  • 在这里插入图片描述
    大顶堆特点:arr[i]>arr[2i+1]&&arr[i]>=arr[2i+2]
  • 小顶对举例说明
  • 在这里插入图片描述
  • 小顶堆特点:arr[i]<=arr[2i+1]&&arr[2i+2]
  • 一般升序排序我们采用大顶堆,降序排序我们采用小顶堆

堆排序的思想

堆排序的基本思想

  1. 将待排序的序列构造成一个大顶堆
  2. 此时,整个序列的最大值就是堆顶的根节点
  3. 将其与末尾元素进行交换,此时末尾就是最大值
  4. 然后将剩余的n-1个元素重写构造成一个大顶堆,这样就会得到n个元素的次小值,如此反复的执行,便能得到一个有序序列了.
  5. 可以看到在构建大顶堆的过程中,元素的个数逐渐减少,最后就得到一个有序序列.

堆排序步骤图解说明

  1. 构造初始堆,将给定一个无序序列构造成一个大顶堆(一般升序大顶堆,降序小顶堆)
  2. 原始数组[4,6,8,5,9]
  • 假设给定无序序列结构如下
    在这里插入图片描述
  • 此时我们从最后一个非叶子节点开始(叶节点自然不用调整,第一个非叶子节点arr.length/2-1=5/2-1=1,也就是下面的6节点,)从左至右,从上至下进行调整
    在这里插入图片描述
  • 再找到第二个非叶子节点,由于[4,9,8]中9元素最大,4和9交换
    在这里插入图片描述
  • 这时,交换导致了子根[4,5,6]结构混乱,继续调整,[4,5,6]中6最大,交换4,6

在这里插入图片描述
此时,我们就得到了一个大顶堆

  1. 将堆顶元素与末尾元素进行交换,使末尾元素最大,然后继续调整堆,再将堆顶元素与末尾元素交换,得到第二大元素,得到第二大元素,如此反复进行交换,重建,交换.
  • 将堆顶元素9和末尾元素4进行交换,
    在这里插入图片描述
  • 重新调整结构,使其满足堆定义
    在这里插入图片描述
  • 再将堆顶元素8与末尾元素5进行交换,得到第二大元素8
    在这里插入图片描述
  • 后续过程中,继续进行调整,交换,如此反复进行,最终使得整个序列有序
    在这里插入图片描述
    在简单总结一下堆排序思路
    1, 将无序序列构建成一个堆,根据升序降序的需求选择大顶堆或小顶堆
    2, 将堆顶元素与末尾元素进行交换,将最大元素"沉"大数组末端
    3,重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序
    结合代码分析
    在这里插入图片描述
    代码实现
package com.atguigu.tree;

import java.util.Arrays;

public class HeapSort {
    public static void main(String[] args) {
        int[] arr={4,6,8,5,9};
        heapSort(arr);

        //插入排序的速度测试
        int[] arr2=new int[80000];
        for (int i=0;i<80000;i++){
            arr2[i]=(int)(Math.random()*40000);//生成一个[0,20000)的随机整数
        }
        long startTime=System.currentTimeMillis();
        heapSort(arr2);
        long endTime=System.currentTimeMillis();
        System.out.println("排序用的时间:"+(endTime-startTime));
    }


    //编写一个堆排序的方法
    public static void heapSort(int[] arr){
        int temp=0;
        System.out.println("堆排序");
        //分部完成
        adjustHeap(arr,1,arr.length);
        System.out.println("第一次调整后:"+ Arrays.toString(arr));

        adjustHeap(arr,0,arr.length);
        System.out.println("第二次调整后:"+Arrays.toString(arr));

        //完成我们的最终代码
        //将一个无序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆
        for(int i=arr.length/2-1;i>=0;i--){
            adjustHeap(arr,i,arr.length);
        }
        System.out.println("数组:"+Arrays.toString(arr));

        //将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端
        //重写调整结构,使其能满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复调整+交换步骤,直到整个序列有序
        for(int j=arr.length-1;j>0;j--){
            //交换
            temp=arr[j];
            arr[j]=arr[0];
            arr[0]=temp;
            adjustHeap(arr,0,j);//真实情况每次调整总是重顶上调整的.
        }
        System.out.println("数组:"+Arrays.toString(arr));

    }

    //将一个数组(二叉树),调整成一个大顶堆

    /**
     * 完成将以i对应的非叶子节点数调整为大顶堆
     * @param arr 待调整的数组
     * @param i 表示非叶子节点的在数组中索引
     * @param length 多少个元素进行调整,length是在逐渐减少
     */
    public  static void adjustHeap(int[] arr,int i,int length){
        int temp=arr[i];//先取出当前元素的值,保存在临时变量里面
        //开始调整
        /*
        说明,k=i*2+1是i节点的左子节点.
         */
        for(int k=i*2+1;k<length;k=k*2+1){
            if((k+1)<length&&arr[k]<arr[k+1]){//说明左子节点它的值小于右子节点的值
                k++;//k指向右子节点
            }
            if(arr[k]>temp){//如果子节点大于父节点
                arr[i]=arr[k];//把较大的值赋值给当前的父节点
                i=k;//让i执行k,继续循环比较
            }else {
                break;
            }

        }
        //当for循环结束后,我们已经将以i为父节点的树的最大值,调整到了最上面
        arr[i]=temp;//将temp放到调整之后的位置
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/12886.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

苹果电脑的文件怎么复制到移动硬盘,macbook文件怎么拷贝到移动硬盘

如果我们使用的是Mac电脑&#xff0c;刚好需要将一些文件从Mac复制到NTFS外置硬盘&#xff0c;那么&#xff0c;苹果电脑的文件怎么复制到移动硬盘&#xff1f; 一、如何将文件从Mac电脑上复制到NTFS外置硬盘&#xff1f; 我可以在Mac上正常使用NTFS外置硬盘吗&#xff1f;很多…

Linux【搭建环境与基本指令】

Linux【搭建环境与基本指令】&#x1f34e;一.Linux搭建环境&#x1f352;1.1什么是Linux&#x1f349;1.1.1Linux介绍&#x1f349;1.1.2CentOS 和 RedHat 的关系&#x1f349;1.1.3在Java中应用到Linux的方面&#x1f352;1.2XShell的安装与使用&#x1f349;1.2.1XShell的安…

定时器的使用和线程安全

在linux下如果对定时要求不太精确的话&#xff0c;使用alarm()和signal()就行了&#xff1b; 但是如果想要实现精度较高的定时功能的话&#xff0c;就要使用setitimer函数。 核心api&#xff1a; int setitimer(int which, const struct itimerval *value, struct itimerval *…

【李宏毅】机器学习-RNN

RNN(Recurrent Neural Network) 为什么需要RNN呢&#xff1f; 举例来说&#xff0c;有一个任务需要识别每个单词代表的含义。在下面的句子中&#xff0c;taipei分别表示目的地和出发地&#xff0c;我们希望神经网络能够在不同的句子中&#xff0c;识别出不同的语义&#xff0c;…

3、排序(order by)与分页(limit)多表查询 -mysql

3、排序与分页&多表查询 -mysql排序与分页一、排序 Order By二、分页 Limit多表查询一、一个案例引发的多表连接2、笛卡尔积&#xff08;或交叉连接&#xff09;的理解二、多表查询分类讲解1、等值连接 vs 非等值连接2、自连接 vs 非自连接3、内连接 vs 外连接三、SQL99语法…

pytorch深度学习实战lesson18

第十八课 卷积层 卷积是深度学习最重要的概念之一&#xff0c;下面来学习和回顾一下卷积的基本概念。 目录 理论部分 从全连接层到卷积层 卷积层 实践部分 理论部分 从全连接层到卷积层 还是从一个例子开始&#xff1a;假设我要对猫和狗进行分类。 假设我用一千二百万像…

3年经验,光靠自动化测试基础,你可能连17k的测试岗都找不到,认清现实.....

相信对于每一个求职者来说都有被面试的经历吧&#xff0c;曾经作为一位测试小白的我&#xff0c;每一次面试过后都会各种吐槽面试官的不是&#xff0c;吐槽HR人事的不足&#xff0c;以及自己的有点没有发挥出来&#xff0c;今天我终于体会了一次面试官的心情.... 起因&#xf…

【夯实Kafka知识体系及基本功】分析一下(Broker)服务的可靠性机制分析「原理篇」

副本机制 分布式系统中&#xff0c;为了提高可靠性&#xff0c;最常用、最有效的策略是“副本机制”&#xff0c;Kafka也不例外。 Kafka 为每个 Partition 维护了一个 AR&#xff08;Assigned Replicas&#xff09;列表&#xff0c;由 ISR&#xff08;In-Sync Replicas&#x…

通过瑞利判据对显微镜物镜进行分辨率研究

摘要 通常可以采用瑞利判据理论表征显微镜的分辨率&#xff0c;瑞利判据是1896年由第三代瑞利男爵约翰威廉斯特拉特(John William Strutt)提出的。该理论认为&#xff0c;当一个艾里图样的中心与另一个艾里图样的第一个最小值重叠时&#xff0c;就可以分辨它们。在这个例子中…

力扣(LeetCode)3. 无重复字符的最长子串(C++)

滑动窗口 设置滑动窗口&#xff0c; lll 维护左窗口 &#xff0c; rrr 维护右窗口 &#xff0c;利用哈希表统计字母出现次数。 遍历字符串 sss &#xff0c;lll 循环右移&#xff0c;每次移动 &#xff0c; lll 指向的字母 s[l]s[l]s[l] 出现次数 。如果窗口内 s[l]s[l]s[l] …

NCMMSC 2021丨长短视频多语种多模态识别挑战赛

比赛背景 2021年第十六届全国人机语音通讯学术会议&#xff08;National Conference on Man-Machine Speech Communication&#xff0c;NCMMSC2021&#xff09;将于2021年10月15-18日在江苏徐州举行。本次会议由中国中文信息学会和中国计算机学会联合主办。 针对本次会议&…

STA -- clock gating check

对于现在design中例化好的icg以及工具插进去的icg&#xff0c;不存在clock gating check的问题&#xff0c;因为clock gating 搞成了一个lib cell&#xff0c;不再是latch加上与门的组合。不过design中除了这些icg&#xff0c;还有一些的clock gating check的出现&#xff0c;这…

写给 Android 开发:从0到1,再从1到N,都离不开 Framework

作为过来人&#xff0c;发现很多学习者和实践者都在 Android Framework上面临着很多的困扰&#xff0c;比如&#xff1a; 工作场景中遇到难题&#xff0c;往往只能靠盲猜和感觉&#xff0c;用临时性的补救措施去掩盖&#xff0c;看似解决了问题&#xff0c;但下次同样的问题又…

Node.js开发、CommondJS 、ES-Module模块化设计

目录 Node.js是什么 基础使用 Node的REPL 全局变量 模块化设计 CommondJS规范 基础使用exports和module.exports require CommondJS优缺点 AMD和CMD规范 ES_Module 基本使用方法 导出 导入 结合使用 默认导出 ES Module解析流程 Node.js是什么 Node与浏览器的对比 在…

两点云求差集和交集

这里两点云的差集指从点云1中删除属于点云2的点得到的点集&#xff0c;并集指既属于点云1又属于点云2的点集。 两点云求差集 基于kd-tree搜索的方法较快速&#xff0c;当然也可以暴力搜索。思路如下&#xff1a; step1 在点云2建立kd-tree&#xff0c;设置容忍误差&#xff0…

UI控件DevExpress WinForm新手指南——如何在应用启动时执行操作

DevExpress WinForm拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForm能完美构建流畅、美观且易于使用的应用程序&#xff0c;无论是Office风格的界面&#xff0c;还是分析处理大批量的业务数据&#xff0c;它都能轻松胜任…

RESTful 接口设计

文章目录RESTful 接口设计1.获取所有员工列表2.增加一个员工3.更新员工4.删除员工5.查询单个员工RESTful 接口设计 1.获取所有员工列表 /*** 获取所有员工* 1. 请求路径--确认资源--员工--/employees* 2. 请求方法--get* 3. 请求参数--无* 4. 请求响应--多个员工--List<Em…

苹果iOS App Store上架操作流程

很多开发者在开发完iOS APP、进行内测后&#xff0c;下一步就面临上架App Store&#xff0c;不过也有很多同学对APP上架App Store的流程不太了解&#xff0c;下面我们来说一下iOS APP上架App Store的具体流程&#xff0c;如有未涉及到的部分&#xff0c;大家可以及时咨询&#…

基于微信小程序的学生购电系统设计与实现-计算机毕业设计源码+LW文档

小程序开发说明 开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Mave…

服务端Skynet(二)——消息调度机制

服务端Skynet(二)——消息调度机制 文章目录服务端Skynet(二)——消息调度机制1、提前了解知识1.1、互斥锁&#xff08;mutex lock : **mut**ual **ex**clusion lock&#xff09;1.2、自旋锁&#xff08;spinlock&#xff09;1.3、读写锁&#xff08;readers–writer lock&…