十大经典排序算法整理汇总(附代码)

简介: 本文整理并总结了十大经典的排序算法(冒泡排序、选择排序、插入排序、快速排序、归并排序、希尔排序、计数排序、基数排序、桶排序、堆排序)的时间复杂度、空间复杂度等性质。

前言


本文整理并总结了十大经典的排序算法(冒泡排序、选择排序、插入排序、快速排序、归并排序、希尔排序、计数排序、基数排序、桶排序、堆排序)的时间复杂度、空间复杂度等性质。

本文并不会详细讲解每种排序算法的原理,网上有很多很好的教程,大家可以自己去搜了看。

最后我还亲自手写了十种排序算法的 c++ 代码,大家可以用来通过 LeetCode 912. 排序数组[1] 这道题。

性质汇总


如果发现图中有错误,请留言告知。

image.png十大经典排序算法性质汇总

维基百科


我觉得还是英文维基百科讲的比较详细、严谨。如果大家看的比较累的话,可以自己百度搜索相应的教程。

冒泡排序

https://en.wikipedia.org/wiki/Bubble_sort

选择排序

https://en.wikipedia.org/wiki/Selection_sort

插入排序

https://en.wikipedia.org/wiki/Insertion_sort

快速排序

https://en.wikipedia.org/wiki/Quicksort

归并排序

https://en.wikipedia.org/wiki/Merge_sort

希尔排序

https://en.wikipedia.org/wiki/Shellsort

计数排序

https://en.wikipedia.org/wiki/Counting_sort

基数排序

https://en.wikipedia.org/wiki/Radix_sort

桶排序

https://en.wikipedia.org/wiki/Bucket_sort

堆排序

https://en.wikipedia.org/wiki/Heapsort

代码实现


所有的排序算法接口都是相同的,也就是 vector xxxSort(vector& nums) 。只需要你传入一个 vector 类型的数组,就能返回排序后的结果。

运行下来可以发现,桶排序速度是比较快的。而冒泡排序、选择排序和插入排序因为时间复杂度太高无法通过本题,基数排序因为无法处理负数也不能通过本题。

classSolution {
public:   
vector<int>sortArray(vector<int>&nums) { 
returnquickSort(nums);    }
// 冒泡排序(超时)vector<int>bubbleSort(vector<int>&nums) {  
intn=nums.size();    
for (inti=0; i<n; ++i) {   
for (intj=n-2; j>=i; --j) {  
if (nums[j] >nums[j+1]) {   
swap(nums[j], nums[j+1]); 
                }      
            }      
        }    
returnnums; 
    }
// 选择排序(超时)vector<int>selectSort(vector<int>&nums) {  
intn=nums.size();   
for (inti=0; i<n; ++i) {
intidx=i;     
for (intj=i; j<n; ++j) {  
if (nums[j] <nums[idx]) {  
idx=j;      
                }         
            }      
swap(nums[i], nums[idx]); 
        }     
returnnums;   
    }
// 插入排序(超时)  vector<int>insertSort(vector<int>&nums) {    
intn=nums.size();  
for (inti=0; i<n; ++i) {   
for (intj=i; j>0&&nums[j] <nums[j-1]; --j) { 
swap(nums[j], nums[j-1]);
        }     
    }    
returnnums; 
}
// 快速排序(24 ms) voidqSort(vector<int>&nums, intl, intr) {   
if (l>=r) return;   
intm=l; 
for (inti=l; i<r; ++i) {   
if (nums[i] <nums[r]) {  
swap(nums[m++], nums[i]); 
            }     
        }    
swap(nums[m], nums[r]); 
qSort(nums, l, m-1);  
qSort(nums, m+1, r);  
    }
vector<int>quickSort(vector<int>&nums) { 
intn=nums.size();   
qSort(nums, 0, n-1);   
returnnums;  
    }
// 归并排序(192 ms)vector<int>mSort(vector<int>&nums, intl, intr) {  
if (l>=r) return {nums[l]}; 
intm=l+(r-l)/2;   
vector<int>lnums=mSort(nums, l, m); 
vector<int>rnums=mSort(nums, m+1, r); 
vector<int>res;    
inti=0, j=0;  
while (i<=m-l&&j<=r-m-1) {    
if (lnums[i] <rnums[j]) {   
res.push_back(lnums[i++]); 
            } else {      
res.push_back(rnums[j++]);
            }     
        }      
while (i<=m-l) {  
res.push_back(lnums[i++]); 
        }       
while (j<=r-m-1) {   
res.push_back(rnums[j++]);  
        }      
returnres;    }
vector<int>mergeSort(vector<int>&nums) {   
intn=nums.size(); 
nums=mSort(nums, 0, n-1);
returnnums; 
    }
// 归并排序 + 非递归(80 ms)vector<int>mergeSortNR(vector<int>&nums) {  
intn=nums.size();     
for (intlen=1; len<n; len<<=1) {      
for (intl=0; l<n-len; l+=2*len) {  
intm=l+len-1;   
intr=min(n-1, l+2*len-1);
vector<int>res;  
inti=l, j=m+1; 
while (i<=m&&j<=r) {    
if (nums[i] <nums[j]) { 
res.push_back(nums[i++]);   
                    } else {       
res.push_back(nums[j++]); 
                    }    
                }       
while (i<=m) {  
res.push_back(nums[i++]);   
                }         
while (j<=r) {  
res.push_back(nums[j++]); 
                }         
for (inti=l; i<=r; ++i) {   
nums[i] =res[i-l];  
                }         
            }       
        }    
returnnums;
    }
