【Java数据结构】——第十节(下).选择排序与堆排序

news2024/9/21 18:33:16

作者简介:大家好,我是未央;

博客首页:未央.303

系列专栏:Java初阶数据结构

每日一句:人的一生,可以有所作为的时机只有一次,那就是现在!!!

文章目录

前言

一、选择排序

1.1 算法思路

 1.2 代码实现

1.3 特性总结

二、堆排序(从小到大)

2.1 算法思路

2.2 代码实现

2.3 特性总结

总结


 

前言

今天我们将介绍另外的两种常见的算法,即选择排序算法和堆算法;这两个算法也是非常重要的算法,必须要好好掌握才行;


一、选择排序

1.1 算法思路

动画图示:

 算法思路:

在遍历数组的过程中,从当前遍历的数组元素的下一个元素开始,向后找出剩余数组元素中的最小值,让这个最小值和当前遍历到的数组元素进行交换;

详细说就是:

  • 在元素集合array[i]--array[n-1]中选择关键码最大(小)的数据元素
  • 若它不是这组元素中的最后一个(第一个)元素,则将它与这组元素中的最后一个(第一个)元素交换
  • 在剩余的array[i]--array[n-2](array[i+1]--array[n-1])集合中,重复上述步骤,直到集合剩余1个元素

240a71907ac23932af5a4cd53072eafc.png


 1.2 代码实现

/**
     * 选择排序
     * @param array
     */
    public static void selectSort(int[] array) {
        for (int i = 0; i < array.length; i++) {
            int minIndex = i;
            for (int j = i + 1; j < array.length; j++) {
                if (array[j] < array[minIndex]) { // 注意这里不能是array[i] < array[j]因为j在这个循环里是静态的,我们排序要求是动态的
                    minIndex = j; // 比如[1、34、56、12、23], i下标所对应的数组的值一开始等于34,j -> 12是满足条件,minIndex更新,等于12所对应的下标
                    // 但如果是array[i] < array[j],此时array[j]还等于34,等于遇到23,条件仍然满足,minIndex又更新了,但其实这个时候不应该更新,因为刚才的12就是从i下标往后的数组中最小的值了
                }
            }
            int tmp = array[i]; 
            array[i] = array[minIndex]; // 如果每找到,minIndex = i,相当于是自己和自己进行交换
            array[minIndex] = tmp;
        }
    }

1.3 特性总结

  • 1. 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用
  • 2. 时间复杂度:O(N^2)
  • 3. 空间复杂度:O(1)
  • 4. 稳定性:不稳定

选择排序为啥不是稳定性排序呢????举个例子:数组 6、7、6、2、8,在对其进行第一遍循环的时候,会将第一个位置的6与后面的2进行交换。此时,就已经将两个6的相对前后位置改变了。因此选择排序不是稳定的排序算法;


二、堆排序(从小到大)

2.1 算法思路

  1. 将要排序的数组建立为大根堆
  2. 堆顶元素(当前数组的最大值)与数组end下标的元素互换位置
  3. 然后从堆顶向下调整为大根堆,这里要注意调整时的边界条件end是在不断变化的,当前end也不断在变化着的,每调整一次end就减一,直到end == 0

图示分析:


2.2 代码实现

import java.util.Arrays;
// 堆排序完整代码测试
public class heapSortTest {
    // 向下调整为大根堆
    public static void shiftDownBig(int[] array, int root, int len) {
        int parent = root;
        int child = 2 * parent + 1;
        while (child < len) {
            if (child + 1 < len && array[child] < array[child + 1]) {
                child = child + 1;
            }
            if (array[child] > array[parent]) {
                int tmp = array[child];
                array[child] = array[parent];
                array[parent] = tmp;
                parent = child;
                child = 2 * parent + 1;
            }
            else {
                break;
            }
 
        }
    }
    // 大根堆的创建(这里我们用到是向下调整建立大根堆,时间复杂度O(n)——如果是向上调整建立大根堆堆,时间复杂度是O(n * log2N)
    public static void createHeap(int[] array) {
        for (int i = (array.length - 1 - 1) / 2; i >= 0; --i) {
            shiftDownBig(array, i, array.length);
        }
    }
    /**
     * 堆排序,从小到大排序——建立大根堆(原地排序,在数组本身排序)
     * @param
     */
    public static void heapSort(int[] array) {
        // 1、先建立一个大根堆,建堆的时间复杂度为O(n)因为我们是通过向下调整来建堆的
        createHeap(array);
        // 2、将当前堆顶元素(array[0])与堆中end下标的元素互换位置,然后向下调整,保证仍为大根堆——这样堆顶元素仍旧是当前数组中最大的元素
        // end从堆中最后一个元素开始,保证堆中(数组)的最大值在堆中最后一个元素的位置,然后倒数第二大、第三大元素接着从array.length - 2开始向前排
        for (int end = array.length - 1; end > 0; --end) {
            int tmp = array[end];
            array[end] = array[0];
            array[0] = tmp;
            // 调整0下标这棵树仍为大根堆
            shiftDownBig(array, 0, end);
            // 保证调整完后是大根堆,注意这里的结束位置是end,end后面是用到存放数组前k个元素的,如果结束位置是array.length,那么我们之前放到数组array.length - 1下标的数组最大值就又被调整了
        }
        // 具体堆排的时间复杂度为 O(n * logn)--总的时间复杂度就是(n + n * logn)即O(n * log以2为底的n)
    }
 
