常见的排序算法

前言

算法对于我们普通的工程师来说可算得上陌生又熟悉,因为在平时的业务代码中可能见到他的身影比较少,但在底层的代码中我们可能会经常发现排序算法的影子,如数据库索引,操作系统的进程调度。因此,掌握这种算法中的思想还是致关重要,今天大猿就带大家来实战一下基础的排序算法,加强记忆。

常见的排序分类

在这里插入图片描述

直接插入排序

先直接上代码:

    public static void insertSort2(int [] arr){for (int i = 1; i < arr.length; i++) {int key = arr[i];int j=i-1;for ( ; j >= 0 ; j--) {if(key < arr[j]){arr[j + 1] = arr[j];}else {break;}}arr[j + 1] = key;}StringBuffer stringBuffer = new StringBuffer();for (int j : arr) {stringBuffer.append(",").append(j);}System.out.println(stringBuffer);}public static void main(String[] args) {int [] arr = {345,23,79,54,67,666,23,78,2,22,985};//   insertSort(arr);insertSort2(arr);}

运行结果

在这里插入图片描述

复杂度

时间复杂度

运行复杂度,当整个序列基本有序的情况下此时插入排序将出现最好情况 O(n) , 这个也不难想象,当整个排序序列基本有效时,比较只需要n次,内部循环几乎可以不执行。
对于一般情况时间复杂度是O(n^2);

空间复杂度

因为在程序执行过程中,我们只用一个一个临时存储变量,所以空间复杂度为O(1);

稳定性

该算法是稳定算法,如何理解稳定性呢?稳定性最直白的理解就是如果出现相同元素的时候,看原来的序列是否遭到破坏。

希尔排序

上代码,

    public static void main(String[] args) {int[] arr = new int[100];for (int i = 0; i < 100; i++) {arr[i] = (int) (Math.random() *100);}shellSort(arr);}public static void shellSort(int [] arr){for (int gap = arr.length /2; gap>0; gap /=2){for(int i = gap; i < arr.length ; i ++){int temp = arr[i];int j=i - gap;for( ; j >= 0; j -= gap){if(arr[j] < temp){arr[j+gap]=arr[j];}else {break;}}arr[j+gap] = temp;}}StringBuffer stringBuffer = new StringBuffer();for (int j : arr) {stringBuffer.append(",").append(j);}System.out.println(stringBuffer);}

运行结果

在这里插入图片描述

复杂度

时间复杂度

希尔排序可以理解为特殊的插入排序,最好和最坏时间复杂度基本与插入排序保持一致。软设上给出的平均复杂度为O(n^1.3) 有兴趣的同学可以去研究一下理论。

空间复杂度

空间复杂度基本与插入排序是一致的。

稳定性

该算法为非稳定算法。

计数排序

代码

    public static int[] countSort(int[] array) {//1.得到数列的最大值int max = array[0];for(int i=1; i<array.length; i++){if(array[i] > max){max = array[i];}}//2.根据数列最大值确定统计数组的长度int[] countArray = new int[max+1];//3.遍历数列,填充统计数组for(int i=0; i<array.length; i++){countArray[array[i]]++;}//4.遍历统计数组,输出结果int index = 0;int[] sortedArray = new int[array.length];for(int i=0; i<countArray.length; i++){for(int j=0; j<countArray[i]; j++){sortedArray[index++] = i;}}return sortedArray;}public static int[] countSortV2(int[] array) {//1.得到数列的最大值和最小值,并算出差值dint max = array[0];int min = array[0];for(int i=1; i<array.length; i++) {if(array[i] > max) {max = array[i];}if(array[i] < min) {min = array[i];}}int d = max - min;//2.创建统计数组并统计对应元素个数int[] countArray = new int[d+1];for(int i=0; i<array.length; i++) {countArray[array[i]-min]++;}//3.统计数组做变形,后面的元素等于前面的元素之和for(int i=1;i<countArray.length;i++) {countArray[i] += countArray[i-1];}//4.倒序遍历原始数列,从统计数组找到正确位置,输出到结果数组int[] sortedArray = new int[array.length];for(int i=array.length-1;i>=0;i--) {sortedArray[countArray[array[i]-min]-1]=array[i];countArray[array[i]-min]--;}return sortedArray;}public static void main(String[] args) {int[] array = new int[] {4,4,6,5,3,2,8,1,7,5,6,0,10};int[] sortedArray = countSort(array);System.out.println(Arrays.toString(sortedArray));array = new int[] {95,94,91,98,99,90,99,93,91,92};sortedArray = countSortV2(array);System.out.println(Arrays.toString(sortedArray));}

运行结果

在这里插入图片描述

时间复杂度

计数排序的时间复杂度为O(n+k),其中n是待排序序列的长度,k是待排序序列中的最大值,注意计算时间复杂度时只是考虑了构造统计数组的最大长度k和

空间复杂度

计数排序的空间复杂度为O(k)。

稳定性

该算法是一个稳定算法,对于数的范围不大,但是算量很多的情况非常实用。

选择排序

继续先上代码

    public static void selectSort(int [] arr){int maxIndex =0;for (int i = 0; i < arr.length-1; i++) {for (int j = i; j <arr.length ; j++) {if(arr[maxIndex]<arr[j]){maxIndex =j;}}if(maxIndex != i){int temp =0;temp = arr[maxIndex];arr[maxIndex] = arr[i];arr[i] = temp;}}StringBuffer stringBuffer = new StringBuffer();for (int i = 0; i <arr.length; i++) {stringBuffer.append(",").append(arr[i]);}System.out.println(stringBuffer.toString());}public static void main(String[] args) {int [] arr = {345,23,79,54,67,666,23,78,2,22,985};selectSort(arr);}

运行结果

在这里插入图片描述

时间和空间复杂度

选择排序的时间复杂度为O(n^2) 空间复杂度为O(1)

稳定性

该算法为不稳定算法。

堆排序

堆排序稍微复杂点,先上个截图,至于具体理论的话请同学们自己去找教材或者视频,下面给出算法及代码
在这里插入图片描述

    public static void main(String[] args) {int arr [] ={1,10,3,2,6,5,7,9,8,0,4};heapSort(arr);System.out.println(Arrays.toString(arr));}/**** @param array*/private static  void heapSort(int []  array){//构建堆for (int i = (array.length-2)/2; i >=0; i--) {downAdjust(array,i,array.length);}System.out.println("-----------------------");System.out.println(Arrays.toString(array));//调整堆for (int i = array.length-1; i >0; i--) {int temp = array[i];array[i] = array[0];array[0] = temp;downAdjust(array,0,i);/*            if("UP".equals(cmd)){upAdjust(array);}*/}}/**** 节点下沉* @param arr* @param parentIndex* @param length*/private static void  downAdjust(int [] arr,int parentIndex , int length){int temp = arr[parentIndex];int childIndex = 2* parentIndex +1;while (childIndex < length){//定位到右孩子if(childIndex+1 < length && arr[childIndex+1]>arr[childIndex]){childIndex++;}if(temp > arr[childIndex]){break;}arr[parentIndex] = arr[childIndex];parentIndex = childIndex;childIndex = 2* childIndex+1;}arr[parentIndex] = temp;// System.out.println(Arrays.toString(arr));}

运行结果

在这里插入图片描述

复杂度及稳定性

堆排序是不稳定排序,其时间复杂度时O(nlog(2)n),空间复杂度为n+1;此外
该算法是非稳定算法。

冒泡排序

代码如下:

    public static void main(String[] args) {int [] arr = {345,23,79,54,67,666,23,78,2,22,985};bubbleSort(arr);}public static void  bubbleSort(int [] arr){for (int i = 0; i < arr.length; i++) {for (int j = 0; j < arr.length - i - 1; j++) {int temp = 0;if (arr[j] < arr[j+1]) {temp = arr[j];arr[j]=arr[j+1];arr[j+1] = temp;}}}StringBuffer stringBuffer = new StringBuffer();for (int i = 0; i <arr.length; i++) {stringBuffer.append(",").append(arr[i]);}System.out.println(stringBuffer.toString());}

运行结果

在这里插入图片描述

复杂度分析及稳定性分析

冒泡算法的复杂度为O(n^2) 空间复杂度为O(1),该算法为稳定的排序算法。

快速排序

主算法
在这里插入图片描述

    public static void main(String[] args) {int [] arr = {345,23,79,54,67,666,23,78,2,22,985};quickSort(arr,0,arr.length-1);StringBuffer stringBuffer = new StringBuffer();for (int i = 0; i <arr.length; i++) {stringBuffer.append(",").append(arr[i]);}System.out.println(stringBuffer.toString());}public static void quickSort(int [] arr, int start,int end){if(start > end){return;}int midIndex = partition(arr, start, end);quickSort(arr,start,midIndex-1);quickSort(arr,midIndex+1,end);}private static int partition(int[] arr, int start, int end) {int right = end;int left = start;int midValue = arr[left];while (left != right){while (left<right && midValue < arr[right]){right --;}// arr[left] = arr[right];while (left<right && midValue >= arr[left]){left ++;}//  arr[right] = arr[left];if(left < right){int temp =0;temp = arr[left];arr[left] = arr[right];arr[right] = temp;}}arr[start] = arr[right];arr[right] = midValue;return right;}

运行结果

在这里插入图片描述

复杂度分析

时间复杂度

快速排序的一般时间复杂度为 O(nlog(2)n) ,最坏的时间复杂度为O(n^2);

空间复杂度

递归算法的空间复杂度 = 每次递归的空间复杂度O(1) * 递归深度, 因为堆栈的深度就是快速排序的空间复杂度位O(log(2)n),最坏也就是O(n)

稳定性

快速排序为不稳定算法

归并排序

先上代码

    public static void main(String[] args) {int [] arr = {345,23,79,54,67,666,23,78,2,22,985};mergeSort(arr, 0, arr.length - 1);for (int i : arr) {System.out.print(i + " ");}}public static void mergeSort(int[] arr, int left, int right) {if (left < right) {int mid = (left + right) / 2;mergeSort(arr, left, mid);mergeSort(arr, mid + 1, right);merge(arr, left, mid, right);}}public static void merge(int[] arr, int left, int mid, int right) {int[] temp = new int[right - left + 1];int i = left;int j = mid + 1;int k = 0;while (i <= mid && j <= right) {if (arr[i] <= arr[j]) {temp[k++] = arr[i++];} else {temp[k++] = arr[j++];}}while (i <= mid) {temp[k++] = arr[i++];}while (j <= right) {temp[k++] = arr[j++];}for (int p = 0; p < temp.length; p++) {arr[left + p] = temp[p];}}

运行结果
在这里插入图片描述

时间复杂度

从上面的代码来看,其归并的深度为log(2)n 而每次合并的时间复杂度都为n,所以综合下来其时间复杂度为 n*log(2)n;

空间复杂度

因为归并需要额外的空间数组,其大小n

稳定性

该算法为稳定的排序算法,相同元素不改变原来的位置。

桶排序

桶排序的基本思想可以说是与计数排序有异曲同工之妙,由于篇幅原因,需要了解算法的具体实现的小伙伴可以自己去翻阅资料。

总结

  • 本文带大家实战了常见的排序算法,并给出了运行结果,其中采用 动态规划 思想的算法有 选择排序 ; 选择排序、冒泡排序和堆排序 都属于 贪心法,而 归并排序 采用了分治思想;希尔排序可以说是既采用了动态规划思想,又采用了分之思想快速排序既采用贪心算法,又吸收了分治思想
  • 对于不同场景我们可以采用不同的排序算法,从时间复杂度来看,快排,归并,堆排序是响应速度最快的三种常见排序方法,但所占空间都比较高;从空间复杂度来看,冒泡,插入,简单选择排序是应用空间最小的排序方法,但响应时间有点慢;复杂为线性的排序算法只有基数排序和桶排序,但该算法并不适合所有的应用场景,所以在实际应用大各位小伙伴要懂得权衡利弊,妥善处置。

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

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

相关文章

打造智能语音机器人-用语音控制机器人

人工智能现已成为国家发展重大战略&#xff0c;智能语音技术作为人工智能产业链上的关键一环&#xff0c;AI应用成熟的技术之一&#xff0c;人工智能的发展也进入了一个崭新的阶段。那么打造智能语音机器人怎样实现用语音控制机器人呢&#xff1f;和小编一起来看看。 选择合适的…

Xcode for Mac:强大易用的集成开发环境

Xcode for Mac是一款专为苹果开发者打造的集成开发环境&#xff08;IDE&#xff09;&#xff0c;它集成了代码编辑器、编译器、调试器等一系列开发工具&#xff0c;让开发者能够在同一界面内完成应用的开发、测试和调试工作。 Xcode for Mac v15.2正式版下载 Xcode支持多种编程…

如何将web content项目导入idea并部署到tomcat

将Web Content项目导入IntelliJ IDEA并部署到Tomcat主要涉及以下几个步骤&#xff1a; 1. 导入Web Content项目 打开IntelliJ IDEA。选择“File” -> “New” -> “Project from Existing Sources…”。浏览到你的Web Content项目的文件夹&#xff0c;并选择它。Intell…

1.C++入门(上)

目录 1.C关键字 2.命名空间 作用域方面的优化 a.命名空间定义 b.命名空间使用 3.C 输入&输出 1.C关键字 C有63个关键字&#xff0c;C语言有32个关键字&#xff0c;存在重叠如荧光笔标出 2.命名空间 作用域方面的优化 如果变量&#xff0c;函数和类的名称都存在于全…

Hive服务详解

Hive服务 HiveServer2、Hive Metastore 服务服务共同构成了 Hive 生态系统中的核心功能&#xff0c;分别负责管理元数据和提供数据查询服务&#xff0c;为用户提供了一个方便、高效的方式来访问和操作存储在 Hive 中的数据。 1. Hive 查询服务&#xff08;HiveServer2&#xf…

STM32自己从零开始实操01:原理图

在听完老师关于 STM32 物联网项目的所有硬件课程之后&#xff0c;就是感觉自己云里雾里&#xff0c;明明课程都认真听完了&#xff0c;笔记也认真记录&#xff0c;但是就是感觉学到的知识还不是自己。 遂决定站在老师的肩膀上自己开始设计项目&#xff0c;将知识变成自己的&am…

沉浸式推理乐趣:体验线上剧本杀小程序的魅力

在这个信息爆炸的时代&#xff0c;人们的娱乐方式也在不断地推陈出新。其中&#xff0c;线上剧本杀小程序以其独特的沉浸式推理乐趣&#xff0c;成为了许多人的新宠。它不仅让我们在闲暇之余享受到了推理的快乐&#xff0c;更让我们在虚拟的世界里感受到了人性的复杂与多彩。 线…

【Linux网络编程】数据链路层

数据链路层 1.以太网帧格式2.重谈局域网转发的原理(基于协议)3.认识MTU3.1MTU对IP协议的影响3.2MTU对UDP协议的影响3.3MTU对于TCP协议的影响 4.ARP协议 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你的支持是对我最大的鼓励…

Windows系统下将MySQL数据库表内的数据全量导入Elasticsearch

目录 下载安装Logstash 配置Logstash配置文件 运行配置文件 查看导入结果 使用Logstash将sql数据导入Elasticsearch 下载安装Logstash 官网地址 选择Windows系统&#xff0c;需下载与安装的Elasticsearch相同版本的&#xff0c;下载完成后解压安装包。 配置Logstash配…

浏览器的同源策略与解决跨域

同源策略&#xff08;协议、域名、端口&#xff09; 同源策略&#xff08;Same-Origin Policy&#xff09;是一个在浏览器安全模型中被实施的重要安全机制。它是基于域名、协议和端口号的限制&#xff0c;用于防止不同源的网页间的恶意行为和信息泄露。 根据同源策略&#xf…

C语言笔试题之重排链表

重排链表 实例要求 1、给定一个单链表 L 的头节点 head &#xff0c;单链表 L 表示为&#xff1a; L0 → L1 → … → Ln - 1 → Ln2、请将其重新排列后变为&#xff1a; L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …3、不能只是单纯的改变节点内部的值&#xff0c;而是…

“AI技能,新的职场通行证?揭秘阿里最新职业趋势报告“

随着“五一”劳动节的临近&#xff0c;阿里巴巴发布了一份引人注目的报告——《“AI”职业趋势报告》。这份报告不仅揭示了人工智能&#xff08;AI&#xff09;在各行各业中的关键作用&#xff0c;也预示了一个全新的工作时代正在加速到来。 报告中明确指出&#xff0c;AI的应用…

mysql8.0免安装版windows

1.下载 MySQL下载链接 2.解压与新建my.ini文件 解压的路径最好不要有中文路径在\mysql-8.0.36-winx64文件夹下新建my.ini文件&#xff0c;不建data文件夹(会自动生成) [mysqld] # 设置3306端口 port3306 # 设置mysql的安装目录(尽量用双斜杠\\,单斜杠\可能会报错) basedirD:\…

谈谈前端CSS盒模型

前言&#xff1a; 什么是CSS盒模型&#xff1f;盒模型的构造&#xff1f; 在前端开发中&#xff0c;CSS 盒模型是一种非常基础且核心的概念&#xff0c;它描述了文档中的每个元素被框架处理的方式。 ---- 打开浏览器开发者工具&#xff0c;查看Elements右侧下的Styles底部。 …

Docker从无到有

主要为windows下docker的安装与使用~ 初始Docker Docker理解 对于docker的加简介&#xff0c;我们可以官网获取它的概念&#xff0c;接下来就从什么是docker、为什么要使用docker以及它的作用来进行一个快速入门 前提&#xff1a;项目在发布时&#xff0c;不仅需要其jar包同…

2024年五一假期出行预测报告

来源&#xff1a;高德地图 2024年五一假期期间&#xff0c;预计全国高速出程整体交通压力高于返程&#xff0c;预计5月1日&#xff08;假期首日&#xff09;9时-13时是出程拥堵高峰时段&#xff0c;峰值出现在10时-11时&#xff1b; 全国高速返程高峰或将较为分散&#xff0c…

【持续更新】java刷题常用数据结构、方法和思路

动态数组——ArrayList ArrayList类是一个可以动态修改的数组&#xff0c;与普通数组的区别就是它是没有固定大小的限制&#xff0c;我们可以添加或删除元素&#xff1b;ArrayList 继承了 AbstractList &#xff0c;并实现了 List 接口。 实例化方法&#xff1a;ArrayList<…

hadoop安装记录

目录 零、版本说明一、环境准备1.1.规划1.2.准备 二、安装配置hadoop 三、启动 零、版本说明 centos [rootnode1 ~]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core)jdk [rootnode1 ~]# java -version java version "1.8.0_311" Java(TM) SE Run…

基于微信小程序云开发实现考研题库小程序V2.0

不久之前&#xff0c;基于云开发的微信答题小程序搭建题库小程序V1.0&#xff0c;软件架构是微信原生小程序云开发。现在来回顾一下&#xff0c;已经实现的功能。 一、V1.0项目预览 1、页面结构 首页 答题页 结果页 我的页 排行榜页 答题历史页 登录页 使用指引页 2…

Linux实验一:Linux环境及编程工具

目录 一、实验目的二、实验内容三、参考代码四、实验步骤步骤1. 编辑源代码test1.c步骤2. 编译源代码test1.c步骤3. 调试test1步骤4. 重新编译运行test1.c 五、实验结果六、实验总结 一、实验目的 1、掌握Linux C开发过程中的基本概念&#xff1b; 2、掌握如vim&#xff0c;GC…