目录
问题描述
给定一个长度为n的数列,将这个数列按从小到大的顺序排列。1<=n<=200
输入格式
第一行为一个整数n。
第二行包含n个整数,为待排序的数,每个整数的绝对值小于10000。
输出格式
输出一行,按从小到大的顺序输出排序后的数列。
样例输入
5
8 3 6 4 9
样例输出
3 4 6 8 9
一、sort排序:
更多信息可借鉴(介绍的很全面):https://blog.youkuaiyun.com/weixin_42617472/article/details/83748991
#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char** argv) {
int n;
cin>>n;
vector<int> arr;
int num;
for(int i = 0; i < n; i++)
{
cin>>num;
arr.push_back(num);
}
sort(arr.begin(), arr.end());//up
for(int i = 0; i < n; i++)
{
cout<<arr[i]<<" ";
}
return 0;
}
二、冒泡排序
- 比较相邻的元素,如果前一个比后一个大,就把它们两个调换位置。
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较
分类 -------------- 内部比较排序 数据结构 ---------- 数组 最差时间复杂度 ---- O(n^2) 最优时间复杂度 ---- 如果能在内部循环第一次运行时,使用一个旗标来表示有无需要交换的可能,可以把最优时间复杂度降低到O(n) 平均时间复杂度 ---- O(n^2) 所需辅助空间 ------ O(1) 稳定性 ------------ 稳定
#include <iostream>
using namespace std;
void BubbleSort(int arr[], int n)
{
int temp;
// 外层循环控制循环次数,n个数,n-1对 ,最多n-1次
for(int i = 0; i < n-1; i++)
{
// 内层循环控制比较范围
for(int j = 0; j < n - 1 - i; j++)
{
//依次比较相邻的两个元素,使较大的那个向后移
if(arr[j] > arr[j+1])
{
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
int main(int argc, char** argv) {
int n;
cin>>n;
int arr[n];
for(int i = 0; i < n; i++)
{
cin>>arr[i];
}
//冒泡排序
BubbleSort(arr,n);
for(int i = 0; i < n; i++)
{
cout<<arr[i]<<" ";
}
return 0;
}
三、选择排序
算法过程:初始时在序列中找到最小(大)元素,放到序列的起始位置作为已排序序列;然后,再从剩余未排序元素中继续寻找最小(大)元素,放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
分类 -------------- 内部比较排序
数据结构 ---------- 数组
最差时间复杂度 ---- O(n^2)
最优时间复杂度 ---- O(n^2)
平均时间复杂度 ---- O(n^2)
所需辅助空间 ------ O(1)
稳定性 ------------ 不稳定
#include <iostream>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
void selectSort(int arr[], int n)
{
int temp,min;
for(int i = 0; i < n-1; i++)
{//i为已排序序列的末尾
min = i;
for(int j = i+1; j < n; j++)//未排序序列
{
if(arr[j] < arr[min])//寻找未排序序列的最小值
{
min = j;
}
}
if(min != i)
{//将第i小值放在末尾,该操作也说明选择排序算法不稳定
temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
}
}
}
int main(int argc, char** argv) {
int n;
cin>>n;
int arr[n];
for(int i = 0; i < n; i++)
{
cin>>arr[i];
}
//选择排序
selectSort(arr,n);
for(int i = 0; i < n; i++)
{
cout<<arr[i]<<" ";
}
return 0;
}
四、插入排序
算法:
- 从第一个元素开始,该元素可以认为已经被排序
- 取出下一个元素,在已经排序的元素序列中从后向前扫描
- 如果该元素(已排序)大于新元素,将该元素移到下一位置
- 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
- 将新元素插入到该位置后
- 重复步骤2~5
分类 ------------- 内部比较排序
数据结构 ---------- 数组
最差时间复杂度 ---- 最坏情况为输入序列是降序排列的,此时时间复杂度O(n^2)
最优时间复杂度 ---- 最好情况为输入序列是升序排列的,此时时间复杂度O(n)
平均时间复杂度 ---- O(n^2)
所需辅助空间 ------ O(1)
稳定性 ------------ 稳定
#include <iostream>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
void insertSort(int arr[], int n)
{
int current;
for(int i = 1; i < n; i++)
{
current = arr[i];
int j = i - 1;
while(j >= 0 && arr[j] > current)
{
arr[j+1] = arr[j];
j--;
}
arr[j+1] = current;
}
}
int main(int argc, char** argv) {
int n;
cin>>n;
int arr[n];
for(int i = 0; i < n; i++)
{
cin>>arr[i];
}
//插入排序
insertSort(arr,n);
for(int i = 0; i < n; i++)
{
cout<<arr[i]<<" ";
}
return 0;
}
五、希尔排序(缩小增量排序)
思想:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序。
1. 增量h与n的关系:3*h+1 <= n ,并按此规律递减
2. 对于某个增量h,存在一组数据组成的子序列,进行插入排序
3. 当h = 1时,就成为直接插入排序,此时数据已经基本有序。
当n较小时,直接插入排序速度较快,当n较大时,希尔排序更具有优势。
希尔排序是不稳定的排序算法。
代码:
#include <iostream>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
void shellSort(int arr[], int n)
{
int h = 1;
while(h <= n)//生成初始增量
{
h = 3*h + 1;
}
while(h >= 1)
{
for(int i = h; i < n; i++)
{
int j = i - h;
int get = arr[i];
while(j >= 0 && arr[j] > get)
{//当前数据 < 前面间距为h的数据
arr[j + h] = arr[j];
j = j - h;
}
arr[j + h] = get;
}
h = (h - 1)/3; //递减增量
}
}
int main(int argc, char** argv) {
int n;
cin>>n;
int arr[n];
for(int i = 0; i < n; i++)
{
cin>>arr[i];
}
//希尔排序
shellSort(arr,n);
for(int i = 0; i < n; i++)
{
cout<<arr[i]<<" ";
}
return 0;
}
附加:全部for循环
//排序,希尔排序
for (gap = 3 * 3 / 2; gap > 0; gap /= 2){
for (m = gap; m < 9; ++m){
for (n = m - gap; n >= 0; n -= gap){
if (pixel[n] > pixel[n + gap])
swap(pixel[n], pixel[n + gap]);
}
}
}
六、归并排序
1.采用分治法,是一种稳定的排序算法。
2.递归归并
算法思想:
将序列一分为二,递归左边子序列,使其有序;递归右边子序列,使其有序;归并两个有序的子序列A,B,合并过程如下:
a. 比较两个序列的起始元素,谁小就取出谁放入辅助空间,并将其在原数组中删除。
b. 继续比较起始元素,知道其中一个子序列为空,将未空的子序列依次序取出放入辅助空间。
c. 将辅助空间的序列一次读入两个序列对应的位置。
#include <iostream>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
//合并两个已排好序的数组A[left...mid][mid+1...right]
void merge(int arr[],int left,int mid,int right)
{
int len = right - left + 1;
int *temp = new int[len]; //辅助空间
int index = 0;
int i = left; //A组起始元素
int j = mid + 1; //B组起始元素
while(i <= mid && j <= right)
{
//带等号保证归并排序的稳定性
temp[index] = arr[i] <= arr[j] ? arr[i++]:arr[j++];
index++;
}
while(i <= mid) temp[index++] = arr[i++] ;
while(j <= right) temp[index++] = arr[j++];
for(int k = 0; k < len; k++)
arr[left++] = temp[k];
}
//自上而下的递归归并排序
void mergeSort(int arr[], int left, int right)
{
if(left == right)
return;
int mid = (left + right) / 2;
mergeSort(arr,left,mid); //左边有序
mergeSort(arr,mid+1,right);//右边有序
merge(arr,left,mid,right); //合并
}
int main(int argc, char** argv) {
int n;
cin>>n;
int arr[n];
for(int i = 0; i < n; i++)
{
cin>>arr[i];
}
//归并排序
mergeSort(arr,0,n-1);
for(int i = 0; i < n; i++)
{
cout<<arr[i]<<" ";
}
return 0;
}
3.迭代归并.
依次向后寻找长度为i的数组,一分为2 ,进行归并。i每次训话2倍增长。
#include <iostream>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
//合并两个有序的子序列
void merge(int arr[],int left, int mid, int right)
{
int len = right - left + 1;
int *temp = new int[len];
int i = left;
int j = mid + 1;
int index = 0;
while(i <= mid && j <= right)
temp[index++] = arr[i] < arr[j] ? arr[i++]:arr[j++];
while(i <= mid)
temp[index++] = arr[i++];
while(j <= right)
temp[index++] = arr[j++];
for(int k = 0; k < len; k++)
arr[left++] = temp[k];
}
// 迭代实现归并排序
void mergeSort(int arr[], int len)
{
int left,mid,right;
for(int i = 1; i < len; i *= 2)
{//子数组大小初始为i,2倍增长
left = 0;
while(left + i < len)
{//后一个子数组存在需要归并
mid = left + i - 1;
//后一个子数组大小可能不够
right = mid + i < len ? mid+i:len-1;
//合并两个子数组
merge(arr,left,mid,right);
//前一个子数组索引向后移动
left = right+1;
}
}
}
int main(int argc, char** argv) {
int n;
cin>>n;
int arr[n];
for(int i = 0; i < n; i++)
{
cin>>arr[i];
}
//归并排序
mergeSort(arr,n);
for(int i = 0; i < n; i++)
{
cout<<arr[i]<<" ";
}
return 0;
}
七、快速排序
不稳定排序。
算法思想:
1. 选取数列第一个元素值,作为“基准元素”(pivot)
2. 从右到左依次遍历数列,比“基本元素”小,赋值给左指针指向的位置,左边指针右移;
从左向右依次遍历数列,比“基准元素”大,赋值给右指针指向的位置,右指针左移;
左右指针相遇或错过时,停止,此时“基准元素”就处在中间位置,左边比它小,右边比他大。
该过程称为“分区域”(partition)
3. 对左右两边的元素分别进行相同的“分区”递归排序。
代码:
#include <iostream>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
//分区
int partition(int arr[],int left, int right)
{
//选择最左边一个元素作为基准
int pivot = arr[left];
while(left < right)
{
//从右向左遍历数组,大于等于基准元素,指针向左移
while(left < right && arr[right] >= pivot) right--;
if(left < right)
{//移动到了小于基准元素的位置,且左指针在右指针左边
arr[left] = arr[right];
left++;
}
//从左向右
while(left < right && arr[left] < pivot) left++;
if(left < right)
{
arr[right] = arr[left];
right--;
}
}
arr[left] = pivot;
return left;
}
//递归实现快速排序
void quickSort(int arr[], int left,int right)
{
if(left < right)
{
int pivot = partition(arr,left,right);
quickSort(arr,left,pivot-1);
quickSort(arr,pivot+1,right);
}
}
int main(int argc, char** argv) {
int n;
cin>>n;
int arr[n];
for(int i = 0; i < n; i++)
{
cin>>arr[i];
}
//快速排序
quickSort(arr,0,n-1);
for(int i = 0; i < n; i++)
{
cout<<arr[i]<<" ";
}
return 0;
}
算法思想:
1.选择最左边的元素为“基准元素”
2.从左到右依次遍历,找小于“基准元素”的值
和“索引位置”处的值交换,索引位置右移,
最终索引位置的前一个位置即为“分区位置”。
3. 对左右两边的元素分别进行相同的“分区”递归排序。
int partition(int arr[],int left, int right)
{
//选择最左边一个元素作为基准
int pivot = left;
//索引从下一个元素开始比较
int index = pivot + 1;
for(int i = index; i <= right; i++)
{
if(arr[i] < arr[pivot])
{//找到一个小于"基准元素"的,和索引位置的元素交换,索引位置右移
swap(arr[i],arr[index]);
index++;
}
}
//最终索引位置的前一个位置即是"分区位置"
swap(arr[pivot],arr[index-1]);
return index-1;
}
八、堆排序
堆排序是指利用堆这种数据结构所设计的一种选择排序算法,是不稳定的排序算法。
堆是一种近似完全二叉树的结构(通常用一维数组来实现)。
以大顶堆为例,父结点的值总是大于它的孩子结点的值。
步骤:
1. 将初始待排序序列构建成大顶堆,为初始无序区。
2. 将堆顶元素A[1]和A[n]交换,得到新的无序区(A[1]...A[n-1]),且满足(A[1]...A[n-1])< A[N]。
3.此时新的堆顶可能违反大顶堆得性质,调整成新堆,将A[1]和A[n-1]交换,...
4.不断重复,直到有序区的元素个数为n-1。
#include <iostream>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
//建立大顶堆
void BuildHeap(int arr[],int start, int length)
{
int temp;
temp = arr[start];//保留父节点数据
for(int i = start*2; i <= length; i *= 2)//子节点:左孩子2i、右孩子2i+1
{
//找到左孩子和右孩子中的最大值及序号i
if( i<length && arr[i] < arr[i+1] ) i++;
//父节点数据大于孩子中的最大值,不做交换
if(temp >= arr[i]) break;
//否则,将最大值赋值给当前父节点
arr[start] = arr[i];
//保留被交换的结点的序号
start = i;
}
arr[start] = temp;//将最初的父节点数据赋值给最后被交换的位置
}
//大顶堆排序
void HeapSort(int arr[], int n)
{
//将无序数组构建成大顶堆
for(int i = n/2; i > 0; i--)
{
BuildHeap(arr,i,n);
}
//依次取堆顶数据,并重新大顶堆
for(int i = n; i > 1; i--)
{
//将堆顶数据 和 当前未经排序子序列的最后一个数据 交换
swap(arr[1],arr[i]);
//建造一个大顶堆
BuildHeap(arr,1,i-1);
}
}
int main(int argc, char** argv) {
int n;
cin>>n;
int arr[n];
for(int i = 1; i <= n; i++)
{
cin>>arr[i];
}
//大顶堆排序
HeapSort(arr,n);
for(int i = 1; i <= n; i++)
{
cout<<arr[i]<<" ";
}
return 0;
}
九、二叉树排序
二叉排序树满足三个条件:
(1)若左子树不空,则左子树上所有结点的值均小于它的根节点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根节点的值;
(3)左、右子树也分别为二叉排序树。
堆二叉排序树进行中序遍历的结果即为増序序列。
此代码引自:https://www.cnblogs.com/zhaoshuai1215/p/3448154.html
#include <iostream>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
struct BST{
int number; //保存数组元素的值
struct BST* left;
struct BST* right;
};
void insertBST(BST** tree, int v) {
if (*tree == NULL) {
*tree = new BST;
(*tree)->left=(*tree)->right=NULL;
(*tree)->number=v;
return;
}
if (v < (*tree)->number)
insertBST(&((*tree)->left), v);
else
insertBST(&((*tree)->right), v);
}
void printResult(BST* tree) {
if (tree == NULL)
return;
if (tree->left != NULL)
printResult(tree->left);
cout << tree->number << " ";
if (tree->right != NULL)
printResult(tree->right);
}
void createBST(BST** tree, int a[], int n) {
*tree = NULL;
for (int i=0; i<n; i++)
insertBST(tree, a[i]);
}
int main(int argc, char** argv) {
int n;
cin>>n;
int arr[n];
for(int i = 0; i < n; i++)
{
cin>>arr[i];
}
BST* root;
//二叉树构建
createBST(&root,arr,n);
//中序遍历
printResult(root);
return 0;
}
十、计数排序
及时排序不是基于比较的排序算法,故是稳定的排序算法。
线性时间复杂度。
要求输入的数据是有确定范围的整数,最好呈现聚集状态。
算法:
1. 找到待排序数组中的最大和最小元素;
2, 统计数组中每个值为i的元素出现的个数,存入数组C的第i项;
3. 对所有计数累加(从C的第一个元素开始,每一项和前一项相加);
4. 反向填充目标数组,将每个元素i防止在新数组的C(i)项,每放一个元素就将C(i)减一。
#include <iostream>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
//计数排序
void countSort(int arr[], int dst[],int n,int max,int min)
{
int range = max - min + 1;
int *counter = new int[range];
//计数器初始化
for(int i = 0; i < range; i++)
counter[i] = 0;
//开始计数
for(int i = 0; i < n; i++)
counter[arr[i] - min]++;
//累加计数器
for(int i = 1; i < range; i++)
counter[i] += counter[i-1];
//反赋值dst
for(int i = 0; i < n; i++)
{
int data = arr[i];
int index = counter[data - min];
dst[index] = data;
counter[data - min] --;
}
}
int main(int argc, char** argv) {
int n;
cin>>n;
int arr[n]; int max, min;
cin>>arr[0];
max = arr[0]; min = arr[0];
for(int i = 1; i < n; i++)
{
cin>>arr[i];
if(arr[i] > max) max = arr[i];
if(arr[i] < min) min = arr[i];
}
cout<<"max= "<<max<<" min= "<<min<<endl;
int dst[n];
//计数排序
countSort(arr,dst,n,max,min);
for(int i = 1; i <= n; i++)
{
cout<<dst[i]<<" ";
}
return 0;
}
十一、桶排序
计数排序也可以看作是桶排序的特例,数组关键字范围为N,划分为N个桶。
利用了函数的映射关系,高效与否的关键就在于这个映射函数。
工作的原理:假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排)。
算法步骤:
1. 设置一个定量的数组当作空桶(可以使用二维数组,这里使用的是vector<vector<int> >);
2. 遍历输入数据,并且把数据一个一个放到对应的桶里去;
3. 对每个不是空的桶进行排序(这里使用的直接插入排序);
4. 从不是空的桶里把排好序的数据拼接起来。
#include <iostream>
#include <vector>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
//桶排序
void bucketSort(int arr[], int n, int bucketsize, int max,int min)
{
//桶的初始化
int bucketCount = (max - min)/bucketsize + 1;
vector<vector<int> > bucket;
bucket.resize(bucketCount+1);
int index;
//利用映射函数将数据分配到各个桶中
for(int i = 0; i < n; i++)
{
index = (arr[i] - min) / bucketsize;
bucket[index].push_back(arr[i]);
}
//桶内排序
index = 0;
for(int i = 0; i < bucket.size(); i++)
{
//对桶内元素进行插入排序
int size = bucket[i].size();
int current;
for(int k = 1; k < size; k++)
{
current = bucket[i][k];
int m = k-1;
while(m >= 0 && bucket[i][m] > current)
{
bucket[i][m+1] = bucket[i][m];
m--;
}
bucket[i][m+1] = current;
}
//反赋值给数组
for(int k = 0; k < size; k++)
{
arr[index] = bucket[i][k];
index++;
}
}
}
int main(int argc, char** argv) {
int n;
cin>>n;
int arr[n]; int max, min;
cin>>arr[0];
max = arr[0]; min = arr[0];
for(int i = 1; i < n; i++)
{
cin>>arr[i];
if(arr[i] > max) max = arr[i];
if(arr[i] < min) min = arr[i];
}
cout<<"max= "<<max<<" min= "<<min<<endl;
//桶排序
bucketSort(arr,n,5,max,min);
for(int i = 0;i < n;i++)
{
cout<<arr[i]<<" ";
}
return 0;
}
十二、基数排序
思想:对数据选择多种基数,对每一种基数依次使用同排序。
步骤(以整数为例):
1. 从个位开始,根据0~9的值将数据分到10个桶里面,例如12会划分到2号桶。
2. 将0~9的10个桶的数据顺序放回数组中。
3. 从十位继续分放到10个桶中...重复上述过程,一直到高位。
该方法称为LSD(Least significant digital),还可以从高位到低位,叫做MSD。
#include <iostream>
#include <vector>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
//获取某个数字的第pos位的值
int getNumInPos(int num, int pos)
{
int temp = num;
int count = pos;
while(count > 1)
{
temp /= 10;
count--;
}
temp %= 10;
return temp;
}
//基数排序
void radixSort(int arr[], int n, int max)
{
//获取最大值的位数
int pos_size = 0;
int temp = max;
while(temp > 0)
{
temp /= 10;
pos_size++;
}
cout<<"pos_size = "<<pos_size<<endl;
//桶的初始化
int bucket_size = 10;//分别代表数字0,1,2,3,4,5,6,7,8,9
vector<vector<int> > bucket;
bucket.resize(bucket_size+1);
int index; int bucket_insize;
//从低位到高位逐位进行桶排序
for(int pos = 1; pos <= pos_size; pos++)
{
//获取pos位的数字,将数据分配到各个桶中
for(int i = 0; i < n; i++)
{
index = getNumInPos(arr[i],pos);
bucket[index].push_back(arr[i]);
}
//反赋值给数组
index = 0;
for(int i = 0; i < 10; i++)
{
bucket_insize = bucket[i].size();
for(int j = 0; j < bucket_insize; j++)
{
arr[index] = bucket[i][j];
index++;
}
bucket[i].clear();
}
//输出每轮桶排序的中间结果
cout<<"pos = "<<pos<<" ";
for(int i = 0;i < n;i++)
{
cout<<arr[i]<<" ";
}
cout<<endl;
}
}
int main(int argc, char** argv) {
int n;
cin>>n;
//int n = 15;
//int arr[15] = {3,54,2,11,18,41,221,8,39,4,7,63,13,6,5};
int arr[n];int max, min;
cin>>arr[0];
max = arr[0]; min = arr[0];
for(int i = 1; i < n; i++)
{
cin>>arr[i];
if(arr[i] > max) max = arr[i];
if(arr[i] < min) min = arr[i];
}
cout<<"max= "<<max<<" min= "<<min<<endl;
//基数排序
radixSort(arr,n,max);
for(int i = 0;i < n;i++)
{
cout<<arr[i]<<" ";
}
return 0;
}
以上排序算法的比较和分析
比较排序的时间复杂度:通常为O(n2)或者O(nlogn),比较排序的时间复杂度下界就是O(nlogn),
非比较排序的时间复杂度:可以达到O(n),但是都需要额外的空间开销。
非线性时间比较类排序:
通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此称为非线性时间比较类排序,常见的排序算法都是比较排序。
线性时间非比较类排序:
不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此称为线性时间非比较类排序。非比较排序包括计数排序、桶排序和基数排序;非比较排序对数据有要求,因为数据本身包含了定位特征,故可以不通过比较来确定元素的位置。
排序的稳定性和复杂度:
排序方法 | 平均情况 | 最好情况 | 最坏情况 | 辅助空间 | 稳定性 | 是否比较 |
冒泡排序 | ![]() | | ![]() | | 稳定 | 比较排序 |
简单选择排序 | ![]() | ![]() | 不稳定 | 比较排序 | ||
直接插入排序 | ![]() | ![]() | ![]() | ![]() | 稳定 | 比较排序 |
希尔排序 | ![]() | | ![]() | ![]() | 不稳定 | 比较排序 |
堆排序 | ![]() | ![]() | 不稳定 | 比较排序 | ||
归并排序 | ![]() | ![]() | 稳定 | 比较排序 | ||
二叉树排序 | ![]() | ![]() | 稳定 | 比较排序 | ||
快速排序 | ![]() | ![]() | ![]() | ![]() | 不稳定 | 比较排序 |
基数排序 | 取决于基数个数、桶个数、桶内排序算法 | ![]() | 不稳定 | 非比较排序 | ||
计数排序 |
| ![]() | 稳定 | 非比较 | ||
桶排序 | ![]() | | 稳定 | 非比较 |