*PS:整理自小蓝课件qwq
选择排序
基本思想:每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在待排序的数列的最前,直到全部待排序的数据元素排完
优:稳定
缺:慢
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int n;
int a[100010];
void SelectSort()
{
for(int i=1;i<n;++i)
{
int k=i;
for(int j=i+1;j<=n;++j)
if(a[j]<a[k]) k=j;
if(k!=i) swap(a[i],a[k]);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
SelectSort();
for(int i=1;i<=n;++i)
printf("%d ",a[i]);
return 0;
}
冒泡排序
从1到n依次比较相邻的两个数,把大的放前面,小的放后面。第一遍排序结束时,最小的一定排到最后。重复上述过程,仍从第1个数开始交换,直到交换到倒数第2个数……
由于在排序过程中总是大数往前,小数往后,相当气泡上升,所以叫冒泡排序。
优化:设置一个bool变量判断当前有无排好序。
优:稳定
缺:慢
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int n;
int a[100010];
void Sort()
{
int l=n;
bool change;
do
{
change=false;
for(int i=1;i<l;++i)
if(a[i]<a[i+1])
{
swap(a[i],a[i+1]);
change=true;
}
--l;
}while(change);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
Sort();
for(int i=1;i<=n;++i)
printf("%d ",a[i]);
return 0;
}
桶排序
思想:若待排序的记录的关键字在一个明显有限范围内(整型)时,可设计有限个有序桶,每个桶装入一个值(当然也可以装入若干个值),顺序输出各桶的值,将得到有序的序列。
优:思想简单,代码容易实现
缺:排序的数字小。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int n,k;
int a[1010];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&k);
++a[k];
}
for(int i=0; i<=1000;i++)
while(a[i]>0)
{
printf("%d ",a[i]);
--a[i];
}
return 0;
}
插入排序
思想:维护有序区1~i,每次插入第i+1个元素并维护有序性,直到1~n变为一个有序区。其算法的时间复杂性为O(n2)插入排序适用于原先数据已经排列好,插入一个新数据的情况。
优:
缺:慢。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int n;
int a[100010];
void InsertSort()
{
for(int i=2;i<=n;++i)
{
int k=a[i],j=i-1;
while(k<a[j])
{
a[j+1]=a[j];
--j;
}
a[j+1]=k;
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
InsertSort();
for(int i=1;i<=n;++i)
printf("%d ",a[i]);
return 0;
}
快速排序
快速排序是对冒泡排序的一种改进。它的基本思想是:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。O(nlog2n)。
优:速度快
缺:不稳定
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int n;
int a[100010];
void qsort(int L,int R)
{
int l=L,r=R;
int k=a[(l+r)>>1];
while(l<=r)
{
while(a[l]<k) ++l;
while(a[r]>k) --r;
if(l<=r) swap(a[l],a[r]),++l,--r;
}
if(l<R) qsort(l,R);
if(L<r) qsort(L,r);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
qsort(1,n);
for(int i=1;i<=n;++i)
printf("%d ",a[i]);
return 0;
}
归并排序
将两个或两个以上有序的数列(或有序表),合并成一个仍然有序的数列(有序表),这种操作称为归并操作。这样的方法经常用于多个有序的数据文件归并成一个有序的数据文件。若将两个有序表合并成一个有序表则称为二路归并,同理,有三路归并、四路归并等。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int n;
int a[100010],b[100010];
void Done(int l,int mid,int r)
{
int i=l,j=mid+1,k=l-1;
while(i<=mid&&j<=r)
{
if(a[i]<a[j]) b[++k]=a[i],++i;
else b[++k]=a[j],++j;
}
while(i<=mid) b[++k]=a[i],++i;
while(j<=r) b[++k]=a[j],++j;
for(i=l;i<=r;++i)
a[i]=b[i];
}
void MergeSort(int l,int r)
{
if(l==r) return ;
int mid=(l+r)>>1;
MergeSort(l,mid);
MergeSort(mid+1,r);
Done(l,mid,r);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
MergeSort(1,n);
for(int i=1;i<=n;++i)
printf("%d ",a[i]);
return 0;
}
堆排序
不断弹出堆顶元素。
(偷懒直接粘上堆的模板)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int N;
int a[100010];
void creat(int n)
{
int k,f=1;
while((n<<1)<=N&&f)
{
k=n;
if((n<<1)<=N&&a[n<<1]<a[k]) k=n<<1;
if((n<<1|1)<=N&&a[n<<1|1]<a[k]) k=n<<1|1;
if(k!=n) swap(a[n],a[k]),n=k;
else f=0;
}
}
void make()
{
for(int i=N/2;i>=1;--i)
creat(i);
}
int ask_top()
{
return a[1];
}
void pop()
{
swap(a[1],a[N]),--N;
creat(1);
}
bool empty()
{
if(!N) return true;
return false;
}
void Sort()
{
int l=N;
while(N) pop();
for(int i=l;i>=1;--i)
printf("%d ",a[i]);
}
int size()
{
return N;
}
void push(int k)
{
++N;
int n=N,f=1;
a[n]=k;
if(n==1) return;
while(n>1&&f)
{
if(a[n]<a[n>>1]) swap(a[n],a[n>>1]);
else f=0;
n>>=1;
}
return;
}
int main()
{
scanf("%d",&N);
for(int i=1;i<=N;++i)
scanf("%d",&a[i]);
make();
Sort();
return 0;
}
STL
函数名 | 功能描述 |
---|---|
sort | 对给定区间所有元素进行排序 |
stable_sort | 对给定区间所有元素进行稳定排序 |
partial_sort | 对给定区间所有元素部分排序 |
partial_sort_copy | 对给定区间复制并排序 |
nth_element | 找出给定区间的某个位置对应的元素 |
is_sorted | 判断一个区间是否已经排好序 |
partition | 使得符合某个条件的元素放在前面 |
stable_partition | 相对稳定的使得符合某个条件的元素放在前面 |
各种排序算法的比较
- 稳定性比较
(排序的稳定性是指如果在排序的序列中,存在前后相同的两个元素的话,排序前和排序后他们的相对位置不发生变化)
插入排序、冒泡排序、二叉树排序、归并排序及其他线形排序是稳定的。
选择排序、希尔排序、快速排序、堆排序是不稳定的。 - 时间复杂度比较
插入排序、冒泡排序、选择排序的时间复杂性为O(n2);快速排序、堆排序、归并排序的时间复杂性为O(nlog2n);桶排序的时间复杂性为O(n);
*在最好情况下,直接插入排序和冒泡排序最快;在平均情况下,快速排序最快;在最坏情况下,堆排序和归并排序最快。