十种常用排序算法总结
直接插入排序+折半插入排序+希尔排序+冒泡排序+快速排序+简单选择排序+堆排序(大根堆+小根堆)+归并排序+基数排序+桶排序+数组散列、集合模拟桶排序
稳定的有:直接插入、冒泡、归并、基数排序;
不稳定的:简单选择、希尔、快速、堆排序。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define req(i, a, b) for(int i=(a); i<=(b); i++)
#define ull unsigned __int64
#define sc(t) scanf("%d",&(t))
#define sc2(t,x) scanf("%d%d",&(t),&(x))
#define pr(t) printf("%d\n",(t))
#define pf printf
#define prk printf("\n")
#define pi acos(-1.0)
#define ms(a,b) memset((a),(b),sizeof((a)))
#define mc(a,b) memcpy((a),(b),sizeof((a)))
#define w while
#define vr vector
#define gr greater
typedef long long ll;
//next_permutation(arr, arr+size);全排列
//prev_permutation(arr, arr+size);
int n, a[100005];
void Insertsort()
{
int j;
req(i, 2, n)
{
if(a[i] < a[i-1])
{
a[0] = a[i];
for(j=i-1; a[0]<a[j]; j--)
a[j+1] = a[j];
a[j+1] = a[0];
}
}
}
void display()
{
req(i, 1, n)
printf("%d ",a[i]);
prk;
}
int main()
{
sc(n);
req(i, 1, n)
sc(a[i]);
Insertsort();
display();
return 0;
}
/*
input:
11
2 1 5 4 3 3 6 1 3 2 3
output:
1 1 2 2 3 3 3 3 4 5 6
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define req(i, a, b) for(int i=(a); i<=(b); i++)
#define ull unsigned __int64
#define sc(t) scanf("%d",&(t))
#define sc2(t,x) scanf("%d%d",&(t),&(x))
#define pr(t) printf("%d\n",(t))
#define pf printf
#define prk printf("\n")
#define pi acos(-1.0)
#define ms(a,b) memset((a),(b),sizeof((a)))
#define mc(a,b) memcpy((a),(b),sizeof((a)))
#define w while
#define vr vector
#define gr greater
typedef long long ll;
//next_permutation(arr, arr+size);全排列
//prev_permutation(arr, arr+size);
int n, a[100005];
void Half_Insertsort()
{
int j, low, high, mid;
req(i, 2, n)
{
a[0] = a[i];
low = 1, high = i-1;
while(low <= high)
{
mid = (low+high) >> 1;
if(a[mid] > a[0])
high = mid-1;
else low = mid+1;
}
for(j=i-1; j>=high+1; j--)
a[j+1] = a[j];
a[j+1] = a[0];
}
}
void display()
{
req(i, 1, n)
printf("%d ",a[i]);
prk;
}
int main()
{
sc(n);
req(i, 1, n)
sc(a[i]);
Half_Insertsort();
display();
return 0;
}
/*
input:
11
2 1 5 4 3 3 6 1 3 2 3
output:
1 1 2 2 3 3 3 3 4 5 6
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define req(i, a, b) for(int i=(a); i<=(b); i++)
#define ull unsigned __int64
#define sc(t) scanf("%d",&(t))
#define sc2(t,x) scanf("%d%d",&(t),&(x))
#define pr(t) printf("%d\n",(t))
#define pf printf
#define prk printf("\n")
#define pi acos(-1.0)
#define ms(a,b) memset((a),(b),sizeof((a)))
#define mc(a,b) memcpy((a),(b),sizeof((a)))
#define w while
#define vr vector
#define gr greater
typedef long long ll;
//next_permutation(arr, arr+size);全排列
//prev_permutation(arr, arr+size);
int n, a[100005];
void Shell_Insertsort() //是直接插入排序的改进
{
int j;
for(int d=n>>1; d>=1; d>>=1) //直接插入排序步长是1 ,这里改成逐步缩短为1的d
{
req(i, d+1, n)
{
if(a[i] < a[i-d]) //其余部分同直接插入一样,只是把步长为1的代码改成d
{ //相当于让没d个单位的数据组成新数组
a[0] = a[i];
for(j=i-d; a[j]>a[0]&&j>0; j-=d)
a[j+d] = a[j];
a[j+d] = a[0];
}
}
}
}
void display()
{
req(i, 1, n)
printf("%d ",a[i]);
prk;
}
int main()
{
sc(n);
req(i, 1, n)
sc(a[i]);
Shell_Insertsort();
display();
return 0;
}
/*
input:
11
2 1 5 4 3 3 6 1 3 2 3
output:
1 1 2 2 3 3 3 3 4 5 6
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define req(i, a, b) for(int i=(a); i<=(b); i++)
#define ull unsigned __int64
#define sc(t) scanf("%d",&(t))
#define sc2(t,x) scanf("%d%d",&(t),&(x))
#define pr(t) printf("%d\n",(t))
#define pf printf
#define prk printf("\n")
#define pi acos(-1.0)
#define ms(a,b) memset((a),(b),sizeof((a)))
#define mc(a,b) memcpy((a),(b),sizeof((a)))
#define w while
#define vr vector
#define gr greater
typedef long long ll;
//next_permutation(arr, arr+size);全排列
//prev_permutation(arr, arr+size);
int n, a[100005];
void Buddlesort()
{
rep(i, 1, n)
{
bool flag = false;
for(int j=n; j>i; j--)
{
if(a[j] < a[j-1])
{
swap(a[j-1],a[j]);
flag = true;
}
}
if(!flag) //某一遍没有发生交换时,则停止,减少时间浪费
break; //因此可以发现,数列有序后,冒泡排序仍需再一次遍历判断是否有序才可停止
}
}
void display()
{
req(i, 1, n)
printf("%d ",a[i]);
prk;
}
int main()
{
sc(n);
req(i, 1, n)
sc(a[i]);
Buddlesort();
display();
return 0;
}
/*
input:
11
2 1 5 4 3 3 6 1 3 2 3
output:
1 1 2 2 3 3 3 3 4 5 6
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define req(i, a, b) for(int i=(a); i<=(b); i++)
#define ull unsigned __int64
#define sc(t) scanf("%d",&(t))
#define sc2(t,x) scanf("%d%d",&(t),&(x))
#define pr(t) printf("%d\n",(t))
#define pf printf
#define prk printf("\n")
#define pi acos(-1.0)
#define ms(a,b) memset((a),(b),sizeof((a)))
#define mc(a,b) memcpy((a),(b),sizeof((a)))
#define w while
#define vr vector
#define gr greater
typedef long long ll;
//next_permutation(arr, arr+size);全排列
//prev_permutation(arr, arr+size);
int n, a[100005];
int partition(int low,int high)
{
int tem = a[low];
while(low < high)
{
while(a[high] > tem && high > low) high--;
a[low] = a[high]; //找到第一个比tem小的,放入low位置上
while(a[low] <= tem && low < high) low++;
a[high] = a[low]; //找到第一个比tem大的放入刚才空出来的high位置上
} //重复进行,low==high时停止循环,此时,比tem大的都去了tem右边,小的都在tem左边,则tem到达指定位置low==high
a[low] = tem;
return low;
}
void Quicksort(int low,int high)
{
int pos = partition(low, high); //快排一趟至少有一个元素到达指定位置,以此为分界线,分割成两部分,再排
if(pos-1 > low)
Quicksort(low, pos-1);
if(pos+1 < high)
Quicksort(pos+1, high);
}
void display()
{
req(i, 1, n)
printf("%d ",a[i]);
prk;
}
int main()
{
sc(n);
req(i, 1, n)
sc(a[i]);
Quicksort(1,n);
display();
return 0;
}
/*
input:
11
2 1 5 4 3 3 6 1 3 2 3
output:
1 1 2 2 3 3 3 3 4 5 6
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define req(i, a, b) for(int i=(a); i<=(b); i++)
#define ull unsigned __int64
#define sc(t) scanf("%d",&(t))
#define sc2(t,x) scanf("%d%d",&(t),&(x))
#define pr(t) printf("%d\n",(t))
#define pf printf
#define prk printf("\n")
#define pi acos(-1.0)
#define ms(a,b) memset((a),(b),sizeof((a)))
#define mc(a,b) memcpy((a),(b),sizeof((a)))
#define w while
#define vr vector
#define gr greater
typedef long long ll;
//next_permutation(arr, arr+size);全排列
//prev_permutation(arr, arr+size);
int n, a[100005];
void Selectsort()
{
req(i, 1, n-1)
{
int min = i;
req(j, i+1, n)
{
if(a[j] < a[min])
min = j;
}
if(min != i)
swap(a[i], a[min]);
}
}
void display()
{
req(i, 1, n)
printf("%d ",a[i]);
prk;
}
int main()
{
sc(n);
req(i, 1, n)
sc(a[i]);
Selectsort();
display();
return 0;
}
/*
input:
11
2 1 5 4 3 3 6 1 3 2 3
output:
1 1 2 2 3 3 3 3 4 5 6
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define req(i, a, b) for(int i=(a); i<=(b); i++)
#define ull unsigned __int64
#define sc(t) scanf("%d",&(t))
#define sc2(t,x) scanf("%d%d",&(t),&(x))
#define pr(t) printf("%d\n",(t))
#define pf printf
#define prk printf("\n")
#define pi acos(-1.0)
#define ms(a,b) memset((a),(b),sizeof((a)))
#define mc(a,b) memcpy((a),(b),sizeof((a)))
#define w while
#define vr vector
#define gr greater
typedef long long ll;
//next_permutation(arr, arr+size);全排列
//prev_permutation(arr, arr+size);
int n, a[100005];
void AdjustDown(int x, int m)
{
a[0] = a[x];
for(int i=x*2; i<=m; i*=2)
{
if(i<m && a[i]<a[i+1]) //取左右子节点中的较大者
i++;
if(a[0] >= a[i]) //即无需调整
break;
else
{
a[x] = a[i]; //如果子结点较大,将父子结点交换,继续往下调整
x = i;
}
}
a[x] = a[0];
}
void BuildMaxHeap()
{
for(int i=n/2; i>=1; i--) //从最小父节点往上调整
AdjustDown(i, n);
}
void Heapsort()
{
BuildMaxHeap();
for(int i=n; i>1; i--)
{
swap(a[i],a[1]); //每次输出一个a[1],即当时最大根,输出后与a[i]
AdjustDown(1,i-1); //即最后一个叶节点互换位置,重新调整1~i-1的剩余二叉树
}
//这样建的大根堆每次把最大值调整到最后,类似尾插,结束后的数组就是从小到大的有序序列
}
void display()
{
req(i, 1, n)
printf("%d ",a[i]);
prk;
}
int main()
{
sc(n);
req(i, 1, n)
sc(a[i]);
Heapsort();
display();
return 0;
}
/*
input:
11
2 1 5 4 3 3 6 1 3 2 3
output:
1 1 2 2 3 3 3 3 4 5 6
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define req(i, a, b) for(int i=(a); i<=(b); i++)
#define ull unsigned __int64
#define sc(t) scanf("%d",&(t))
#define sc2(t,x) scanf("%d%d",&(t),&(x))
#define pr(t) printf("%d\n",(t))
#define pf printf
#define prk printf("\n")
#define pi acos(-1.0)
#define ms(a,b) memset((a),(b),sizeof((a)))
#define mc(a,b) memcpy((a),(b),sizeof((a)))
#define w while
#define vr vector
#define gr greater
typedef long long ll;
//next_permutation(arr, arr+size);全排列
//prev_permutation(arr, arr+size);
//只有两个地方跟建大根堆不一样
int n, a[100005];
void AdjustDown(int x, int m)
{
a[0] = a[x];
for(int i=x*2; i<=m; i*=2)
{
if(i<m && a[i]>a[i+1]) //第一个,找左右子节点较小者
i++;
if(a[0] <= a[i]) //第二个,较小的作为父节点
break;
else
{
a[x] = a[i];
x = i;
}
}
a[x] = a[0];
}
void BuildMaxHeap()
{
for(int i=n/2; i>=1; i--)
AdjustDown(i, n);
}
void Heapsort()
{
BuildMaxHeap();
for(int i=n; i>1; i--)
{
swap(a[i],a[1]);
AdjustDown(1,i-1);
}
}
void display()
{
req(i, 1, n)
printf("%d ",a[i]);
prk;
}
int main()
{
sc(n);
req(i, 1, n)
sc(a[i]);
Heapsort();
display();
return 0;
}
/*
input:
11
2 1 5 4 3 3 6 1 3 2 3
output:
1 1 2 2 3 3 3 3 4 5 6
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define req(i, a, b) for(int i=(a); i<=(b); i++)
#define ull unsigned __int64
#define sc(t) scanf("%d",&(t))
#define sc2(t,x) scanf("%d%d",&(t),&(x))
#define pr(t) printf("%d\n",(t))
#define pf printf
#define prk printf("\n")
#define pi acos(-1.0)
#define ms(a,b) memset((a),(b),sizeof((a)))
#define mc(a,b) memcpy((a),(b),sizeof((a)))
#define w while
#define vr vector
#define gr greater
typedef long long ll;
//next_permutation(arr, arr+size);全排列
//prev_permutation(arr, arr+size);
int n, a[100005];
void Merge(int low,int mid,int high)
{
int b[high+5];
req(i, low, high)
b[i] = a[i];
int i, j, k;
for(i=low,j=mid+1,k=low;i<=mid&&j<=high;k++)
{
if(b[i] < b[j]) a[k] = b[i++]; //按序合并
else a[k] = b[j++];
}
while(i<=mid) a[k++] = b[i++]; //合并剩余部分
while(j<=high) a[k++] = b[j++];
}
void Mergesort(int low,int high)
{
if(low < high) //不断割裂成两部分,排序后合并
{
int mid = (low+high) >> 1;
Mergesort(low,mid);
Mergesort(mid+1,high);
Merge(low,mid,high);
}
}
void display()
{
req(i, 1, n)
printf("%d ",a[i]);
prk;
}
int main()
{
sc(n);
req(i, 1, n)
sc(a[i]);
Mergesort(1,n);
display();
return 0;
}
/*
input:
11
2 1 5 4 3 3 6 1 3 2 3
output:
1 1 2 2 3 3 3 3 4 5 6
*/
r是关键字种类,d是分组,n是元素个数,如一组数据15、233、168,r=6,因为出现了1、2、3、5、6、8,这六个关键字,d=3,因为最高位是百位,需要将关键字拆分为3组,第一组{5、3、8},第二组{1、3、6},第三组{0,2,1},n=3,因为有15、233、168三个数据,辅助空间是O®是因为基数排序按关键字种类存在对应队列中
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define req(i, a, b) for(int i=(a); i<=(b); i++)
#define ull unsigned __int64
#define sc(t) scanf("%d",&(t))
#define sc2(t,x) scanf("%d%d",&(t),&(x))
#define pr(t) printf("%d\n",(t))
#define pf printf
#define prk printf("\n")
#define pi acos(-1.0)
#define ms(a,b) memset((a),(b),sizeof((a)))
#define mc(a,b) memcpy((a),(b),sizeof((a)))
#define w while
#define vr vector
#define gr greater
typedef long long ll;
//next_permutation(arr, arr+size);全排列
//prev_permutation(arr, arr+size);
//基数排序有MSD:最高位优先 和 LSD:最低位优先两种
//取决于基数如只出现1 2 3 4 5,则只需要五个队列
//显然现实排序没这么简单,所以用0~9十个队列
int n, a[100005];
vector<int> q[10];
void display();
void Base() //将每个队列按基数排序的加入原数组,原数组顺序得以改变
{ //出于基数排序具有稳定性,下一轮相同数字的前后顺序就不会再调整了
int k = 1;
req(i, 0, 9)
{
rep(j, 0, q[i].size())
a[k++] = q[i][j];
}
}
void Basesort(int d)
{
req(i, 0, 9) //每轮将上轮数据清空
q[i].clear();
int res = 0;
req(i, 1, n) //d=1象征个位,d=10,象征十位,依次取位置
{
int x = a[i];
x /= d; //如2723/100=27;27%10=7,就取到了百位上的数字
if(x == 0) //判断该数是不是已经不够取了,中间有0和不够取是不一样的,要分清
res++;
x %= 10;
q[x].push_back(a[i]); //将a[i]这个数加入到对应队列中
}
Base();
if(res != n) //即如果不是所有数都取不到了,就意味着还有数有位数,需要继续排序
Basesort(d*10);
}
void display()
{
req(i, 1, n)
printf("%d ",a[i]);
prk;
}
int main()
{
sc(n);
req(i, 1, n)
sc(a[i]);
Basesort(1);
display();
return 0;
}
/*
input:
11
2 1 5 4 3 3 6 1 3 2 3
output:
1 1 2 2 3 3 3 3 4 5 6
intput:
7
329 457 657 839 436 720 355
output:
329 355 436 457 657 720 839
intput:
16
88 883 882 885 8 882 88881 2 19 235 15 883 100000000 100000001 23 89
output:
2 8 15 19 23 88 89 235 882 882 883 883 885 88881 100000000 100000001
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define req(i, a, b) for(int i=(a); i<=(b); i++)
#define ull unsigned __int64
#define sc(t) scanf("%d",&(t))
#define sc2(t,x) scanf("%d%d",&(t),&(x))
#define pr(t) printf("%d\n",(t))
#define pf printf
#define prk printf("\n")
#define pi acos(-1.0)
#define ms(a,b) memset((a),(b),sizeof((a)))
#define mc(a,b) memcpy((a),(b),sizeof((a)))
#define w while
#define vr vector
#define gr greater
typedef long long ll;
//next_permutation(arr, arr+size);全排列
//prev_permutation(arr, arr+size);
//这两个太简单,放在一起写了
//不过要注意,数组排序是集合、散列的运用,输入数据x不能大于数组边界n
int n, a[100005];
void Mapsort()
{
map<int,int> m;
int x;
sc(n);
req(i, 1, n) //可以直接输入到桶里,我这里为了方便和格式一致,保持前面的输入
{
sc(x);
m[x]++; //数据出现一次加一次
}
puts("\nresult for Map:");
//类似于for(int i=1; i
for(map<int,int>::iterator it=m.begin(); it!=m.end(); it++)
{
while(it->second) //first指向元素,second指向个数
{
printf("%d ",it->first);
it->second--;
}
}
prk;prk;
}
void Numsort()
{
int x;
sc(n);
req(i, 1, n) //这里把元素视作下标,所以x<=n
{
sc(x);
a[x]++;
}
puts("\nresult for Num:");
req(i, 1, n) //map中没出现过的数据不会在遍历过程中遇到,数组的话只能从头判断
{
while(a[i])
{
printf("%d ",i);
a[i]--;
}
}
prk;
}
int main()
{
Mapsort(); //桶排序
Numsort(); //数组排序
return 0;
}
/*
input:
11
2 1 5 4 3 3 6 1 3 2 3
11
2 1 5 4 3 3 6 1 3 2 3
output:
result for Map:
1 1 2 2 3 3 3 3 4 5 6
result for Num:
1 1 2 2 3 3 3 3 4 5 6
*/