一.最快最简单的排序:桶排序(简化版)
对于桶排序,其实非常简单,只是需要用一个一维数组便可以解决。
比如,我们需要对一串1~100范围内的数进行排序,现在给出这样的一串数:2,30,25,11,25。如果要对这五个数进行排序,我们首先就要开始构建出装这些数据的桶,因为开始说了范围为1~100,所以我们需要100个桶,但是为了方便桶的序号与我们的数据相同,所以一般选择定义一个a[101]这样的大桶,然后我们将每一个数组序号想象为一个桶,因为开始桶里面是没有东西的,所以我们将数组的初值都定义为0。
接着我们就需要将我们的数据放进桶里面了,比如第一个数为2,那么a[2]就加一,即a[2]的值就从0变成了1,同理将后面的后面的数也放进桶之中,注意!因为25出现了两次,那么a[25]也会加两次。即a[25]的值会从0变成2。
#include<stdio.h>
int main()
{
int n,i=0,j=0;
int a[101];//构建桶 。
for(i=0;i<101;i++)
{
a[i]=0;//清空桶里面的内容 。
}
for(i=0;i<5;i++)
{
scanf("%d",&n);//依次录入5个数。
a[n]++;//放进对应的桶中。
}
for(i=0;i<101;i++)//依次检验桶里面是否有东西
{
for(j=0;j<a[i];j++)//看桶里装了几个数据 ,有几个打印几个。
{
printf("%d ",i);//打印数据
}
}
return 0;
}
图 1桶排序的核心代码示例
PS:这是升序,如果需要降序,只需要将打印的代码的 for(i=0;i<101;i++)改为for(i=100;i>0;i--)即可。桶排序是一种十分浪费空间的排序算法,需要排序数的范围越大,所开辟的空间越大;而且桶排序不能给小数排序。
二. 经典排序:冒泡排序
冒泡排序是一种非常经典的排序方式,也最常用的排序方法之一。
冒泡排序的基本思想是:每次比较相邻两个数的大小,如果他们的顺序错误,就把他们的位置交换。
图 2冒泡法图解
#include<stdio.h>
int main()
{
int n,i,j,flag=0;
int a[100];
scanf("%d",&n);//输入一个N表示接下来将会有N个数进行排序。
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);//依次输入要排序的N个数。
}
for(i=0;i<=n-2;i++)//冒泡算法的核心代码,两个嵌套的循环。
{ for(j=0;j<=n-i-2;j++)//N个元素需要N-1趟。
{
if(a[j]>a[j+1])//比较相邻的两个元素,如果满足条件便交换。
{
flag=a[j];a[j]=a[j+1];a[j+1]=flag;
}
}
}
for(i=0;i<n;i++)
printf("%d ",a[i]);//打印排好后的数据。
return 0;
}
图 3冒泡排序代码
PS:因为冒泡排序使用了两个嵌套的循环,所以冒泡排序的时间复杂度较高。
三. 最常用的排序:快速排序
相比较于桶排序和冒泡排序,快速排序无论是在时间复杂度还是空间上都更加优秀。
假设现在我们对“4 2 5 6 1 3”这6个数进行排序,首先我们先选定一个基准数,在这里我们选定4为基准数(随机选择,其他的都可以)。
4 | 2 | 5 | 6 | 1 | 3 |
接着我们就需要开始从序列的两端开始探测,假设j从序列的右边开始向左探测,i从序列的左边开始向右探测,j的任务是寻找比基准数小的元素,i的任务是寻找比基准数大的元素,注意,每一次探测,必须先从右边开始,即先从j开始。
j开始探测,发现了3比基准数小,标记,接着i开始探测,发现5比基准数大,标记。
4 | 2 | 5(i) | 6 | 1 | 3(j) |
将i和j标记的数互换,但是i和j的位置不换。
4 | 2 | 3(i) | 6 | 1 | 5(j) |
i和j继续探测,j发现了1,i发现了6,互换。
4 | 2 | 3 | 1(i) | 6(j) | 5 |
然后j继续向左走,发现了1,注意,此时i和j碰面了,这时我们只需要将基准数和i和碰面的数交换即可。
1 | 2 | 3 | 4 | 6 | 5 |
此时我们发现基准数左边都是比基准数小的数,右边全是比基准数大的数,然后用同样的方法来处理基准数两边的序列,即处理“1 2 3”这个序列和“6 5”这个序列。
其实快速排序就是将选定的基准数归位,直到所有的基准数都归位,那么序列也就排好了。
#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从右边开始向左找,记住一定先从右边开始。
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);//利用递归,继续处理右边的序列。
return;
}
int main()
{
int i,j;
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]);//打印排好序后的数列。
return 0;
}
图 4快速排序代码
排序的算法还有很多,这里只是简单介绍了这三种。