数据结构与算法——选择排序法

news2024/12/29 9:39:58

个人简介

👀个人主页: 前端杂货铺
🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展
📃个人状态: 研发工程师,现效力于中国工业软件事业
🚀人生格言: 积跬步至千里,积小流成江海
🥇推荐学习:🍍前端面试宝典 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js🍒Three.js🍖数据结构与算法体系教程

🌕个人推广:每篇文章最下方都有加入方式,旨在交流学习&资源分享,快加入进来吧

数据结构与算法

内容参考链接
数据结构与算法——线性查找法线性查找法

文章目录

  • 数据结构与算法
    • 一、选择排序法
    • 二、使用带约束的泛型
    • 三、使用 Comparable 接口
    • 四、选择排序法的复杂度
    • 五、本篇小结


一、选择排序法

排序算法:让数据有序,排序算法中蕴含着重要的算法设计思想

如果我们想把数组 [1, 4, 2, 3, 6, 5] 变成 [1, 2, 3, 4, 5, 6] 的顺序,就可以使用选择排序法实现

基本思路:arr[i…n) 未排序,arr[0…i) 已排序,arr[1…n) 中的最小值要放到 arr[i] 的位置

代码实现:sort() 方法里面是双重 for 循环,用于对当前最小值索引的更改,之后再通过 swap() 方法,实现索引位置对应值的交换

时间复杂度:O(n^2)

SelectionSort.java

public class SelectionSort {
	// 构造方法
    private SelectionSort() {}

    public static void sort(int[] arr) {
        // arr[0...1) 是有序的; arr[i...n) 是无序的
        for (int i = 0; i < arr.length; i++) {
            // 选择 arr[i...n) 中的最小值的索引
            int minIndex = i;
            for (int j = i; j < arr.length; j++) {
                if (arr[j] < arr[minIndex]) {
                    minIndex = j;
                }
            }
            swap(arr, i, minIndex);
        }
    }
    // 交换值
    private static void swap(int[] arr, int i, int j) {
        int t = arr[i];
        arr[i] = arr[j];
        arr[j] = t;
    }

    public static void main(String[] args) {
        int[] arr = {1, 4, 2, 3, 6, 5};
        SelectionSort.sort(arr);
        for (int e: arr) {
            System.out.print(e + " "); // 输出:1 2 3 4 5 6
        }
    }
}

在这里插入图片描述


二、使用带约束的泛型

同样的,如果我们想针对各种类型进行比较就需要使用泛型来实现

注意这里需要使用 带约束的泛型,即泛型 E 继承 Comparable 接口,实现可比较。其 API => compareTo() 返回整型,小于零表示前者小于后者,等于零表示前者等于后者,大于零表示前者大于后者…

SelectionSort.java

public class SelectionSort {
    private SelectionSort() {}

    // 泛型约束 => 可比较的
    public static <E extends Comparable<E>> void sort(E[] arr) {
        // arr[0...1) 是有序的; arr[i...n) 是无序的
        for (int i = 0; i < arr.length; i++) {
            // 选择 arr[i...n) 中的最小值的索引
            int minIndex = i;
            for (int j = i; j < arr.length; j++) {
                // compareTo 返回整型,小于零表示前者小于后者
                if (arr[j].compareTo(arr[minIndex]) < 0) {
                    minIndex = j;
                }
            }
            swap(arr, i, minIndex);
        }
    }
    // 交换值
    private static <E> void swap(E[] arr, int i, int j) {
        E t = arr[i];
        arr[i] = arr[j];
        arr[j] = t;
    }

    public static void main(String[] args) {
        Integer[] arr = {1, 4, 2, 3, 6, 5};
        SelectionSort.sort(arr);
        for (int e: arr) {
            System.out.print(e + " "); // 输出:1 2 3 4 5 6
        }
    }
}

在这里插入图片描述


三、使用 Comparable 接口

接下来,我们尝试实现让 Student类 使用 Comparable 接口

代码实现:

我们定义 Student类,让其使用 Comparable 接口,在类内部重写 compareTo() 方法(该方法必须要重写,不然编译报错),按成绩的升序进行排序

我们再重写 toString() 方法,格式化字符串

Student.java

