本文主要选取了桶排序,冒泡排序,以及快速排序。当然还有其他几种,可以根据需要进行学习。
一、桶排序
1、什么是桶排序?
桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。桶排序的工作的原理:假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排)。
2、为了使桶排序更加高效,我们需要做到这两点:
在额外空间充足的情况下,尽量增大桶的数量;使用的映射函数能够将输入的 N 个数据均匀的分配到 K 个桶中。同时,对于桶中元素的排序,选择何种比较排序算法对于性能的影响至关重要。
3、根据上面的定义,我们来探究一下:
a.什么时候排序最慢?当输入的数据被分配到了同一个桶中。
b.什么时候排序最快?当输入的数据可以均匀的分配到每一个桶中。
4、算法描述
a.设置一个定量的数组当作空桶;
b.遍历输入数据,并且把数据一个一个放到对应的桶里去;
c.对每个不是空的桶进行排序;
d.从不是空的桶里把排好序的数据拼接起来。
5、图示桶排序
5、图示算法
在桶中的元素分布:
然后,元素在每个桶中排序:
6、代码实现(将5 3 5 2 8按照从小到大顺序输出)
#include <stdio.h>
int main()
{
int a[11],i,j,t;
for(i=0;i<=10;i++)
a[i]=0; //初始化为0
for(i=1;i<=5;i++) //循环读入5个数
{
scanf("%d",&t); //把每一个数读到变量t中
a[t]++; //进行计数
}
for(i=0;i<=10;i++) //依次判断a[0]~a[10]
for(j=1;j<=a[i];j++) //出现了几次就打印几次
printf("%d ",i);
getchar();getchar();
//这里的getchar();用来暂停程序,以便查看程序输出的内容
//也可以用system("pause");等来代替
return 0;
}
二、冒泡排序
1、什么是冒泡排序?
冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,
也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
2、算法描述
a.比较相邻的元素。如果第一个比第二个大,就交换它们两个;
b.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
c.针对所有的元素重复以上的步骤,除了最后一个;
d.重复步骤1~3,直到排序完成。
3、图示算法()
4、代码实现(将8 100 50 22 15 6 1 1000 999 0按照从小到大顺序输出 )
#include <stdio.h>
int main()
{
int a[100],i,j,t,n;
scanf("%d",&n); //输入一个数n,表示接下来有n个数
for(i=1;i<=n;i++) //循环读入n个数到数组a中
scanf("%d",&a[i]);
//冒泡排序的核心部分
for(i=1;i<=n-1;i++) //n个数排序,只用进行n-1趟
{
for(j=1;j<=n-i;j++) //从第1位开始比较直到最后一个尚未归位的数。n-i是因为已经归位的不继续比较
{
if(a[j]<a[j+1]) //比较大小并交换
{ t=a[j]; a[j]=a[j+1]; a[j+1]=t; }
}
}
for(i=1;i<=n;i++) //输出结果
printf("%d ",a[i]);
getchar();getchar();
return 0;
}
三、快速排序
1、什么是快速排序?
快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
2、算法描述
快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:
1.从数列中挑出一个元素,称为 “基准”(pivot);
2.重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
3.递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列分别进行快速排序,直至所有元素都归位。
4、图示算法
5、代码实现(将6 1 2 7 9 3 4 5 10 8按照从小到大顺序输出)
#include <stdio.h>
int a[101],n;//定义全局变量,这两个变量需要在子函数中使用
void quicksort(int left,int right)
{
int i,j,t,temp;
if(left>right)
return;
temp=a[left]; //temp中存的就是基准数
i=left;
j=right;
while(i!=j)
{
//顺序很重要,要先从右往左找
while(a[j]>=temp && i<j)
j--;
//再从左往右找
while(a[i]<=temp && i<j)
i++;
//交换两个数在数组中的位置
if(i<j)//当哨兵i和哨兵j没有相遇时
{
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
//最终将基准数归位
a[left]=a[i];
a[i]=temp;
quicksort(left,i-1);//继续处理左边的,这里是一个递归的过程
quicksort(i+1,right);//继续处理右边的,这里是一个递归的过程
}
int main()
{
int i,j,t;
//读入数据
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
quicksort(1,n); //快速排序调用
//输出排序后的结果
for(i=1;i<=n;i++)
printf("%d ",a[i]);
getchar();getchar();
return 0;
}
四、三种排序的区别
由上表可见,桶排序是最快的,它的时间复杂度是 O(n+k);冒泡排序是 O(n2);快速排序是 O(nlog2n)。但是桶排序是最占空间的,它的空间复杂度是O(n+k),冒泡排序是 O(1);快速排序是 O(1)。
可以根据应用选择不同的排序,快速排序在实际应用使用较多。
如果需要了解更多排序的相关知识,可以参考