// 希尔排序(40 ms)vector<int>shellSort(vector<int>&nums) {  
intn=nums.size();   
for (intgap=n/2; gap>0; gap/=2) {      
for (inti=gap; i<n; ++i) {   
for (intj=i; j-gap>=0&&nums[j-gap] >nums[j]; j-=gap) {    
swap(nums[j-gap], nums[j]); 
                }         
            }      
        }    
returnnums; 
    }
// 计数排序(32 ms) vector<int>countSort(vector<int>&nums) {     
intn=nums.size();      
if (!n) return {};    
intminv=*min_element(nums.begin(), nums.end());  
intmaxv=*max_element(nums.begin(), nums.end()); 
intm=maxv-minv+1;     
vector<int>count(m, 0);  
for (inti=0; i<n; ++i) {    
count[nums[i]-minv]++;    
        }
vector<int>res; 
for (inti=0; i<m; ++i) {   
for (intj=0; j<count[i]; ++j) {  
res.push_back(i+minv);   
            }      
        }      
returnres;    }
// 基数排序(不适用于负数) vector<int>radixSort(vector<int>&nums) {  
intn=nums.size();    
intmaxv=*max_element(nums.begin(), nums.end()); 
intmaxd=0;  
while (maxv>0) {  
maxv/=10;     
maxd++;      
        }       
vector<int>count(10, 0), rank(n, 0);  
intbase=1;    
while (maxd>0) {     
count.assign(10, 0);    
for (inti=0; i<n; ++i) {    
count[(nums[i]/base)%10]++;  
            }         
for (inti=1; i<10; ++i) {     
count[i] +=count[i-1];   
            }           
for (inti=n-1; i>=0; --i) {    
rank[--count[(nums[i]/base)%10]] =nums[i];            }          
for (inti=0; i<n; ++i) {       
nums[i] =rank[i]; 
            }          
maxd--;       
base*=10;     
        }     
returnnums;  
    }
// 桶排序 (20 ms) vector<int>bucketSort(vector<int>&nums) {     
intn=nums.size();   
intmaxv=*max_element(nums.begin(), nums.end());  
intminv=*min_element(nums.begin(), nums.end());     
intbs=1000;    
intm= (maxv-minv)/bs+1;  
vector<vector<int>>bucket(m);  
for (inti=0; i<n; ++i) {  
bucket[(nums[i]-minv)/bs].push_back(nums[i]);  
        }    
intidx=0;    
for (inti=0; i<m; ++i) {   
intsz=bucket[i].size();  
bucket[i] =quickSort(bucket[i]);   
for (intj=0; j<sz; ++j) {   
nums[idx++] =bucket[i][j];  
            }   
        }    
returnnums;   
    }
// 堆排序(32 ms)  voidadjust(vector<int>&nums, intp, ints) {   
while (2*p+1<s) {      
intc1=2*p+1;   
intc2=2*p+2;   
intc= (c2<s&&nums[c2]>nums[c1]) ?c2 : c1;  
if (nums[c] >nums[p]) swap(nums[c], nums[p]);    
elsebreak;      
p=c;     
        }   
    }
vector<int>heapSort(vector<int>&nums) {    
intn=nums.size(); 
for (inti=n/2-1; i>=0; --i) {     
adjust(nums, i, n);    
        }       
for (inti=n-1; i>0; --i) { 
swap(nums[0], nums[i]);   
adjust(nums, 0, i); 
        }    
returnnums;  
    }
};

参考资料


[1]

LeetCode 912. 排序数组: https://leetcode-cn.com/problems/sort-an-array/

image.png

作者简介:godweiyang知乎同名华东师范大学计算机系硕士在读,方向自然语言处理与深度学习喜欢与人分享技术与知识,期待与你的进一步交流~

相关文章
|
1月前
|
存储 机器学习/深度学习 算法
|
1月前
|
监控 安全 机器人
毕业论文设计题目大全(源码+论文)_kaic
毕业论文设计题目大全(源码+论文)_kaic
|
9月前
|
存储 算法 Java
2023年Java核心技术第十二篇(篇篇万字精讲)
2023年Java核心技术第十二篇(篇篇万字精讲)
63 1
|
9月前
|
SQL 算法 Linux
腾讯T3算法大牛整理分享的LeetCode算法小抄完整文档
本文⽬前可以⼿把⼿带你解决 110 道 LeetCode 算法问题,⽽且在不断更新,全部基于 LeetCode 的题⽬,涵盖了所有题型和技巧。
|
9月前
|
算法
趣学算法【第一章:算法之美】感悟(下)
趣学算法【第一章:算法之美】感悟(下)
|
9月前
|
算法 程序员
趣学算法【第一章:算法之美】感悟(上)
趣学算法【第一章:算法之美】感悟(上)
|
9月前
|
机器学习/深度学习 传感器 安全
2023 年高教社杯B题多波束测线问题思路及参考代码(持续更新)
2023 年高教社杯B题多波束测线问题思路及参考代码(持续更新)
|
搜索推荐 C++
十大经典排序算法整理汇总(附代码)
十大经典排序算法整理汇总(附代码)
|
机器学习/深度学习 算法 数据挖掘
周志华《机器学习》西瓜书精炼版笔记来了!16 章完整版
周志华《机器学习》西瓜书精炼版笔记来了!16 章完整版
1573 0
周志华《机器学习》西瓜书精炼版笔记来了!16 章完整版
|
机器学习/深度学习 自然语言处理 算法
graphSage还是HAN ?吐血力作综述Graph Embeding 经典好文
graphSage还是HAN ?吐血力作综述Graph Embeding 经典好文
graphSage还是HAN ?吐血力作综述Graph Embeding 经典好文