public class Student implements Comparable<Student> {
    private String name;
    private int score;
    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }

    @Override
    public int compareTo(Student another) {
        return this.score - another.score;
    }

    @Override
    public String toString() {
        // 格式化字符串
        return String.format("Student(name: %s, score: %d)", name, score);
    }
}

我们在 main 函数中定义 student 数组,通过排序算法进行排序,最后再循环输出

SelectionSort.java

public class SelectionSort {
    private SelectionSort() {}

    // 泛型约束 => 可比较的
    public static <E extends Comparable<E>> void sort(E[] arr) {
        // arr[0...1) 是有序的; arr[i...n) 是无序的
        for (int i = 0; i < arr.length; i++) {
            // 选择 arr[i...n) 中的最小值的索引
            int minIndex = i;
            for (int j = i; j < arr.length; j++) {
                // compareTo 返回整型,小于零表示前者小于后者
                if (arr[j].compareTo(arr[minIndex]) < 0) {
                    minIndex = j;
                }
            }
            swap(arr, i, minIndex);
        }
    }
    // 交换值
    private static <E> void swap(E[] arr, int i, int j) {
        E t = arr[i];
        arr[i] = arr[j];
        arr[j] = t;
    }

    public static void main(String[] args) {
        Student[] students = {
                new Student("Jon", 95),
                new Student("Pu", 100),
                new Student("Alice", 60)
        };
        SelectionSort.sort(students);
        for (Student student: students) {
            System.out.print(student + " ");
        }
    }
}

在这里插入图片描述


四、选择排序法的复杂度

接下来,我们测试算法的性能,并且使用 1万个 数据和 10万个 数据来查看时间复杂度是否为 O(n^2)。

我们新创建一个 ArrayGenerator.java 文件,用于随机生成长度为 n 的数组

ArrayGenerator.java

import java.util.Random;

public class ArrayGenerator {
    private ArrayGenerator() {}

    // 生成一个长度为 n 的随机数组,每个数字的范围是 [0, bound)
    public static Integer[] generateRandomArray(int n, int bound) {
        Integer[] arr = new Integer[n];
        Random rnd = new Random();
        for (int i = 0; i < n; i++) {
        	// nextInt() 用于获取一个 int 类型的数
            arr[i] = rnd.nextInt(bound);
        }
        return arr;
    }
}

我们再创建一个 SortingHelper.java 文件,用于判断是否为排序,以及用来做排序测试

SortingHelper.java

public class SortingHelper {
    private SortingHelper() {}

    public static <E extends Comparable<E>> boolean isSorted(E[] arr) {
        for (int i = 1; i < arr.length; i++) {
            if (arr[i-1].compareTo(arr[i]) > 0) {
                return false;
            }
        }
        return true;
    }

    public static <E extends Comparable<E>> void sortTest(String sortName, E[] arr) {
        long startTime = System.nanoTime();
        if (sortName.equals("SelectionSort")) {
            SelectionSort.sort(arr);
        }
        long endTime = System.nanoTime();

        double time = (endTime - startTime);

        if (!SortingHelper.isSorted(arr)) {
            throw new RuntimeException(sortName + "failed");
        }
        System.out.println(String.format("%s , n = %d : %f s", sortName, arr.length, time / 1000000000));
    }
}

在 SelectionSort.java 文件中我们编写基本的选择排序逻辑,并实现 1万个 和 10万个 数据的排序

public class SelectionSort {
    private SelectionSort() {}

    // 泛型约束 => 可比较的
    public static <E extends Comparable<E>> void sort(E[] arr) {
        // arr[0...1) 是有序的; arr[i...n) 是无序的
        for (int i = 0; i < arr.length; i++) {
            // 选择 arr[i...n) 中的最小值的索引
            int minIndex = i;
            for (int j = i; j < arr.length; j++) {
                // compareTo 返回整型,小于零表示前者小于后者
                if (arr[j].compareTo(arr[minIndex]) < 0) {
                    minIndex = j;
                }
            }
            swap(arr, i, minIndex);
        }
    }
    // 交换值
    private static <E> void swap(E[] arr, int i, int j) {
        E t = arr[i];
        arr[i] = arr[j];
        arr[j] = t;
    }

