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

news/2024/5/20 7:22:32/文章来源:https://blog.csdn.net/qq_45902692/article/details/133998498

个人简介

👀个人主页: 前端杂货铺
🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展
📃个人状态: 研发工程师,现效力于中国工业软件事业
🚀人生格言: 积跬步至千里,积小流成江海
🥇推荐学习:🍍前端面试宝典 🍉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;}@Overridepublic int compareTo(Student another) {return this.score - another.score;}@Overridepublic 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.luyixian.cn/news_show_187775.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis底层核心数据结构详解

文章目录 一、深入String&#xff08;SDS&#xff09;1. 字符串简介2. SDS存在的意义3. SDS结构设计4. SDS与C字符串的区别4.1 常数复杂度获取字符串长度4.2 杜绝缓冲区溢出4.3 二进制安全4.4 SDS API 5 小结 二、深入List (QuickList)1. 链表节点结构设计2. Redis的链表实现的…

7.21 SpringBoot项目实战【图书借阅】并发最佳实践:细粒度Key锁、数据库乐观锁、synchronized、ReentrantLock

文章目录 前言一、编写服务层二、编写控制器三、并发实战1. synchronized关键字2. Lock 接口3. Atomic类4. 细粒度Key锁5. 数据库乐观锁6. 最终service完整代码 最后 前言 上文的产品设计流程&#xff1a;查看图书列表 7.3 实现-》查看图书详情上文7.20 -》图书借阅(本文)。 就…

【深圳1024开发者城市聚会定向征文】

在这个周末&#xff0c;我有幸参加了1024程序员节活动&#xff0c;这是一个专门为程序员们举办的活动&#xff0c;旨在庆祝程序员这个特殊的群体。在这个活动中&#xff0c;我不仅感受到了浓厚的编程氛围&#xff0c;还收获了许多宝贵的经验和知识。 活动在深圳湾科技生态园举…

Leetcode周赛368补题(3 / 3)

