排序算法(Java实现)

1. 冒泡排序

    冒泡排序属于交换排序。效率较低,适用小规模数据集。

    原理:循环遍历要排序的元素,依次比较两个相邻的元素,每次循环都找到一个最大(或最小)的数放到最后(或最前)。没有相邻元素需要交换时,说明已经排序完成。

    它是稳定排序 (即相等的两个元素,在排序后相对位置不会发生变化)。

public static void bubbleSort(int[] arrData) {int temp;int count = 0;//控制循环次数for (int i = 0; i < arrData.length - 1; ++i) {for (int j = 0; j < arrData.length - 1 - i; ++j) {++count;if (arrData[j] > arrData[j + 1]) {temp = arrData[j];arrData[j] = arrData[j + 1];arrData[j + 1] = temp;}}}System.out.println("比较次数:" + count);}

改进算法1,记录本此循环有无数据交换,若无则表示数据已经有序,跳出循环。

public static void bubbleSort1(int[] arrData) {int temp;int count = 0;boolean noChange;//控制循环次数for (int i = 0; i < arrData.length - 1; ++i) {noChange = true;for (int j = 0; j < arrData.length - 1 - i; ++j) {++count;if (arrData[j] > arrData[j + 1]) {temp = arrData[j];arrData[j] = arrData[j + 1];arrData[j + 1] = temp;noChange = false;}}if (noChange) {break;}}System.out.println("比较次数:" + count);}

改进算法2,改进算法1加上记录本次循环比较交换的最后位置,后面的元素是有序的,下次循环无需再比较最后位置元素之后的数据。

public static void bubbleSort2(int[] arrData) {int temp;int count = 0;boolean noChange;int lastPos = arrData.length - 1;int comparePos = 0;//控制循环次数for (int i = 0; i < arrData.length - 1; ++i) {noChange = true;for (int j = 0; j < lastPos; ++j) {++count;if (arrData[j] > arrData[j + 1]) {temp = arrData[j];arrData[j] = arrData[j + 1];arrData[j + 1] = temp;noChange = false;comparePos = j;}}lastPos = comparePos;if (noChange) {break;}}System.out.println("比较次数:" + count);}

对数据{19,25,1,30,12,8,26,24,40,72},bubbleSort的比较次数为45次,bubbleSort1的比较次数为35次,bubbleSort2的比较次数为25次。

2. 快速排序

    快速排序属于交换排序。基于分而治之策略,效率稍高。

    原理:每一趟排序将数据分割成左右两部分,其中左边的数据都比右边的数据小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程递归进行,最终整个数据变成有序。

    它是不稳定排序 (即相等的两个元素,在排序后相对位置可能发生变化)。

public static void quickSort(int[] arrData, int left, int right) {if (left > right) {return;}//基准数int base = arrData[left];int i = left;int j = right;while (true) {//要先从右向左找while (i < j && base <= arrData[j]) {--j;}while (i < j && base >= arrData[i]) {++i;}if (i >= j) break;int temp = arrData[i];arrData[i] = arrData[j];arrData[j] = temp;}//将基准数和小的数交换arrData[left] = arrData[i];arrData[i] = base;//左边排序quickSort(arrData, left, i - 1);//右边排序quickSort(arrData, j + 1, right);}
3. 直接插入排序

    直接插入排序属于插入排序。适合数据个数小于20个的数据集。

    原理:将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增1的有序表。一开始有序表就只有第一个数。

   public static void insertSort(int[] arrData) {//一开始有序表只有第一个数for (int i = 1; i < arrData.length; ++i) {//当前数比前一个小if (arrData[i] < arrData[i - 1]) {int temp = arrData[i];//保存当前数int j;//查找有序表里的插入位置for (j = i - 1; j >= 0 && temp < arrData[j]; --j) {arrData[j + 1] = arrData[j];//将前面的大数后移一格}arrData[j + 1] = temp;//System.out.println(Arrays.toString(arrData));}}}
4. 希尔排序

    希尔排序属于插入排序,又称“缩小增量排序”,是直接插入排序更高效的改进版本。

    原理:把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至 1 时,整个文件恰被分成一组,算法便终止。

public static void shellSort(int[] arrData) {//遍历所有的步长for(int d = arrData.length/2; d > 0; d /= 2 ){//遍历所有元素for(int i = d; i < arrData.length; i++){//遍历本组中所有元素for(int j = i-d; j >= 0; j -= d){//如果当前元素大于加上步长后的那个元素if(arrData[j] > arrData[j+d]){int temp = arrData[j];arrData[j] = arrData[j+d];arrData[j+d] = temp;}}}}}
5. 选择排序

    原理:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。

public static void selectSort(int[] arrData){for(int i=0;i<arrData.length;++i){int minIndex = i;//把当前遍历的数和后面所有数依次进行比较,并记录最小数下标for(int j=i+1;j<arrData.length;++j){if(arrData[minIndex]>arrData[j]){minIndex = j;}}//如果最小的数和当前遍历的数下标不一致,说明下标为minIndex的数比当前遍历的数更小if(i != minIndex){int temp = arrData[i];arrData[i] = arrData[minIndex];arrData[minIndex] = temp;}}}

6. 归并排序

    归并排序是建立在归并操作上的一种有效,稳定的排序算法。

    原理:将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。也是基于分而治之策略。

public static int[] mergeSort(int[] arrData, int low, int high) {if (low == high) {return new int[]{arrData[low]};}int mid = low + (high - low) / 2;int[] leftArrData = mergeSort(arrData, low, mid); //左有序数组int[] rightArrData = mergeSort(arrData, mid + 1, high); //右有序数组int[] newOut = new int[leftArrData.length + rightArrData.length]; //新有序数组int m = 0, i = 0, j = 0;while (i < leftArrData.length && j < rightArrData.length) {newOut[m++] = leftArrData[i] <= rightArrData[j] ? leftArrData[i++] : rightArrData[j++];}while (i < leftArrData.length)newOut[m++] = leftArrData[i++];while (j < rightArrData.length)newOut[m++] = rightArrData[j++];return newOut;}

7. 桶排序

    桶排序(箱排序)是一种分布式排序。

    原理:将数据转换为另一种形式排序。通常用数组来表示每个桶,用原数据的值表示桶的索引。是一种空间换时间的算法。

public static void bucketSort(int[] arrdata) {//注意数据需都>=0int max = getMaxOne(arrdata);int[] bucket = new int[max + 1];for (int i = 0; i < arrdata.length; ++i) {bucket[arrdata[i]]++;//计数}int pos = 0;for (int i = 0; i < bucket.length; ++i) {for (int j = 0; j < bucket[i]; ++j) {//同一个位置可能有几个相同数据值arrdata[pos++] = i;//i是原数据值}}}static int getMaxOne(int[] arrData) {int max = arrData[0];for (int i = 1; i < arrData.length; ++i) {if (arrData[i] > max) {max = arrData[i];}}return max;}

8. 基数排序

    基数排序(radix sort)属于“分布式排序”(distribution sort)。也是用空间换时间的算法。

    原理:透过键值的部份信息,将要排序的元素分配至某些“桶”中,以达到排序的作用。如对整数数列排序中,先以个位为key分组,然后合并;再以十位为key分组,合并;以此类推,直到最大数的最高位。

public static void radixSort(int[] arrData) {//d表示最大数字的位数有多少位int d = getLen(getMaxOne(arrData));int k = 0;int n = 1; //作除数int m = 1; //控制键值排序依据在哪一位,从第一位即个位开始int[][] temp = new int[10][arrData.length]; //数组的第一维表示可能的余数0-9int[] order = new int[10]; //数组order[i]用来表示该位是i的数的个数while (m <= d) {//根据余数来分组for (int i = 0; i < arrData.length; i++) {int lsd = ((arrData[i] / n) % 10);temp[lsd][order[lsd]] = arrData[i];order[lsd]++;}//合并分组for (int i = 0; i < 10; i++) {if (order[i] != 0) {for (int j = 0; j < order[i]; j++) {arrData[k] = temp[i][j];k++;}}order[i] = 0;}n *= 10;//作除数k = 0;m++;//位数+1}}static int getMaxOne(int[] arrData) {int max = arrData[0];for (int i = 1; i < arrData.length; ++i) {if (arrData[i] > max) {max = arrData[i];}}return max;}static int getLen(int v) {return (v + "").length();}

9. 堆排序

    原理:堆排序首先要构造堆结构。堆结构是一个完全二叉树。完全二叉树指的是,若设二叉树的深度为n,除第 n 层外,其它各层 (1~n-1) 的结点数都达到最大个数,第 n 层所有的结点都连续集中在最左边。完整的堆排序经过反复的两个步骤:构造堆结构和堆排序输出(根节点)。

 public static void heapSort(int[] arrData) {int size = arrData.length;int i;//将n个元素建堆for (i = size / 2 - 1; i >= 0; i--) {//只需循环非叶节点heapCompare(arrData, i, size);}int k, t;for (i = size - 1; i > 0; i--) {//根节点为最大值,放到数组后面t = arrData[0];arrData[0] = arrData[i];arrData[i] = t;k = 0;heapCompare(arrData, k, i);}}static void heapCompare(int[] arrData, int i, int total) {//i为非叶节点int j;while (2 * i + 1 < total) {//第i个节点有子树j = 2 * i + 1; //左子节点if ((j + 1) < total) {//存在右子节点if (arrData[j] < arrData[j + 1])//若左边小于右边j++;//指向右子节点}if (arrData[i] < arrData[j]) {//j为 i节点的子节点int t = arrData[i]; //交换数据arrData[i] = arrData[j];arrData[j] = t;i = j;//堆被破坏,需重新调整子树} else {//堆未破坏,无需调整break;}}}

10. 数据比较

稳定?原地?最好最坏平均空间说明
冒泡排序O(n)O(n²)O(n²)O(1)
插入排序O(n)O(n²)O(n²)O(1)
归并排序O(nLogn)O(nLogn)O(nLogn)O(n)需额外空间
桶排序O(n+k)O(n²)O(n²)O(n*k)k为桶总数
基数排序O(d(n+r))O(d(n+r))O(d(n+r))O(n+r)d是关键码个数,r为关键码的最大值
快速排序O(nLogn)O(n²)O(nLogn)O(Logn)
希尔排序O(n)O(n²)O(nLogn)O(1)
选择排序O(n²)O(n²)O(n²)O(1)最低效
堆排序O(nLogn)O(nLogn)O(nLogn)O(1)

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

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

相关文章

GitLab-访问返回403 forbidden问题处理

访问gitlab时报错forbidden 一般访问量大&#xff0c;密码错误频率高的时候&#xff0c;gitlab防爆机制启动了&#xff0c;对IP做了封禁&#xff0c;导致某些IP访问的是否返回 403 forbidden 1. 查看被封的IP /opt/gitlab/embedded/bin/redis-cli -s /var/opt/gitlab/redis/red…

和硕首次参加展OCP 峰会,将发布多项AI合作项目产品 | 百能云芯

电子代工大厂和硕联合科技宣布&#xff0c;将参与今年的 OCP 全球峰会 (OCP Global Summit)&#xff0c;展示与英伟达 (NVIDIA) 合作成果&#xff0c;包含使用英伟达 GH200 Grace Hopper 超级芯片的 MGX AI 服务器&#xff0c;以及搭载 A100、L40 等服务器产品。 OCP 峰会于 10…

自动化RPA开发 --获取所有窗口信息和进程信息

场景 准备做一个RPA工具&#xff0c;可以从桌面和浏览器选择元素&#xff0c;获取窗口信息和进程信息是必要的&#xff0c;因为获取了窗口信息和进程&#xff0c;可用对程序做一些想要的操作。 coding 工具类 /*** Windows系统工具类*/ public class WinOsUtils {static fi…

Everything和SVN结合使用-在Everything中显示SVN

点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册点击跳转>Scratch编程案例点击跳转>软考全系列 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&…

智能加压站远程监控与维护,提高小区供水效率与安全性的创新方案

不知道大家有没有遇到过这样的情况&#xff1a;当你在家中使用水龙头接水时&#xff0c;突然水管的水流就逐渐变细直到消失。正当你震惊带着一丝疑惑是否停水的时候&#xff0c;水流又开始由细变粗&#xff0c;仿佛在和你开玩笑一样。 实际上&#xff0c;这种情况的出现通常是由…

Angular安全专辑之五 —— 防止URL中敏感信息泄露

URL 中的敏感数据是指在网址上的机密或者个人信息&#xff0c;包括 UserId, usernames, passwords, session, token 等其他认证信息。 由于URL 可能会被第三方拦截和查看&#xff08;比如互联网服务商、代理或者其他监视网络流量的攻击者&#xff09;&#xff0c;所以URL中的敏…

Maika 与越南童模们受邀请参加中国上海时装周 hanakimi 品牌开幕

金风送爽&#xff0c;秋高气和。2024中国上海时装周以“活力互链”为主题&#xff0c;于10月8日正式启幕。 魅力四射的越南童模身着著名时尚品牌MLB、Hana Kami、Jacadi的精美设计&#xff0c;迈着有力、专业但又不失优雅的步伐走上时尚舞台上海大型现场。无论是拍摄造型照还是…

如何使用 Disco 将黑白照片彩色化

Disco 是一个基于视觉语言模型&#xff08;LLM&#xff09;的图像彩色化工具。它使用 LLM 来生成彩色图像&#xff0c;这些图像与原始黑白图像相似。 本文将介绍如何使用 Disco 将黑白照片彩色化。 使用 Disco 提供了一个简单的在线演示&#xff0c;可以用于测试模型。 访问…

14Maven与Tomcat面试题

1MAVEN Maven是一个基于项目对象模型&#xff08;POM&#xff09;的项目管理工具&#xff0c;它可以帮助开发者自动化构建、依赖管理、项目报告等。Maven通过一个中央信息片段能够管理项目的构建、报告和文档等步骤&#xff0c;同时也能够管理项目的依赖。Maven的核心概念是POM…

五、WebGPU Vertex Buffers 顶点缓冲区

五、WebGPU Vertex Buffers 顶点缓冲区 在上一篇文章中&#xff0c;我们将顶点数据放入存储缓冲区中&#xff0c;并使用内置的vertex_index对其进行索引。虽然这种技术越来越受欢迎&#xff0c;但向顶点着色器提供顶点数据的传统方式是通过顶点缓冲和属性。 顶点缓冲区就像任…

SpringBoot实战(二十五)集成 Shiro

目录 一、Shiro 简介1.1 Shiro 定义1.2 Shiro 核心组件1.3 Shiro 认证过程 二、SpringBoot集成2.1 集成思路2.2 Maven依赖2.3 自定义 Realm2.4 Shiro 配置类2.5 静态资源映射2.6 AuthController2.7 User 实体2.8 用户接口类2.9 用户接口实现类2.10 OrderController&#xff08;…

SpringBoo整合WebSocket实战演练——Java入职十三天

前言 本文将介绍如何在Spring Boot应用程序中使用WebSocket实现服务端向客户端推送消息。Spring Boot和WebSocket的整合实现服务端向客户端推送消息,使得客户端能够实时接收并处理服务器发来的信息。WebSocket协议是一种双向通信的网络协议,使得客户端和服务器能够建立持久连…

List小练习,实现添加图书,并且有序遍历

SuppressWarnings({"all"})public static void main(String[] args) {List list new LinkedList(); // List list new Vector(); // List list new ArrayList();list.add(new Book1("红楼小梦",35.5,"曹雪芹"));list.add(new B…

Mysql数据库 1. SQL基础语法和操作

一、Mysql逻辑结构 一个数据库软件可以包含许多数据库 一个数据库包含许多表 一个表中包含许多字段&#xff08;列&#xff09; 数据库软件——>数据库——>数据表——>字段&#xff08;列&#xff09;、元组&#xff08;行&#xff09; 二、SQL语言基础语法 1.SQL…

ROS2的cv_bridge库opencv版本不匹配问题

1. 问题 /usr/bin/ld: warning: libopencv_imgcodecs.so.4.2, needed by /opt/ros/foxy/lib/libcv_bridge.so, may conflict with libopencv_imgcodecs.so.4.5/usr/bin/ld: warning: libopencv_core.so.4.2, needed by /opt/ros/foxy/lib/libcv_bridge.so, may conflict with …

git远程仓库、开发者使用流程、ssh连接

git远程仓库 https://www.cnblogs.com/liuqingzheng/p/15328319.html 远程仓库有&#xff1a; : github gitlab gitee 在gitee上创建了仓库 &#xff08;确保仓库是空的&#xff09;本地&#xff1a;git init本地&#xff1a;git commit -m 提交版本指定远程仓库地址 添加一…

滚雪球学Java(53):从入门到精通:SimpleDateFormat类高深用法,让你的代码更简洁!

咦咦咦&#xff0c;各位小可爱&#xff0c;我是你们的好伙伴——bug菌&#xff0c;今天又来给大家普及Java SE相关知识点了&#xff0c;别躲起来啊&#xff0c;听我讲干货还不快点赞&#xff0c;赞多了我就有动力讲得更嗨啦&#xff01;所以呀&#xff0c;养成先点赞后阅读的好…

STM32如何使用中断?

一&#xff1a;EXTI 简介 STM32F10x 外部中断/事件控制器&#xff08;EXTI&#xff09;包含多达 20 个用于产生事件/中断请求的边沿检测器。 EXTI 的每根输入线都可单独进行配置&#xff0c;以选择类型&#xff08;中断或事件&#xff09;和相应的触发事件&#xff08;上升 沿触…

易点易动设备管理系统:提升生产企业设备保养效率的利器

在现代生产企业中&#xff0c;设备保养是确保生产线稳定运行和产品质量的关键环节。然而&#xff0c;传统的设备保养方式往往面临效率低下、数据不准确等问题&#xff0c;影响了生产效率和竞争力。随着科技的进步&#xff0c;易点易动设备管理系统应运而生&#xff0c;以其智能…

【学一点儿前端】ajax、axios和fetch的概念、区别和易混淆点

省流读法 ajax是js异步技术的术语&#xff0c;早期相关的api是xhr&#xff0c;它是一个术语。 fetch是es6新增的用于网络请求标准api&#xff0c;它是一个api。 axios是用于网络请求的第三方库&#xff0c;它是一个库。 1.Ajax 它的全称是&#xff1a;Asynchronous JavaScri…