第八单元 排序
一、定义
将一组杂乱无章的数据,通过一定的方法按顺序排列。
二、分类
1.稳定排序:假设在一组待排序的数据中,存在多个元素具有相同的关键字,在用某种排序法排序后,若这些元素的相对次序仍然不变,则这种排序方法是稳定的。例如:冒泡排序,基数排序,二叉树排序,归并排序。
2.不稳定排序:假设在一组待排序的数据中,存在多个元素具有相同的关键字,在用某种排序法排序后,若这些元素的相对次序会改变,则这种排序方法是不稳定的。例如:选择排序,快速排序,桶排序,堆排序, 希尔排序。
3.若整个排序过程不需要访问其它存储空间便能完成,则这种排序方法是内部排序。
4.若整个排序过程不访问其它存储空间无法完成,则这种排序方法是外部排序。
三、冒泡排序
1.方法:
(1)比较第一个数与第二个数,若为逆序a[0]>a[1],则交换;然后比较第二个数与第三个数;依次类推……直至第n-1个数和第n个数比较为止。第一趟冒泡排序,结果最大的数被安置在最后一个元素位置上。
(2)对前n-1个数进行第二趟冒泡排序,结果使次大的数被安置在第n-1个元素位置。
(3)重复上述过程,共经过n-1趟冒泡排序后,排序结束。
2.时间复杂度:O(n2)。
3.优点:稳定,错误率低。
4.缺点:速度慢。
四、选择排序
1.方法:不断扫描数据,每次将找出的最小(或最大)的一个元素和待排序的数据中的第一个(或最后一个)元素交换。
2.时间复杂度:O(n2)。
3.优点:错误率低。
4.缺点:不稳定,速度慢。
五、快速排序
1.方法:已知一组杂乱无章的数据a[1]、a[2]……a[n],需将其按升序排列。首先任取数据a[x]作为基准。比较a[x]与其它数据并排序,使a[x]排在数据的第k位,并且使a[1]~a[k-1]中的每一个数据<a[x],a[k+1]~a[n]中的每一个数据>a[x],然后分别对a[1]~a[k-1]和a[k+1]~a[n]两组数据进行快速排序。
2.优化:每次快速排序时,用随机数选取基准,避免特殊数据。
3.时间复杂度:一般情况O(n log n)。
4.优点:速度快。
5.缺点:不稳定。
#include<cstdio>
int a,i,m,x[100000]={0};
void kp(int j,int k)
{
int b,c,d,e,f;
b=j+(k-j)/2;
c=x[b];
x[b]=x[j];
x[j]=c;
e=j;
f=k;
d=1;
while(e!=f)
{
if((d==1)&&(e<f))
{
if(x[f]<=c)
{
x[e]=x[f];
e=e+1;
d=2;
}
else f=f-1;
}
if((d==2)&&(e<f))
{
if(x[e]>=c)
{
x[f]=x[e];
f=f-1;
d=1;
}
else e=e+1;
}
}
x[e]=c;
if(e-j>1) kp(j,e-1);
if(k-e>1) kp(e+1,k);
}
int main()
{
scanf("%d",&a);
for(i=1;i<=a;i++)
{
scanf(" %d",&x[i]);
}
kp(1,a);
for(i=1;i<=a;i++)
{
printf("%d ",x[i]);
}
return 0;
}
六、桶排序(箱排序)
1.方法:设置若干个桶,扫描全部数据,把每个元素记录在该关键字的桶里,然后按序扫描全部桶将所有元素排成一个有序序列。
2.时间复杂度:O(n)。
3.优点:速度极快。
4.缺点:不稳定,必须确定关键字数量和范围,且不能太大。
#include<cstdio>
int main()
{
int a,i,m,x[1000000]={0};
scanf("%d",&a);
for(i=1;i<=a;i++)
{
scanf(" %d",&m);
x[m]=x[m]+1;
}
for(i=1;i<=1000000;i++)
{
for(m=1;m<=x[i];m++)
{
printf("%d\n",i);
}
}
return 0;
}
七、堆排序
1.方法:利用堆。
2.时间复杂度:一般情况O(n log n)。
3.优点:速度快,可以随时添加新的元素和输入最大(或最小)的元素。
4.缺点:不稳定。
八、归并排序
1.方法:
(1)将数据分成两个子数据,再将子数据分成两个子数据,直到每个数据只包含一个元素。
(2)将两个有序的子数据合并成一个有序的子数据,不断向上合并。
2.时间复杂度:一般情况O(n log n)。
3.优点:速度快,稳定。
4.缺点:不易实现。