十大经典排序算法总结(java 描述)-算法概述、复杂度及相关概念
2024-11-15 10:01:49发布 浏览242次 信息编号:200143
友情提醒:凡是以各种理由向你收取费用,均有骗子嫌疑,请提高警惕,不要轻易支付。
十大经典排序算法总结(java 描述)-算法概述、复杂度及相关概念
个人博客来自:
链接:十大经典排序算法总结(java说明)/
封面来自网络
00 算法概述
0.1 算法分类
十种常见的排序算法可以分为两大类:
非线性时间比较排序:通过比较确定元素之间的相对顺序。由于其时间复杂度不能超过O(nlogn),因此称为非线性时间比较排序。
线性时间非比较排序:不通过比较来确定元素之间的相对顺序。它可以突破基于比较的排序的时间下限,以线性时间运行,因此称为线性时间非比较排序。
0.2 算法复杂度
0.3 相关概念
稳定:如果a本来在b前面,并且a=b,那么排序后a仍然在b前面。
不稳定:如果a本来在b前面,且a=b,那么排序后a可能会出现在b后面。
时间复杂度:对排序数据的操作总数。反映当n变化时操作次数的模式。
空间复杂度:是指算法在计算机中执行时所需存储空间的度量。它也是数据大小 n 的函数。
01 冒泡排序(Sort)
冒泡排序是一种简单的排序算法。它反复遍历要排序的序列,一次比较两个元素,如果顺序错误则交换它们。重复访问数组的工作,直到不需要再进行交换,这意味着数组已经排序完毕。这个算法的名字来源于这样一个事实:较小的元素会通过交换慢慢“浮动”到数组的顶部。
1.1 算法描述
1.2 GIF演示
1.3 代码实现
(arr){
= 到达;
for(vari = 0; i < len - 1; i++) {
for(varj = 0; j < len - 1- i; j++) {
if(arr[j] > arr[j+1]) { // 两两比较相邻元素
= arr[j+1]; // 元素交换
arr[j+1] = arr[j];
arr[j] = 温度;
;
02 选择排序
选择排序(-sort)是一种简单直观的排序算法。工作原理:首先,找到未排序序列中最小(大)的元素,并将其存储在已排序序列的起始位置。然后,继续从剩余的未排序元素中找到最小(大)的元素,然后将其放入已排序的序列中。的结束。依此类推,直到所有元素都排序完毕。
2.1 算法描述
对n条记录进行直接选择排序,经过n-1次直接选择排序即可得到有序结果。具体算法描述如下:
2.2 GIF演示
2.3 代码实现
t(arr) {
= 到达;
,温度;
for( 变量 = 0; i < len - 1; i++) {
=i;
for(varj = i + 1; j < len; j++) {
if(arr[j] < arr[]) { // 找到最小的数
= j; // 保存最小数的索引
温度 = arr[i];
arr[i] = arr[];
arr[] = 临时;
;
2.4 算法分析
最稳定的排序算法之一,因为无论输入什么数据,时间复杂度都是O(n2),所以使用时数据量越小越好。唯一的优点可能就是不占用额外的内存空间。从理论上讲,选择排序也可能是大多数人在排序时想到的最常见的排序方法。
03 插入排序(Sort)
插入排序(-Sort)的算法描述是一种简单直观的排序算法。它通过构建有序序列来工作。对于未排序的数据,它会在已排序的序列中从后向前扫描,找到对应的位置并插入。
3.1 算法描述
一般来说,插入排序是使用原地在数组上实现的。具体算法描述如下:
3.2 GIF演示
3.2 代码实现
t(arr) {
= 到达;
, ;
for(vari = 1; i < len; i++) {
=i-1;
= arr[i];
while( >= 0&& arr[] > ) {
arr[ + 1] = arr[];
--;
arr[ + 1] = ;
;
3.4 算法分析
在插入排序的实现中,通常使用就地排序(即只使用O(1)额外空间的排序)。因此,在从后向前扫描的过程中,需要将已排序的元素不断地、逐渐地向后移动。 ,为最新元素提供插入空间。
04 希尔排序
1959年由Shell发明,是第一个突破O(n2)的排序算法,是简单插入排序的改进版本。它与插入排序的不同之处在于它首先比较距离较远的元素。希尔排序也称为减少增量排序。
4.1 算法描述
首先将整个待排序的记录序列分成若干子序列进行直接插入排序。具体算法描述:
4.2 GIF演示
4.3 代码实现
(arr) {
= 编,
温度,
间隙=1;
while(gap < len / 3) { // 动态定义间隙序列
间隙=间隙*3+1;
for(间隙;间隙 > 0;间隙 = Math.floor(间隙 / 3)) {
for(vari=gap;i<len;i++){
温度 = arr[i];
for( varj = i-gap; j > 0&& arr[j]> temp; j-=gap) {
arr[j + 间隙] = arr[j];
arr[j + 间隙] = 温度;
;
4.4 算法分析
希尔排序的核心在于区间序列的设置。间隔顺序可以预先设置或动态定义。动态定义区间序列的算法是由《算法(第4版)》的合著者提出的。
05 归并排序
归并排序是一种基于归并操作的有效排序算法。该算法是使用分而治之法(and)的一个非常典型的应用。将已经有序的子序列合并,得到完全有序的序列;即先对每个子序列进行排序,然后对子序列段进行排序。如果两个有序列表合并为一个有序列表,则称为 2 路合并。
5.1 算法描述
5.2 GIF演示
5.3 代码实现
(arr) { // 使用自上而下的递归方法
= 到达;
如果(长度<2){
;
= Math.floor(len / 2),
左 = arr.slice( 0, ),
右 = arr.slice();
((左),(右));
(左,右){
= [];
while(左.> 0&& 右.> 0) {
if(左[0] arr[]) {
= 左;
if(右 < len&& arr[右] > arr[]) {
= 正确;
如果(!=我){
交换(arr,我,);
(arr,);
(arr, i, j){
var temp = arr[i];
arr[i] = arr[j];
arr[j] = 温度;
(arr){
(已);
for(var i = arr.- 1; i > 0; i --) {
交换(arr,0,i);
伦--;
(arr,0);
;
08 计数排序(Sort)
计数排序不是基于比较的排序算法。它的核心是将输入数据值转换为键并存储在额外的数组空间中。计数排序作为一种线性时间复杂度排序,要求输入数据必须是一定范围内的整数。
8.1 算法描述
8.2 GIF演示
8.3 代码实现
(arr,){
= (+ 1),
= 0;
= 编,
= + 1;
for( 变量 = 0; i < ; i++) {
if(![arr[i]]) {
[arr[i]] = 0;
[arr[i]]++;
for(varj = 0; j < ; j++) {
while([j] > 0) {
arr[++] = j;
[j]——;
;
8.4 算法分析
计数排序是一种稳定的排序算法。当输入元素为0到k之间的n个整数时,时间复杂度为O(n+k),空间复杂度也为O(n+k)。它的排序速度比任何比较排序算法都要快。当k不是很大且序列比较集中时,计数排序是一种非常有效的排序算法。
09 桶排序(Sort)
桶排序是计数排序的升级版本。它利用了函数的映射关系。效率的关键在于这个映射函数的确定。桶排序(sort)的工作原理:假设输入数据服从均匀分布,将数据划分到有限个桶中,然后对每个桶分别进行排序(可以使用其他排序算法或者继续使用桶)递归)按行排序)。
9.1 算法描述
9.2 图片演示
9.3 代码实现
(到达,){
if(arr. === 0) {
;
瓦里;
= arr[0];
= arr[0];
for(i = 1; i < arr.; i++) {
if(arr[i] < ) {
= arr[i]; // 输入数据的最小值
} (arr[i] > ) {
= arr[i]; //输入数据的最大值
// 桶的初始化
ZE=5; // 设置默认桶数为5
= || ;
= Math.floor(( - ) / ) + 1;
= ();
for(i = 0; i < .; i++) {
[i] = [];
//利用映射函数将数据分布到各个桶中
for(i = 0; i < arr.; i++) {
[ Math.floor((arr[i] - ) / )].push(arr[i]);
编曲= 0;
for(i = 0; i < .; i++) {
([我]); // 对每个桶进行排序,这里使用插入排序
for( varj = 0; j < [i].; j++) {
arr.push([i][j]);
;
9.4 算法分析
桶排序在最好的情况下使用线性时间 O(n)。桶排序的时间复杂度取决于对每个桶之间的数据进行排序的时间复杂度,因为其他部分的时间复杂度是O(n)。显然,桶划分得越小,每个桶之间的数据就越少,排序所需的时间就越少。但相应的空间消耗也会增加。
010 基数排序
基数排序是先按低位排序,然后收集;然后按照高位排序,然后收集;依此类推,直到最高顺序。有时某些属性具有优先级顺序,先按低优先级排序,然后按高优先级排序。最终的顺序是优先级高的在先,优先级高且优先级相同的在先。
10.1 算法描述
10.2 GIF演示
10.3 代码实现
// LSD 基数排序
= [];
(arr,){
= 10;
= 1;
for( vari = 0; i < ; i++, dev *= 10, mod *= 10) {
for(varj = 0; j < arr.; j++) {
= ((arr[j] % mod) / dev);
如果([]==空){
[]=[];
[].push(arr[j]);
= 0;
for(varj = 0; j < .; j++) {
= 空;
if([j]!= null) {
while((值= [j].shift) != null) {
arr[pos++] = 值;
;
10.4 算法分析
基数排序是基于单独排序和单独收集的,因此是稳定的。但基数排序的性能比桶排序稍差。每个桶分配关键字需要O(n)的时间复杂度,分配后获得新的关键字序列需要O(n)的时间复杂度。如果待排序的数据可以分为d个关键字,则基数排序的时间复杂度为O(d*2n)。当然,d比n小很多,所以基本上是线性的。
基数排序的空间复杂度为O(n+k),其中k是桶的数量。一般来说,n>>k,所以额外的空间大约需要n。
你想如何加入内部推广群、直播群、技术交流群?
版权归作者所有。欢迎大家留言、贡献。
——结局——
今天的讨论
2018.08.19
提醒:请联系我时一定说明是从星空网上看到的!