算法分析与设计:10 大排序算法大汇总(Java)

news/2024/5/19 2:06:35/文章来源:https://blog.csdn.net/SongXJ_01/article/details/127125152

冒泡排序

  • 相邻比较并交换位置,将大的数冒泡交换到最后。

冒泡排序

    /******************************************************************************** 冒泡排序(Bubble Sort)它重复地走访过要排序的元素,依次比较相邻两个元素,如果它们的顺序错误就把他们调换过来,直到没有元素再需要交换,排序完成。********************************************************************************/public static int[] BubbleSort(int[] arr) {for (int i = 0; i < arr.length - 1; i++) {for (int j = 0; j < arr.length - 1 - i; j++) {if (arr[j] > arr[j + 1]) {int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}return arr;}

时间复杂度:

  • 最坏情况下为O(N2)O(N^2)O(N2),此时待排序列为逆序,或者说接近逆序
  • 最好情况下为O(N)O(N)O(N),此时待排序列为升序,或者说接近升序。

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



插入排序

  • 遍历每一个数,并将数字插入到合适的位置。

插入排序

    /******************************************************************************** 插入排序(Insertion Sort)将一个记录插入到已经排好序的有序表中。********************************************************************************/public static int[] InsertionSort(int[] arr) {for (int i = 0; i < arr.length - 1; i++) {int current = arr[i + 1]; // 待归位的数int preIndex = i;         // 待归位的前面的一个数// 利用逐个比较的方式将待归位的数归位。while (preIndex >= 0 && current < arr[preIndex]) {arr[preIndex + 1] = arr[preIndex];preIndex--;}arr[preIndex + 1] = current; // 找到了正确的位置,进行归位}return arr;}

时间复杂度:

  • 最坏情况下为O(N2)O(N^2)O(N2),此时待排序列为逆序,或者说接近逆序
  • 最好情况下为O(N)O(N)O(N),此时待排序列为升序,或者说接近升序。

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



选择排序

  • 每次从数组中选一个最小的放在开头。

选择排序

    /******************************************************************************** 选择排序(Selection Sort)第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。********************************************************************************/public static int[] SelectionSort(int[] arr) {for (int i = 0; i < arr.length; i++) {int minIndex = i;for (int j = i; j < arr.length; j++) {if (arr[j] < arr[minIndex]) //找到最小的数minIndex = j;           //将最小数的索引保存}int temp = arr[minIndex];arr[minIndex] = arr[i];arr[i] = temp;}return arr;}

时间复杂度:O(N2)O(N^2)O(N2)

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



希尔排序

希尔排序

    /******************************************************************************** 希尔排序(Shell Sort)先选定一个小于N的整数gap作为第一增量,然后将所有距离为gap的元素分在同一组,并对每一组的元素进行直接插入排序。然后再取一个比第一增量小的整数作为第二增量,重复上述操作……********************************************************************************/public static int[] ShellSort(int[] arr) {// step:步长for (int step = arr.length / 2; step > 0; step /= 2) {// 对一个步长区间进行比较 [step,arr.length)for (int i = step; i < arr.length; i++) {int value = arr[i];int j;// 对步长区间中具体的元素进行比较for (j = i - step; j >= 0 && arr[j] > value; j -= step) {// j为左区间的取值,j+step为右区间与左区间的对应值。arr[j + step] = arr[j];}// 此时step为一个负数,[j + step]为左区间上的初始交换值arr[j + step] = value;}}return arr;}

时间复杂度平均:O(N1.3)O(N^{1.3})O(N1.3)

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



快速排序

快速排序

    /******************************************************************************** 快速排序(Quick Sort)1.选择基准值:在待排序列中,按照某种方式挑出一个元素,作为基准值。2.分割操作:以该基准值在序列中的实际位置,把序列分成两个子序列,一边是比它大的值,另外一边是比它小的值。3.递归:对两个子序列进行快排,直到序列为空或者只有一个元素。********************************************************************************/public static void QuickSort(int[] arr, int low, int high) {int p, i, j, temp;if (low >= high) {return;}p = arr[low];   // p是基准数,这里就是每个数组的第一个i = low;j = high;while (i < j) {// 右边当发现小于p的值时停止循环while (arr[j] >= p && i < j) {j--;}// 左边当发现大于p的值时停止循环while (arr[i] <= p && i < j) {i++;}temp = arr[j];arr[j] = arr[i];arr[i] = temp;}arr[low] = arr[i];arr[i] = p;QuickSort(arr, low, j - 1);  // 对左边快排QuickSort(arr, j + 1, high); // 对右边快排}



归并排序

  1. 把长度为n的输入序列分成两个长度为n/2的子序列;
  2. 对这两个子序列分别采用归并排序;
  3. 将两个排序好的子序列合并成一个最终的排序序列。

归并排序的动画图解

归并排序

    /******************************************************************************** 归并排序(Merge Sort)1.把长度为n的输入序列分成两个长度为n/2的子序列;2.对这两个子序列分别采用归并排序;3.将两个排序好的子序列合并成一个最终的排序序列。********************************************************************************/public static void MergeSort(int[] arr, int low, int high) {int mid = (low + high) / 2;if (low < high) {// 递归地对左右两边进行排序MergeSort(arr, low, mid);MergeSort(arr, mid + 1, high);// 合并merge(arr, low, mid, high);}}public static void merge(int[] arr, int low, int mid, int high) {int[] temp = new int[high - low + 1];   // temp数组用于暂存合并的结果int i = low;    // 左半边的指针int j = mid + 1;   // 右半边的指针int k = 0;  // 合并后数组的指针// 将记录由小到大地放进temp数组for (; i <= mid && j <= high; k++) {if (arr[i] < arr[j])temp[k] = arr[i++];elsetemp[k] = arr[j++];}// 接下来两个while循环是为了将剩余的放到temp数组中while (i <= mid)temp[k++] = arr[i++];while (j <= high)temp[k++] = arr[j++];// 将temp数组中的元素写入到待排数组中for (int l = 0; l < temp.length; l++)arr[low + l] = temp[l];}

时间复杂度:

  • 最佳情况,O(n)O(n)O(n)
  • 最差情况,O(nlogn)O(nlogn)O(nlogn)
  • 平均情况,O(nlogn)O(nlogn)O(nlogn)

空间复杂度 O(N+logN)O(N+logN)O(N+logN)



堆排序

通过完全二叉树构建大顶堆,并维护大顶堆的性质。

堆排序

    /******************************************************************************** 堆排序(Heap Sort)通过完全二叉树构建大顶堆,并维护大顶堆的性质。********************************************************************************/public static void HeapSort(int[] arr) {// 构建一个大顶堆for (int i = arr.length / 2 - 1; i >= 0; i--) { // 从倒数第一个非叶子节点开始adjustHeap(arr, i, arr.length - 1);// 从第一个非叶子节点从下至上,从左至右调整结构}for (int i = arr.length - 1; i >= 0; i--) {// 将堆顶元素与末尾元素交换 将最大元素沉到数组末尾 + 重新调整堆结构int temp = arr[0];arr[0] = arr[i];arr[i] = temp;adjustHeap(arr, 0, i); // 将a中前i个记录重新调整为大顶堆}}public static void adjustHeap(int[] array, int index, int length) {int temp = array[index]; // 取出当前元素// i节点是index节点的左子节点for (int i = 2 * index + 1; i < length; i = 2 * i + 1) {if (i + 1 < length && array[i] < array[i + 1]) i++;    // 表明左子节点小于右子节点,将指针移至较大节点if (array[i] > temp) {  // 如果子节点大于父节点array[index] = array[i];    // 将较大值赋给当前节点index = i;  // 指针移向子节点} else break;}// 循环结束,已经将最大值放在了堆顶,将temp值放到最终的位置array[index] = temp;}

时间复杂度:O(nlogn)O(nlogn)O(nlogn)。(由于堆排序对原始记录的状
态并不敏感,因此它无论是最好、最坏和平均时间复杂度均为O(nlogn)O(nlogn)O(nlogn)。)

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

计数排序

找出待排序的数组array中最大的元素max
统计数组中每个值为 i 的元素出现的次数,存入数组 count 的第 i 项
对所有的计数累加(从 count中的第一个元素开始,每一项和前一项相加)
反向填充目标数组:将每个元素 i 放在新数组的第 count [i] 项,每放一个元素就将 count [i] 减去

计数排序

    /******************************************************************************** 计数排序(Count Sort)1.开辟一个长度为 maxValue-minValue+1 的数组。2.分配。扫描一遍原始数组,以当前值- minValue 作为下标,将该下标的计数器增1。3.收集。扫描一遍计数器数组,按倒序把值收集起来。********************************************************************************/public static void CountSort(int[] arr) {// 得到数组的最大值和最小值,并推算出差值dint max = arr[0];int min = arr[0];for (int i = 1; i < arr.length; i++) {if (arr[i] > max) max = arr[i];if (arr[i] < min) min = arr[i];}int d = max - min;// 创建统计数组并统计对应的元素个数int[] countArray = new int[d + 1];for (int j : arr)countArray[j - min]++;// 统计数组做变形,后边的元素等于前面的元素之和for (int i = 1; i < countArray.length; i++)countArray[i] += countArray[i - 1];// 倒序遍历原始数组,从统计数组中找到正确的位置,输出到结果数组int[] sortedArray = new int[arr.length];for (int i = arr.length - 1; i >= 0; i--) {sortedArray[countArray[arr[i] - min] - 1] = arr[i]; // 给sortedArray的当前位置赋值countArray[arr[i] - min]--; // 给countArray的位置的值--}// 将temp数组中的元素写入到待排数组中System.arraycopy(sortedArray, 0, arr, 0, sortedArray.length);}

时间复杂度:

  • 最佳情况,O(n+k)O(n+k)O(n+k)
  • 最差情况,O(n+k)O(n+k)O(n+k)
  • 平均情况,O(n+n)O(n+n)O(n+n)

空间复杂度 O(k)O(k)O(k)



桶排序

桶排序可以看成是计数排序的升级版,它将要排的数据分到多个有序的桶里,每个桶里的数据再单独排序,再把每个桶的数据依次取出,即可完成排序。
桶排序:将值为i的元素放入i号桶,最后依次把桶里的元素倒出来。
桶排序

    /******************************************************************************** 桶排序(Bucket Sort)1.设置一个定量的数组当作空桶子。2.寻访序列,并且把项目一个一个放到对应的桶子去。3.对每个不是空的桶子进行排序。4.从不是空的桶子里把项目再放回原来的序列中。********************************************************************************/public static void BucketSort(int[] arr) {int max = arr[0];int min = arr[0];for (int i = 1; i < arr.length; i++) {if (arr[i] > max) max = arr[i];else if (arr[i] < min) min = arr[i];}// 最大值和最小值的差int diff = max - min;// 桶列表ArrayList<ArrayList<Integer>> bucketList = new ArrayList<>();for (int i = 0; i < arr.length; i++) {bucketList.add(new ArrayList<>());}// 每个桶的存数区间float section = (float) diff / (float) (arr.length - 1);// 数据入桶for (int j : arr) {//当前数除以区间得出存放桶的位置 减1后得出桶的下标int num = (int) (j / section) - 1;if (num < 0) num = 0;bucketList.get(num).add(j);}// 桶内排序for (ArrayList<Integer> integers : bucketList) {Collections.sort(integers);}// 写入原数组int index = 0;for (ArrayList<Integer> arrayList : bucketList) {for (int value : arrayList) {arr[index] = value;index++;}}}

时间复杂度:

  • 最佳情况,O(n+k)O(n+k)O(n+k)
  • 最差情况,O(n2)O(n^2)O(n2)
  • 平均情况,O(n+k)O(n+k)O(n+k)

空间复杂度 O(n+k)O(n+k)O(n+k)



基数排序

将整数按每个位数分别比较,利用了桶的思想。

基数排序

    /******************************************************************************** 基数排序(Raix Sort)* 将整数按每个位数分别比较,利用了桶的思想。********************************************************************************/public static void RaixSort(int[] arr) {// 得到数组中最大的数int max = arr[0];for (int i = 1; i < arr.length; i++)if (arr[i] > max) max = arr[i];// 得到最大数是几位数,通过拼接一个空串将其变为字符串进而求得字符串的长度,即为位数int maxLength = (max + "").length();// 定义一个二维数组,模拟桶,每个桶就是一个一维数组,为了防止放入数据的时候桶溢出,将桶的容量设置得大一些int[][] bucket = new int[10][arr.length];// 记录每个桶中实际存放的元素个数int[] bucketElementCounts = new int[10];// 通过变量n帮助取出元素位数上的数for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {for (int value : arr) {int digitOfElement = value / n % 10;    // 针对每个元素的位数进行处理bucket[digitOfElement][bucketElementCounts[digitOfElement]] = value;    // 将元素放入对应的桶中bucketElementCounts[digitOfElement]++;    // 将桶中的元素个数++}// 按照桶的顺序取出数据并放回原数组int index = 0;for (int k = 0; k < bucket.length; k++) {if (bucketElementCounts[k] != 0) {    // 如果桶中有数据,才取出放回原数组for (int l = 0; l < bucketElementCounts[k]; l++) {    // 说明桶中有数据,对该桶进行遍历arr[index++] = bucket[k][l];    // 取出元素放回原数组}}bucketElementCounts[k] = 0;    // 每轮处理后,需要将每个bucketElementCounts[k]置0}}}

时间复杂度:

  • 最佳情况,O(n×k)O(n×k)O(n×k)
  • 最差情况,O(n×k)O(n×k)O(n×k)
  • 平均情况,O(n×k)O(n×k)O(n×k)

空间复杂度 O(n+k)O(n+k)O(n+k)



汇总

汇总




版权声明:本文部分参考CSDN博主「~wangweijun」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_42453117/article/details/100036347

『 如有不足或错误欢迎评论指正 』

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

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

相关文章

E2成都电路板设计_启动保持停止电路的原理

电气技术分享之2 本文介绍电气工程里常见的启动、保持、停止电路的原理。 1、起保停电路的功能 起保停电路实现的功能&#xff1a;按启动按键&#xff0c;电路的负载得电并保持&#xff0c;按停止按键&#xff0c;负载断电。 2、起保停电路所需的元件 起保停电路所需的元件…

matplotlib绘制直方图,饼图,散点图,气泡图,箱型图,雷达图

matplotlib绘制直方图&#xff0c;饼图&#xff0c;散点图&#xff0c;气泡图&#xff0c;箱型图&#xff0c;雷达图一.直方图用10000个正态分布随机数画直方图二.绘制饼图或者圆环图圆环图根据消费支出画圆环图三.绘制散点图或气泡图使用scatter()函数绘制一个散点图&#xff…

【进制计算】 2 ~ N 进制计算

目录 规则 图解十、二、八、十六进制之间的转换 举例 除法计算出3进制&#xff1a; 乘法次方逆向计算原数&#xff1a; 图解二进制加减乘除计算 规则 十进制 除以 进制数 取余法&#xff1a;&#xff08;1&#xff09;被除数 除以 除数 等于 商 并取得余数&#xff0c;&am…

SSM进阶-Duubo入门demo整合MyBatis

搭建入门demo 搭建SpringSpringMVCDubbo入门demo 准备数据 数据库创建demo表 create table demo (id bigint auto_increment primary key,name varchar(255) null,description text null ); 插入数据 INSERT INTO demo(id, name, description) VAL…

数据库基础,看完这篇就够了!

转载请注明出处❤️ 作者:测试蔡坨坨 原文链接:caituotuo.top/747a74ea.html你好,我是测试蔡坨坨。 对于测试同学来说,除了知道测试基础知识外,还需要掌握一些测试基本技能,主要有Linux、数据库、计算机网络等,在此之前我们已经讨论过Linux基础知识以及在实际工作中的应…

神经网络模型训练简记(一)

神经网络模型训练简记&#xff08;一&#xff09;一、概念介绍1.1人工智能、机器学习、神经网络与深度学习1.2backbone与pretrain_model1.3batch_size、learning_rate、epoch与iteration1.4模型评价指标二、官方数据集简介2.1ImageNet数据集2.2 ILSVRC竞赛2.3 MS COCO数据集2.4…

【专栏】RPC系列(实战)-低配版NameServer

公众号【离心计划】,一起离开地球表面 【RPC系列合集】 【专栏】RPC系列&#xff08;理论&#xff09;-夜的第一章 【专栏】RPC系列&#xff08;理论&#xff09;-协议与序列化 【专栏】RPC系列&#xff08;理论&#xff09;-动态代理 【专栏】RPC系列&#xff08;实战&am…

读书笔记:软件工程(4) - 软件过程模型:瀑布模型

软件过程模型 为了改变软件开发的混乱状况&#xff0c;使软件开发更加有序。 瀑布模型 又称为经典生命周期&#xff0c;它提出了一个系统的&#xff0c;顺序的软件开发方法&#xff0c;从用户需求规格说明开始&#xff0c;通过策划&#xff0c;建模&#xff0c;构建和部署的…

Easyx基本使用(三)

Easyx基本使用&#xff08;三&#xff09; ——绘制简单图形 1. 绘制点&#xff08;putpixel&#xff09; void putpixel(int x,int y,COLORREF color );x&#xff1a;点的x坐标y&#xff1a;点的y坐标color&#xff1a;点的颜色返回值&#xff1a;无 #include <easyx.h…

程序员的数学课15 递归:如何计算汉诺塔问题的移动步数?

递归是重要的程序开发思想&#xff0c;比如程序源代码缩进、树形数据结构、XML 语法、快速排序法等都有递归的影子。 那么&#xff0c;递归思维的本质到底是什么呢&#xff1f;递归的理念看似隐讳&#xff0c;实则非常清晰明了。 为了让你由浅入深地理解它&#xff0c;这一讲…

paddle 训练模型的保持和载入

模型保持中的常见问题 &#xff0c;查看官网 模型保存常见问题-使用文档-PaddlePaddle深度学习平台 一、保存载入体系简介 模型保存与载入 一、保存载入体系简介 1.1 基础API保存载入体系 飞桨框架2.1对模型与参数的保存与载入相关接口进行了梳理&#xff1a;对于训练调优场景…

2023秋招nlp笔试题-太初

单选题 浮点数的表示范围和精度取决于 浮点数的取值范围由阶码的位数决定,而浮点数的精度由尾数的位数决定 响应中断请求的条件是 A.外设提出中断; B.外设工作完成和系统允许时; C.外设工作完成和中断标记触发器为“1”时; D.CPU提出中断。 计算器浮点运算速度为85.0167PF…

Day30_路由的props配置

提出问题&#xff1a; Detail是如何得到别传给他的参数&#xff0c;以及如何简化写法。 第一种写法的props 对象式 使用的很少&#xff0c;传递的是死数据 1.index.js组件里面 2.在detail组件里面 3效果图&#xff1a; 第二种写法props 布尔值 仅限于params参数传递…

心理学考研难度 分析

全国招收心理学院校排名 高等教育评价专业机构软科发布了“2020软科中国最好学科排名”&#xff0c;心理学院校有55所上榜&#xff0c;排名前10%依次为北京师范大学、北京大学、华南师范大学、西南大学、华东师范大学、华中师范大学、上海交通大学、浙江大学、陕西师范大学、上…

内存对齐对性能的影响

计算字节数 在 Go 语言中&#xff0c;可以使用 unsafe.Sizeof 计算出一个数据类型实例需要占用的字节数。 package mainimport ("fmt""unsafe" )type Args struct {num1 intnum2 int }type Flag struct {num1 int16num2 int32 }func main() {fmt.Println…

浅析axios原理与使用(包括axios的优雅写法与res的解构赋值)

目录前言一&#xff0c;什么是axios二&#xff0c;axios的基本使用2.1 不含参的axios调用2.2 含参数的axios调用三&#xff0c;axios的原理&#xff08;拦截器&#xff09;3.1 客户端与服务器之间的交互原理&#xff08;复习可略过&#xff09;3.2 浅析axios原理四&#xff0c;…

西瓜书研读——第三章 线性模型: 线性判别分析 LDA

西瓜书研读系列&#xff1a; 西瓜书研读——第三章 线性模型&#xff1a;一元线性回归 西瓜书研读——第三章 线性模型&#xff1a;多元线性回归 西瓜书研读——第三章 线性模型&#xff1a;线性几率回归&#xff08;逻辑回归&#xff09; 主要教材为西瓜书&#xff0c;结合…

K8s存储与GlusterFS实战

一、存储概述 1、共享存储机制概述 Kubernetes对于有状态的容器应用或者对数据需要持久化的应用&#xff0c;不仅需要将容器内的目录挂载到宿主机的目录或者emptyDir临时存储卷&#xff0c;而且需要更加可靠的存储来保存应用产生的重要数据&#xff0c;以便容器应用在重建之后…

常见的垃圾回收机制

如何工作在某些 Java 虚拟机中,堆的实现截然不同:它更像一个传送带,每分配一个新对象,它就向前移动一格。 这意味着对象存储空间的分配速度特别快。Java 的"堆指针"只是简单地移动到尚未分配的区域,所以它的效率与 C++ 在栈上分配空间的效率相当垃圾回收器工作时…

将Springbooot项目部署到云服务器上运行

将Springbooot项目部署到云服务器上运行一、项目打包二、将结果jar文件上传服务器三、授予jar文件权限&#xff0c;并运行四、运行失败可能原因一、项目打包 File->Project Structure Project Settings -> Artifacts -> 点击 号 -> JAR -> From modules with d…