一. 冒泡排序
原理:比较相邻的元素,若前一个元素比后一个元素大,交换两个元素的位置;对每对相邻元素做一样的操作,从第一对到最后一对,最终最后的元素就是最大值。
初始 4 5 6 3 2 1
1 4 5 3 2 1 6
2 4 3 2 1 5 6
3 3 2 1 4 5 6
4 2 1 3 4 5 6
5 1 2 3 4 5 6
vector<int> BubbleSort(vector<int> &a){
for(int i=a.size()-1;i>=0;i--){
for(int j=0;j<i;j++){
if(a[j]>a[j+1]){
int tmp=a[j];
a[j]=a[j+1];
a[j+1]=tmp;
}
}
}
return a;
}
最坏情况下 比较次数 ,交换次数
时间复杂度 稳定排序
二. 选择排序
原理:每次遍历都假设第一个索引处的元素最小,和其他索引处的值进行比较,如果当前索引处的值大于其他某处索引的值,假定其他某处索引的值为最小值,最后可以找到最小值所在索引;交换第一个索引处和最小值所在索引处的值。
原始 4 6 8 7 9 2 10 1
1 1 6 8 7 9 2 10 4
2 1 2 8 7 9 6 10 4
3 1 2 4 7 9 6 10 8
4 1 2 4 6 9 7 10 8
5 1 2 4 6 7 9 10 8
6 1 2 4 6 7 8 10 9
7 1 2 4 6 7 8 9 10
vector<int> SelectSort(vector<int> &a){
for(int i=0;i<a.size()-1;i++){
int min=i;
for(int j=i+1;j<a.size();j++){
if(a[j]<a[min]) min=j;
}
if(min!=i){
int tmp=a[i];
a[i]=a[min];
a[min]=tmp;
}
return a;
}
最坏情况下 比较次数 ,交换次数
时间复杂度 不稳定排序
三.插入排序
原理:把所有元素分为已排序和未排序;找到未排序的第一个元素,向已排序的组中进行插入;倒叙遍历已排序元素,一次和待插入的元素进行比较,直到找到一个元素小于等于待插入元素,那么久把待插入元素放到这个位置,其他位置元素向后移动一位。
初始 4 3 2 10 12 1 5 6
1 3 4 2 10 12 1 5 6 3
2 2 3 4 10 12 1 5 6 2
3 2 3 4 10 12 1 5 6 10
4 2 3 4 10 12 1 5 6 12
5 1 2 3 4 10 12 5 6 1
6 1 2 3 4 5 10 12 6 5
7 1 2 3 4 5 6 10 12 6
vector<int> InsertSort(vector<int> &a){
for(int i=1;i<a.size();i++){
for(int j=i;j>=0;j--){
if(a[j-1]>a[j]){
int tmp=a[j-1];
a[j-1]=a[j];
a[j]=tmp;
}
else break;
}
}
}
最坏情况下 比较次数 ,交换次数
时间复杂度 稳定排序
四. 希尔排序
原理:对插入排序进行改进
选定一个增长量h,按照h作为数据分组依据,对数据进行分组;对分好组的每组数据完成插入排序;减小增长量,最小减为1,重复第二步操作。
原始: 9 1 2 5 7 4 8 6 3 5
h=5 9 1 2 5 7 4 8 6 3 5
4 1 2 3 5 9 8 6 5 7
h=2 4 1 2 3 5 9 8 6 5 7
2 1 4 3 5 6 5 7 8 9
h=1 2 1 4 3 5 6 5 7 8 9
1 2 3 4 5 5 6 7 8 9
vector<int> ShellSort(vector<int>&a){
int n=a.size();
//确定增量
int h=1;
while(h<=n/2){
h=h*2+1;
}
while(h>=1){
for(int i=h;i<a.size();i++){
for(int j=i;j>=h;j-=h){
if(a[j]<a[j-h]){
int tmp=a[j-h];
a[j-h]=a[j];
a[j]=tmp;
}
else break;
}
}
h=h/2;
}
return a;
}
不稳定排序
五. 归并排序
原理:尽可能将一组数据拆分成两个元素数目相等的子组,并对每个子组继续拆分,直至拆分后的每个子组元素数目为1;将相邻的两个子组进行合并成一个有序的大组;不断重复合步骤并直至最终只有一个组为止。
8 4 5 7 1 3 6 2
8 4 5 7 1 3 6 2
8 4 5 7 1 3 6 2
8 4 5 7 1 3 6 2
4 8 5 7 1 3 2 6
4 5 7 8 1 2 3 6
1 2 3 4 5 6 7 8
void MergeSort(vector<int> &a){
int r=a.size()-1;
int l=0;
Sort(a,l,r);
}
void Sort(vector<int> &a,int l,int r){
if(r<=l){retun;}
int m=l+(r-l)/2;
Sort(a,l,m);
Sort(a,m+1,r);
Merge(a,l,m,r);
}
void Merge(vector<int> &a,int l,int m,int r){
vector<int> a1(a.size());
int p1=l,p2=m,i=l;
while(p1<=m&&p2<=r){
if(a[p1]<a[p2]{
a1[i++]=a[p1++];
}
else{
a1[i++]=a[p2++];
}
}
while(p1<=m1){
a1[i++]=a[p1++];
}
while(p2<=r){
a1[i++]=a[p2++];
}
for(int j=l;j<=r;j++)
{ a[j]=a1[j];}
}
稳定排序
六. 快速排序
原理:设置一个分界值,通过分界值将数组分为左右两部分;将大于或等于分界值的数据放到数组的右边,小于分界值的放在数组的左边。此时左边部分中各元素小于或等于分界值,而右边部分中各元素都大于或等于分界值;左边右边的数据可以独立排序。对于左侧的数据也可以取一个分界值,将该部分分成左右两部分,同样左边放置较小值,右边放置较大值,同样右侧的数据也可以做类似操作。通过递归完成左侧部分排序后,再递归右侧部分排序,当左右两部分数据均排好后,整个数组排序完成。
6 1 2 7 9 3 4 5 8
3 1 2 4 5 6 9 7 8
3 1 2 4 5 9 7 8
2 1 3 4 5 8 7 9
1 2 4 5 7 8
1 2 3 4 5 7 8 9
1 2 3 4 5 6 7 8 9
void QuickSort(vector<int> &a){
int l=0;
int r=a.size()-1;
sort(a,l,r);
}
void Sort(vector<int> &a,int l,int r){
if(l>=r) return;
//分组,左子组右子组均有序
int pa=Partition(a,l,r);
Sort(a,l,p-1);
Sort(a,p+1,r);
}
int Partition(vector<int> &a,int l int r){
int num=a[l]; // 分界值
int pl=l,pr=r+1;
while(true){
while(a[pr]>num){
if(pl==pr) break;
else pr--;
}
while(a[pl]<num){
if(pl==pr) break;
else pl++;
}
if(pl>=pr) break;
else{
swap(a.begin()+pl,a.begin()+pr);
}
}
swap(a.begin()+l,a.begin()+pr);
return pr;
}
不稳定排序