    public static void main(String[] args) {
        int[] array = {23, 42, 13, 12, 28};
        heapSort(array);
        System.out.println(Arrays.toString(array));
    }
    
}

 运行结果:


2.3 特性总结

1、堆排序使用堆来选数,效率就高了很多。

2、时间复杂度:O(N*logN)

3、空间复杂度:O(1)

4、稳定性:不稳定;

总结

今天的两种算法就介绍到这里了,一定要熟练掌握这两种算法使用;

 

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

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

相关文章

一文3000字从0到1手把手教你基于PostMan的接口自动化测试

临近下半年&#xff0c;公司任务也不是很多&#xff0c;趁这个机会老大让我研究了一下PostMan的脚本自动化测试。作为一个前端开发&#xff0c;说实话&#xff0c;对于PostMan的操作&#xff0c;仅仅限于新建请求->填写url地址和参数->send发送&#xff0c;然后看看返回值…

智能排班系统 【开源说明】

文章目录 引言说明讲讲开源开源要做什么了解开源协议项目的信息脱敏写好项目说明文档修改.gitignore 项目不完善点说明管理系统前端页面自适应做得不好部分页面体验不好 管理系统后端接口缺乏数据校验数据管理接口查询不够完善接口可以更加完善 开源仓库地址其他文章引用说明前…

【我的创作纪念日】—— 纪念四年的坚持

这是一篇和技术无关的博客&#xff0c;但对我而言&#xff0c;它承载了不菲的价值 普通且宁静的一天&#xff0c;被一条消息戳中&#xff0c;于是&#xff0c;写一篇分享帖&#xff0c;纪念我这 1460 天的坚持初衷&#xff1a; 前言&#xff1a;对过去的回顾 4 年前的我&#…

南京邮电大学算法与设计实验二:贪心算法(最全最新,与题目要求一致)

三、实验原理及内容 实验原理&#xff1a; 1、用贪心法实现求两序列的一般背包问题。要求掌握贪心法思想在实际中的应用&#xff0c;分析一般背包的问题特征&#xff0c;选择算法策略并设计具体算法&#xff0c;编程实现贪心选择策略的比较&#xff0c;并输出最优解和最优解值。…

图的遍历,最小生成树,最短路径算法的手算。

1.图的遍历 按照某种规则沿着图中的边对图中的所有顶点访问一次且仅访问一次。 注&#xff1a;图是一种特殊的树。 1.广度优先遍历BFS 不难看出&#xff0c;图的广度优先就是参照的树的层次遍历算法。 2.深度优先遍历 从某个顶点开始V&#xff0c;访问这个顶点V相邻的任意…

【音视频开发】视频编码格式:YUV

文章目录 分类标准分类 简介 参考&#xff1a;YCbCr与YUV 分类标准 首先&#xff0c;我们可以将 YUV 格式按照数据大小分为三个格式&#xff0c;YUV 420&#xff0c;YUV 422&#xff0c;YUV 444。由于人眼对 Y 的敏感度远超于对 U 和 V 的敏感&#xff0c;所以有时候可以多个 …

位运算符及其相关操作详解

位运算符详解 前言&#xff1a;由于位运算符是直接对二进制数操作&#xff0c;因此对二进制、八进制、十六进制不甚了解的小伙伴建议先看这篇二进制、八进制、十六进制与十进制的相互关系&#xff0c;这样阅读本篇时将事半功倍 总览 位运算是对计算机存储的二进制序列的相应位进…

【笔试强训选择题】Day17.习题(错题)解析

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;笔试强训选择题 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01; 前言 目…

南京邮电大学算法与设计实验三:动态规划法(最全最新,与题目要求一致)

实验原理&#xff1a; 1、用动态规划法和备忘录方法实现求两序列的最长公共子序列问题。要求掌握动态规划法思想在实际中的应用&#xff0c;分析最长公共子序列的问题特征&#xff0c;选择算法策略并设计具体算法&#xff0c;编程实现两输入序列的比较&#xff0c;并输出它们的…

Linux之NetLink学习笔记