目录 1、元素和最小的山型三元组 | - 三层for暴力循环 2、元素和最小的山型三元组 || - 维护前后最小值 遍历 3、合法分组的最少组数 - 思维 哈希表 1、元素和最小的山型三元组 | - 三层for暴力循环 100106. 元素和最小的山形三元组 I class Solution {public int minimu…

Apache Doris (四十六): Doris数据更新与删除 - 批量删除

🏡 个人主页:IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 🚩 私聊博主:加入大数据技术讨论群聊,获取更多大数据资料。 🔔 博主个人B栈地址:豹哥教你大数据的个人空间-豹哥教你大数据个人主页-哔哩哔哩视频 目录

#电子电器架构 —— 车载网关初入门

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 PS:小细节,本文字数7000+,详细描述了网关在车载框架中的具体性能设置。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 没有人关注你。也无需有人关注你。你必须承认自己的价值,你不能站在他…

51单片机实现换能器超声波测水深

一&#xff0c;超声波换能器定义&#xff1a; 定义1&#xff1a;可把电能、机械能或声能从一种形式转换为另一种形式的能的装置。 所属学科&#xff1a;测绘学下的测绘仪器。 定义2&#xff1a;能量转换的器件。在水声领域中常把声呐换能器、水声换能器、电声换能器统称换能器。…

博客后台模块续更(六)

十三、后台模块-用户列表 1. 查询用户 需要用户分页列表接口。 可以根据用户名模糊搜索。 可以进行手机号的搜索。 可以进行状态的查询。 1.1 接口分析 请求方式请求路径是否需求token头GETsystem/user/list是 请求参数query格式&#xff1a; pageNum: 页码pageSize…

【linux系统】如何在服务器上安装Anaconda

文章目录 1. 安装Anconda1.1. 下载Anaconda安装包1.2. 安装Anaconda1.2.1. 点击回车&#xff08;Enter&#xff09;1.2.2. 添加环境变量1.2.3. 激活环境变量 1.3. 检查是否安装成功 2. Anaconda安装pytorch2.1. 创建虚拟环境2.2. 激活(进入)虚拟环境2.3. 安装pytorch 1. 安装An…

C语言--程序环境和预处理(宏)

目录 前言 本章重点&#xff1a; 1. 程序的翻译环境和执行环境 2. 详解编译链接 2.1 翻译环境​编辑 2.2 编译本身也分为几个阶段 2.3 运行环境 3. 预处理详解 3.1 预定义符号 3.2 #define 3.2.1 #define 定义标识符 3.2.2 #define 定义宏 2.2.3 #define 替换规则 …

Mock测试详细教程入门这一篇就够了!

1、什么是mock测试 1.png Mock测试就是在测试活动中&#xff0c;对于某些不容易构造或者不容易获取的比较复杂的数据/场景&#xff0c;用一个虚拟的对象(Mock对象)来创建用于测试的测试方法。 2、为什么要进行Mock测试 Mock是为了解决不同的单元之间由于耦合而难于开发、测试…

高校教务系统登录页面JS分析——西安交通大学

高校教务系统密码加密逻辑及JS逆向 本文将介绍高校教务系统的密码加密逻辑以及使用JavaScript进行逆向分析的过程。通过本文&#xff0c;你将了解到密码加密的基本概念、常用加密算法以及如何通过逆向分析来破解密码。 本文仅供交流学习&#xff0c;勿用于非法用途。 一、密码加…

Android手机连接电脑弹出资源管理器

如图所示&#xff0c;很讨厌 关闭方法&#xff1a;

Node编写用户登录接口

目录 前言 服务器 编写登录接口API 使用sql语句查询数据库中是否有该用户 判断密码是否正确 生成JWT的Token字符串 配置解析token的中间件 配置捕获错误中间件 完整的登录接口代码 前言 本文介绍如何使用node编写登录接口以及解密生成token&#xff0c;如何编写注册接…

ROI的投入产出比是什么?

ROI的投入产出比是什么&#xff1f; 投入产出比&#xff08;Return on Investment, ROI&#xff09;是一种评估投资效益的财务指标&#xff0c;用于衡量投资带来的回报与投入成本之间的关系。它的计算公式如下&#xff1a; 投资收益&#xff1a;指的是投资带来的净收入&#x…

Python基础入门例程2-NP2 多行输出

描述 将字符串 Hello World! 存储到变量str1中&#xff0c;再将字符串 Hello Nowcoder! 存储到变量str2中&#xff0c;再使用print语句将其打印出来&#xff08;一行一个变量&#xff09;。 输入描述&#xff1a; 无 输出描述&#xff1a; 第一行输出字符串Hello World!&a…

DDOS直接攻击系统资源

DDOS ——直接攻击系统资源 思路&#xff1a; 攻击机利用三次握手机制&#xff0c;产生大量半连接&#xff0c;挤占受害者系统资源&#xff0c;使其无法正常提供服务。 1、先体验下受害者的正常网速。在受害者主机上执行以下命令 (1)开启Apache。 systemctl start apache2 (2…

SysTick—系统定时器

SysTick 简介 SysTick—系统定时器是属于CM3内核中的一个外设&#xff0c;内嵌在NVIC中。系统定时器是一个24bit 的向下递减的计数器&#xff0c;计数器每计数一次的时间为1/SYSCLK&#xff0c;一般我们设置系统时钟SYSCLK 等于72M。当重装载数值寄存器的值递减到0的时候&#…

LeetCode刷题---简单组(一)

文章目录 &#x1f352;题目一 507. 完美数&#x1f352;解法一 &#x1f352;题目二 2678. 老人的数目&#x1f352;解法一 &#x1f352;题目三 520. 检测大写字母&#x1f352;解法一&#x1f352;解法二 &#x1f352;题目一 507. 完美数 对于一个 正整数&#xff0c;如果它…

一文教你学会使用Cron表达式定时备份MySQL数据库

各位小伙伴大家好&#xff0c;今天我就来讲述一下作为一个运维&#xff0c;如何解放自己的双手去让服务器定时备份数据库数据&#xff0c;防止程序操作数据库出现数据丢失。 mysql_dump_script.sh脚本文件 #!/bin/bash#保存备份个数&#xff0c;备份7天数据 number7 #备份保存…