    public static void main(String[] args) {
        int[] dataSize = {10000, 100000};
        for (int n : dataSize) {
            Integer[] arr = ArrayGenerator.generateRandomArray(n, n);
            SortingHelper.sortTest("SelectionSort", arr);
        }
    }
}

在这里插入图片描述

由上图中可看出,当数值增大10倍时,测试时间增大了100倍,从而验证了该算法O(n^2)的时间复杂度


五、本篇小结

本篇文章主要介绍了 选择排序法,我们通过实现 最基本的选择排序算法、使用带约束的泛型、使用 Comparable 接口等 多角度的理解了该算法

之后我们通过对 一万条和十万条 数据的测试,验证了其时间复杂度为 O(n^2)

下一节,我们学习排序基础里面的 插入排序法。

好啦,本篇文章到这里就要和大家说再见啦,祝你这篇文章阅读愉快,你下篇文章的阅读愉快留着我下篇文章再祝!


参考资料:

  1. 百度百科 · Java
  2. 算法与数据结构体系【作者:bobo】

在这里插入图片描述

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

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

相关文章

镇魂街武神躯手游攻略,镇魂街武神躯神魂搭配

武神躯是《镇魂街》手游中令人敬畏的角色之一&#xff0c;技能的合理搭配至关重要。下面将详细介绍镇魂街武神躯手游攻略如何搭配武神躯的技能以取得最佳战斗效果&#xff1a; 关注【娱乐天梯】&#xff0c;获取内部福利号 1. 主动技能-刺客之心&#xff1a;这是武神躯的核心主…

python 桌面软件开发-matplotlib画图鼠标缩放拖动

继上一篇在 Java 中缩放拖动图片后&#xff0c;在python matplotlib中也来实现一个自由缩放拖动的例子&#xff1a; python matplotlib 中缩放&#xff0c;较为简单&#xff0c;只需要通过设置要显示的 x y坐标的显示范围即可。基于此&#xff0c;实现一个鼠标监听回调&#xf…

python安装的第三方库

安装第三方库的方式 先按“winR”并输入 cmd 打开命令运行窗口 输入命令&#xff1a; pip install 包名&#xff0c;比如要安装gym包就输入pip install gym 可能存在报错问题及解决办法 报错Could not fetch URL https://pypi.tuna.tsinghua.edu.cn/simple/pip/: There was …

基于Java的美食推荐管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09; 代码参考数据库参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

SparkSQL的Shuffle分区设定及异常数据处理API(去重、缺失值处理)

一、Spark SQL的Shuffle分区数目设定 在允许spark程序时&#xff0c;查看WEB UI监控页面发现&#xff0c;某个Stage中有200个Task任务&#xff0c;也就是说RDD有200分区Partion。 产生原因&#xff1a; 在Spark SQL中&#xff0c;当Job中产生Shuffle时&#xff0c;默认的分区数…

Android乐器在线租借租赁系统+全套手把手视频教程

【项目功能介绍】 功能列表: 本系统包含后台管理和前端app双端系统, 本系统包含三个角色: 管理员,员工,app用户。 后台管理员的功能包含: 登录, 退出, 乐器管理,添加乐器,修改乐器,禁用启用乐器; 乐器器械管理,添加乐器器械,修改乐器器械,启用禁用乐器器械; 订单管理,确定订单…

Node学习笔记之fs模块

fs 全称为 file system &#xff0c;称之为 文件系统 &#xff0c;是 Node.js 中的 内置模块 &#xff0c;可以对计算机中的磁盘进行操 作。 本章节会介绍如下几个操作&#xff1a; 文件写入文件读取文件移动与重命名文件删除文件夹操作查看资源状态 一、文件写入 文件写入就…

Vercel,建站者的福音!!!

前言 各位互联网精神股东大家好&#xff01; 在今年八九月份之前&#xff0c;我所搭建的杂七杂八的个人、团队应用&#xff0c;包括但不限于文档站&#xff0c;博客站&#xff0c;Api服务&#xff0c;线上项目等&#xff0c;他们背后的服务支持可以归纳为以下几种&#xff1a…

Arduion 驱动 ADXL335三轴加速度计模块

Arduion 驱动 ADXL335三轴加速度计模块 简介电气参数原理图接线代码实验结果 简介 ADXL335是一个小&#xff0c;薄&#xff0c;低功率&#xff0c;完整的三轴加速度计&#xff0c;具有信号调节电压输出。该产品测量加速度的最小全尺度范围为3 g。它可以测量倾斜传感应用中重力…

