C语言之简单排序算法(一)
排序算法是学习算法的开始,我们有时需要通过排序对数据进行处理。根据需要排序的数据多少和对数据处理的要求,我们可以用不同的排序算法。就此我根据自己的理解和搜集的资料,把c语言常用的几种简单排序算法整理出来。
一、冒泡排序
在冒泡排序方法中,数字列表被分为两个子列表:已排序的和未排序的。就如同它的名字一样,最小或最大的元素通过冒泡的方法选出来并移到已排序的列表中,而这里的冒泡是指通过相邻的数据元素的交换,每次只排好一个元素。所以也就是说,一个含有n个元素的列表,需要进行n-1轮来完成排序。
如下图是从小到大排序的第一趟冒泡示例:
而冒泡排序用c语言写出来也是很简单很容易理解的,但是其时间复杂度高,这里嵌套了一次for循环。
代码如下:
#include<stdio.h>
int main(void)
{
int a[100],i,j,t,n;
scanf("%d",&n);//输入要排序的数据个数
for(i=0;i<n;i++)
scanf("%d",&a[i]);
//开始排序
for(i=0;i<n;i++)
{
for(j=0;j<n-i-1;j++)
{
if(a[j]>a[j+1])
{
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
}
for(i=0;i<n;i++)
printf("%d ",a[i]);//输出结果
return 0;
}
二、快速排序
快速排序是对冒泡排序的一种改进,它是通过一趟排序将要排序的数据分割成两部分,其中一部分的所有数据都要比另外一部分的所有数据都要小,然后再按照此方法对这两部分数据分别进行快速排序,这个排序过程可以看成递归。
下面我举个简单例子来说明一下:
如一组数:3 2 7 6 1 4
a).先把第一个元素3取出来,用3依次与其他元素进行比较,如果有比3小的数字就放在3的前边,比3大的数字就放在3的 后边。第一趟排序后变成:2 1 3 7 6 4
b).对前半部分[2 1]继续进行快速排序,重复步骤a变成:[1 2];
对后面部分[7 6 4]也进行同样的快速排序,变成:[6 4 7];
c).上面的前半部分已排好序,只用看后半部分[6 4 7]再重复步骤a得到:[4 6 7];
此时整组数的顺序为:1 2 3 4 6 7 ,总的排序也到此完成。
下图是一个快速排序的动态图:
#include <stdio.h>
#include <stdlib.h>
#define N 6
int partition(int arr[], int low, int high)
{
int key;
key = arr[low];//定义一个关键元素
while(low<high){
while(low <high && arr[high]>= key )
high--;
if(low<high)
arr[low++] = arr[high];
while( low<high && arr[low]<=key )
low++;
if(low<high)
arr[high--] = arr[low];
}
arr[low] = key;
return low;//返回的low就是满足它左边的值比low小,右边的值比low大
}
//使用递归的方式对数组进行快速排序
void quick_sort(int arr[], int start, int end)
{
int pos;
if (start<end){
pos = partition(arr, start, end);
quick_sort(arr,start,pos-1);
quick_sort(arr,pos+1,end);
}
return;
}
int main(void)
{
int i;
int arr[N]={32,12,7, 78, 23,45};
printf("排序前 \n");
for(i=0;i<N;i++)
printf("%d\t",arr[i]);
quick_sort(arr,0,N-1);
printf("\n 排序后 \n");
for(i=0; i<N; i++)
printf("%d\t", arr[i]);
printf ("\n");
system("pause");
return 0;
}
这里用了三个函数,代码相对于冒泡排序要难一些,但其时间复杂度要比冒泡低很多。
三、选择排序
选择排序也是把数字列表分成两个子列表(已排序的和未排序的),和冒泡排序一样,每一轮都把最大或最小的元素筛选出来放在相应位置上,但是对于每一轮,选择排序是比较当前项和第n项,而冒泡是每次比较和移动相邻的两项。
一个含有n个元素的列表,也需要进行n-1轮来完成排序。
为了更直观地理解选择排序请看下图:
这是选择排序的第一趟,之后也是按照上述步骤来。用代码来表示选择排序也用到了两重循环,如下:
#include<stdio.h>
#define N 10
int main(void)
{
int a[N];
int i,j,t;
for(i=0;i<N;i++)
scanf("%d",&a[i]);//输入要排序的数据
//开始排序
for(i=0;i<N-1;i++)
for(j=i+1;j<N;j++)
{
if(a[i]>a[j])
{
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
for(i=0;i<N;i++)
printf("%d ",a[i]);
return 0;
}
选择排序也是十分基础的,它比冒泡排序要快些,也是很容易理解和掌握的。
四、插入排序
我们经常在扑克牌游戏中使用插入排序,把每张拿到的牌插入手中合适的位置,以便手中的牌以一定的顺序排列。而对数据进行插入排序也是如此,在每轮,把未排序子列表中的第一个元素转移到已排序子列表中,并且插入合适的位置。一个含有n个元素的列表至少需要n-1轮排序。
下面时插入排序的示意图:
在此我就不展示插入排序的代码了,以上就是四种简单的排序算法,如果要排序的列表中有多于几百个元素,那就不要使用除了快速排序的这些算法,应该使用更高效的算法如堆排序、Shell排序、桶排序、合并排序、基排序等。这些我将会下次为大家介绍。