1.NetLink机制 NetLink是一种基于应用层跟内核态的通信机制&#xff0c;其特点是一种异步全双工的通信方式&#xff0c;支持内核态主动发起通信的机制。该机制提供了一组特殊的API接口,用户态则通过socket API调用。内核发送的数据再应用层接收后会保存在接收进程socket的缓存…

MediaPipe虹膜检测:实时虹膜跟踪和深度估计

包括计算摄影(例如,人像模式和闪光反射)和增强现实效果(例如,虚拟化身)在内的大量实际应用都依赖于通过跟踪虹膜来估计眼睛位置。一旦获得了准确的光圈跟踪,我们就可以确定从相机到用户的公制距离,而无需使用专用的深度传感器。反过来,这可以改善各种用例,从计算摄影…

《Kali渗透基础》01. 介绍

kali渗透 1&#xff1a;渗透测试1.1&#xff1a;安全问题的根源1.2&#xff1a;安全目标1.3&#xff1a;渗透测试1.4&#xff1a;标准 2&#xff1a;Kali2.1&#xff1a;介绍2.2&#xff1a;策略2.3&#xff1a;安装 3&#xff1a;Kali 初步设置3.1&#xff1a;远程连接3.1.1&a…

深度学习之全过程搭建卷积神经网络(CNN)

大家好&#xff0c;我是带我去滑雪&#xff01; 本期将尝试使用CIFAR-10 数据集搭建卷积神经网络&#xff0c;该数据集由 10 个类别的 60000 张 32x32 彩色图像组成&#xff0c;每个类别有 6000 张图像。 下面开始全过程搭建CNN识别彩色图片&#xff1a; 目录 &#xff08;1&a…

【Linux】冯诺依曼与操作系统

目录 一、冯诺依曼结构体系1、冯诺依曼结构体系简介2、为什么要有内存呢&#xff1f; 二、操作系统1、操作系统如何对硬件进行管理&#xff1f;2、操作系统为什么要对软硬件进行管理&#xff1f; 一、冯诺依曼结构体系 1、冯诺依曼结构体系简介 在现实生活中&#xff0c;我们…

KEYSIGHT MSOS204A 2GHZ 4通道DSOS204A高清晰度示波器

KEYSIGHT是德DSOS204A/MSOS204A高清晰度示波器 附加功能&#xff1a; 2 GHz 带宽&#xff08;可升级&#xff09; 4 个模拟通道和 16 个数字通道 最大存储深度&#xff1a;800 Mpts&#xff08;2 通道&#xff09;&#xff0c;400 Mpts&#xff08;4 通道&#xff09; 最大…

菱形继承、菱形虚拟继承、以及菱形虚拟继承的模型结构内部。

1. 单继承&#xff1a;一个子类只有一个直接父类。 多继承&#xff1a;一个子类有两个或以上直接父类。 菱形继承&#xff1a;菱形继承是多继承的一种特殊情况。 下面是代码和对象模型结构&#xff0c;可以看出菱形结构存在哪些问题&#xff0c;如下&#xff1a; #define _CR…

学习经验分享【30】Pycharm插件chatgpt,用来辅助编写代码

在Pycharm中发现ChatGPT插件&#xff0c;很好用&#xff0c;免费安全&#xff0c;大家可以作为编代码的辅助工作&#xff0c;也可用来玩GPT的接口。具体方法如下 实现效果如下&#xff1a; 更多精彩内容敬请持续关注。如果本博文对你有帮助的话&#xff0c;欢迎点赞、评论区留言…

BUUCTF-一叶障目 解析

打开文件发现一张png图片&#xff0c;里面没有内容&#xff0c;使用tweakpng打开 tweakpng报错 &#xff0c;说明crc校验值对不上 有两种可能&#xff0c;一是crc值被修改&#xff0c;二是图片的宽高被修改&#xff08;在ctf中多半是后者&#xff09; 先尝试修改crc值为55900…

【王道·计算机网络】第五章 传输层

一、传输层概述 传输层为应用层提供通信服务&#xff0c;使用网络层服务传输层的功能&#xff1a; 提供进程和进程之间的逻辑通信&#xff08;网络层提供主机之间的逻辑通信&#xff09;复用&#xff08;发送发不同的应用进程&#xff09;和分用&#xff08;接收方正确的数据传…

【网络协议详解】——PPP协议(学习笔记)

目录 &#x1f552; 1. 数据链路层协议概述&#x1f552; 2. PPP协议分析&#x1f558; 2.1 概述&#x1f558; 2.2 工作流程&#x1f558; 2.3 帧格式 &#x1f552; 3. LCP协议&#x1f558; 3.1 概述&#x1f558; 3.2 报文格式&#x1f558; 3.3 报文种类&#x1f564; 3.3…