【微信小程序开发】之微信授权登陆

目录 前言 ​编辑一、微信授权登陆介绍 1. 基本概念 2. 微信小程序开发实现微信授权登陆原理流程 3. 小程序中运用微信授权登陆的好处 二、微信授权登陆接口演示 1. 在微信开发工具中导入小程序授权微信登陆前端项目 2. 微信授权登陆的方式 2.1 wx.login 2.2 wx.getUse…

提高查询性能的秘密:深入剖析聚集、辅助、覆盖和联合索引

文章目录 &#x1f34a; 聚集索引&#x1f34a; 辅助索引&#x1f34a; 覆盖索引&#x1f389; 覆盖索引是什么&#xff1f;&#x1f389; 什么情况下优化器会选择使用覆盖索引&#xff1f;&#x1f4dd; 1. 查询操作只需要用到辅助索引中的字段&#x1f4dd; 2. 进行统计操作时…

使用Java实现汉诺塔问题~

我们设A为起始柱子&#xff0c;B为辅助柱子&#xff0c;C为目标柱子 由于盘子只能是大的放在下面&#xff0c;小的放在上面&#xff0c;因此&#xff0c;我们需要先将A柱子除了最下层的盘子都移动至B柱子 如下所示完成了最下层柱子到达它的最终位置&#xff0c;接下来&#xf…

Git(一)Windows下安装及使用Git Bash

目录 一、简介1.1 什么是Git&#xff1f;1.2 Git 的主要特点1.3 什么是 Git Bash&#xff1f; 二、下载三、安装3.1 同意协议3.2 选择安装位置3.3 其他配置&#xff08;【Next】 即可&#xff09;3.4 安装完毕3.5 打开 Git Bash 官网地址&#xff1a; https://www.git-scm.com/…

【React Router】React Router学习笔记

React Router学习笔记 React Router1.什么是React Router?2.为什么要用React Router?3.基础3.1 路由配置3.2 路由匹配原理3.3 History3.3.1 browerHistory3.3.2 hashHistory3.3.3 createMemoryHistory3.3.4 实现示例 3.4 默认路由(IndexRoute)与IndexLink3.4.1 IndexRoute3.4…

javaEE -6(10000详解文件操作)

一&#xff1a;认识文件 我们先来认识狭义上的文件(file)。针对硬盘这种持久化存储的I/O设备&#xff0c;当我们想要进行数据保存时&#xff0c;往往不是保存成一个整体&#xff0c;而是独立成一个个的单位进行保存&#xff0c;这个独立的单位就被抽象成文件的概念&#xff0c…

畅行全球,美格智能SLM750模组锻造出海核心优势

什么是产品认证制度&#xff1f; 国际标准化组织&#xff08;ISO&#xff09;将产品认证定义为&#xff1a;由第三方通过检验评定企业的质量管理体系和样品型式试验来确认企业的产品、过程或服务是否符合特定要求&#xff0c;是否具备持续稳定地生产符合标准要求产品的能力&am…

蓝桥每日一题(day 5: 蓝桥593.既约分数)--数学--easy(注:排掉一个重复的情况)

考察gcd模板求解最大公约数。由于我是2去做的&#xff0c;实际上当ij1的时候&#xff0c;能构成的分数只能是一种情况&#xff0c;所以最后的res需要减去1&#xff01;&#xff01;&#xff01; #include <iostream> using namespace std;int gcd(int a, int b){return …

【Bayes-LSTM预测】基于贝叶斯优化算法优化长短期记忆网络的数据分类预测研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

建材物料经营小程序商城的作用是什么

对商家而言&#xff0c;入驻到第三方平台&#xff0c;除了受平台各种限制外&#xff0c;还有佣金/抽成等&#xff0c;也不利于打造私域流量池及会员管理、营销、转化、复购裂变留存等&#xff0c;只能依赖平台活动进行经营。 如今线下流量匮乏及难获取&#xff0c;发传单口口相…

【算法设计】递归与分治算法设计——二分搜索、假币识别问题(C++实现)

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 更多算法分析与设计知识专栏&#xff1a;算法分析&#x1f525; 给大家跳…