内 部 排 序 { 插 入 排 序 : 直 接 插 入 排 序 , 希 尔 排 序 交 换 排 序 : 冒 泡 排 序 , 快 速 排 序 选 择 排 序 : 简 单 选 择 排 序 , 堆 排 序 合 并 排 序 分 配 排 序 : 桶 排 序 , 基 数 排 序 内部排序 \begin{cases} 插入排序: 直接插入排序,希尔排序\\ 交换排序 : 冒泡排序,快速排序\\ 选择排序: 简单选择排序,堆排序\\ 合并排序 \\ 分配排序:桶排序,基数排序 \end{cases} 内部排序⎩⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎧插入排序:直接插入排序,希尔排序交换排序:冒泡排序,快速排序选择排序:简单选择排序,堆排序合并排序分配排序:桶排序,基数排序
算法 | 最好时间复杂度 | 最坏时间复杂度 | 平均时间复杂度 | 空间复杂度 | 稳定性 |
---|---|---|---|---|---|
插入排序 | O ( n ) O(n) O(n) | O ( n 2 ) O(n^2) O(n2) | O ( n 2 ) O(n^2) O(n2) | O ( 1 ) O(1) O(1) | 稳定 |
希尔排序 | - | - | O ( n 1.3 ) O(n^{1.3}) O(n1.3) | O ( 1 ) O(1) O(1) | 不稳定 |
冒泡排序 | O ( n ) O(n) O(n) | O ( n 2 ) O(n^2) O(n2) | O ( n 2 ) O(n^2) O(n2) | O ( 1 ) O(1) O(1) | 稳定 |
快速排序 | O ( n l o g n ) O(nlogn) O(nlogn) | O ( n 2 ) O(n^2) O(n2) | O ( n l o g n ) O(nlogn) O(nlogn) | O ( l o g n ) O(logn) O(logn) | 不稳定 |
选择排序 | O ( n 2 ) O(n^2) O(n2) | O ( n 2 ) O(n^2) O(n2) | O ( n 2 ) O(n^2) O(n2) | O ( 1 ) O(1) O(1) | 不稳定 |
堆排序 | O ( n l o g n ) O(nlogn) O(nlogn) | O ( n l o g n ) O(nlogn) O(nlogn) | O ( n l o g n ) O(nlogn) O(nlogn) | O ( 1 ) O(1) O(1) | 不稳定 |
归并排序 | O ( n l o g n ) O(nlogn) O(nlogn) | O ( n l o g n ) O(nlogn) O(nlogn) | O ( n l o g n ) O(nlogn) O(nlogn) | O ( n ) O(n) O(n) | 稳定 |
桶排序 | O ( n ) O(n) O(n) | O ( n 2 ) O(n^2) O(n2) | O ( n 2 ) O(n^2) O(n2) | O ( m + n ) O(m+n) O(m+n) | 稳定 |
基数排序 | − - − | − - − | − - − | − - − | 稳定 |
算法内容:
1)待排序数列存储在数组arr[n]
中,把数组的首元素看作一个有序数列。
2)依次将arr[i](i = 1....n-1)
插入已经排好序的序列r[0…i-1] 中,并保持有序性。
代码:
#include
#include
using namespace std;
//直接插入排序
void StraightSort(int *arr,int n) //升序
{
int temp = arr[0];
for(int i = 1;i<n;i++)
{
int j = 0;
if(arr[i] < arr[i-1]) //小于才有故事发生
{
temp = arr[i];
arr[i] = arr[i-1]; //向后挪动
for(j = i-2; temp<arr[j] && j>=0 ;j--)
{
arr[j+1] = arr[j];
}
arr[j+1] = temp;
}
}
}
int main()
{
//从txt中读取测试数据
int array[20] = {0};
int num_count = 0;
string path = "D:\\code\\cpp\\cpp_proj\\algorithms\\Sort\\num.txt";
fstream test_file;
test_file.open(path,ios::in);
if(!test_file)
{
cout<<"open failed!"<<endl;
}
cout<<"input num_count : ";
test_file>>num_count;
cout<< num_count<<endl;
cout<<"input num:"<<endl;
for(int i = 0;i<num_count;i++)
{
test_file>>array[i];
cout<<array[i]<<"\t";
}
cout<<endl;
//排序
StraightSort(array,10);
//显示
for(int i = 0;i<num_count;i++)
{
cout<<array[i]<<"\t";
}
cout<<endl;
return 0;
}
测试数据
10
12 2 16 30 28 10 16 20 6 18
希尔排序是直接插入排序的改进,从减少排序元素个数,使序列基本有序,进行改进。
算法内容:
1)待排序数列存储在数组arr[n]
中,增量序列为( d 1 , d 2 , . . . , d t d_1,d_2,...,d_t d1,d2,...,dt), n > d 1 > d 2 > . . . > d t = 1 n>d_1> d_2>...>d_t=1 n>d1>d2>...>dt=1。
2)依次以 d i d_i di 为间隔,进行直接插入排序。
3)最后一次取 d t = 1 d_t = 1 dt=1 进行直接插入排序。
代码:
void ShellInsert(int *arr,int n,int dk)
{
int temp = arr[0];
for(int i = dk;i<n;i++)
{
int j = 0;
if(arr[i]<arr[i-dk])
{
temp = arr[i];
arr[i] = arr[i-dk];
for(j = i-dk;temp<arr[j] && j>=0;j-=dk)
{
arr[j+dk] = arr[j];
}
arr[j+dk] = temp;
}
}
}
void ShellSort(int *arr,int n,int *dt,int t)
{
for(int i = 0;i<t;i++)
{
ShellInsert(arr,n,dt[i]);
}
}
算法内容:
1)n个数据比较n-1趟,每趟比较n-i次,i 为趟数。
代码:
void BubbleSort(int *arr,int n)
{
for(int i = 0;i<n-1;i++) //趟数
{
for(int j = 0;j<n-i-1;j++) //次数
{
if(arr[j]>arr[j+1])
{
arr[j] = arr[j] +arr[j+1];
arr[j+1] = arr[j] - arr[j+1];
arr[j] = arr[j] - arr[j+1];
}
}
}
}
j算法内容:
1)取出数组中的首元素作为基准,定义两个索引 i = low,j = high
。
2)从右向左扫描,找到小于基准的数,然后交换 arr[i],arr[j],i++
其实arr[i]
就是基准
3)从左向右扫描,找到大于基准的数,然后交换 arr[i],arr[j],j--
其实arr[j]
就是基准
4) 重复 2,3 直到 i == j
,返回mid = i
.
5) 在以mid
为界对左右两个子序列重复以上步骤排序。
代码:
int Partition(int *arr,int low,int high)
{
int temp = arr[low];
int i = low;
int j = high;
while(i<j)
{
while(i<j && arr[j] > temp)
j--;
if(i<j)
{`
int t = arr[j];
arr[j] = arr[i];
arr[i] = t;
i++;
}
while(i<j && arr[i] <= temp)
i++;
if(i<j)
{
int t = arr[j];
arr[j] = arr[i];
arr[i] = t;
j--;
}
}
return i;
}
void QuickSort(int *arr,int low,int high)
{
int mid = 0;
if(low < high)
{
mid = Partition(arr,low,high);
QuickSort(arr,low,mid-1);
QuickSort(arr,mid+1,high);
}
}
算法内容:
1)设待排序的元素存储在数组arr[n]
中,首先选择数组中的最小元素记录为arr[min]
然后与arr[1]
交换
2) 然后从arr[2] - arr[n-1]
中选择最小,与arr[2]
交换 ,
3)重复以上过程,n-1
趟排序。
代码:
//直接选择排序
void SelectSort(int *arr,int n)
{
for(int i = 0;i<n-1;i++)
{
int min = i;
for(int j = i+1;j<n;j++)
{
if(arr[j]<arr[min])
{
min = j;
}
}
if(min != i)
{
int temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
}
}
}
算法内容:
1)分解,将待排序的序列分成规模大致相等的两个序列
2)对两个子序列进行合并排序
3)将排序好的有序子序列进行合并,得到最终序列。
代码:
void Merge(int *arr,int low,int mid,int high)
{
int *B = new int [high-low+1];
int i = low,j = mid+1,k = 0;
while(i <= mid && j <= high)
{
if(arr[i] <= arr[j])
B[k++] = arr[i++];
else
B[k++] = arr[j++];
}
while(i<=mid)
B[k++] = arr[i++];
while(j<=high)
B[k++] = arr[j++];
for(i = low,k = 0;i<=high;i++)
{
arr[i] = B[k++];
}
delete []B;
}
void MergeSort(int *arr,int low,int high)
{
if(low < high)
{
int mid = (low + high) / 2;
MergeSort(arr,low,mid);
MergeSort(arr,mid+1,high);
Merge(arr,low,mid,high);
}
}