一、快速排序
算法思想:基于分治的思想,首先在数组中选择一个基准点,然后分别从数组的两端扫描数组,设两个指示标志(low指向起始位置,high指向末尾),从后半部分开始,如果发现有元素比该基准点的值小,就交换low和high位置的值,然后从前半部分开始扫秒,发现有元素大于基准点的值,就交换low和high位置的值,如此往复循环,直到low>=high,然后把基准点的值放到high这个位置。一次排序就完成了。以后采用递归的方式分别对前半部分和后半部分排序,当前半部分和后半部分均有序时该数组就自然有序了。
快速排序c代码实现如下:
#include<stdio.h>
#define MAX_SIZE 6
int findPos(int *a, int low, int high)
{
int val = a[low]; //默认a[low]为基准
while(low < high)
{
while(low < high && a[high] >= val) //右边第一个小于基准的数
high--;
a[low] = a[high];
while(low < high && a[low] <= val) //左边第一个大于基准的数
low++;
a[high] = a[low];
}
a[low] = val;
return low;
}
void quickSort(int *a, int low, int high)
{
int pos;
if(low < high)
{
//找到基准位置的索引
pos = findPos(a, low, high);
//对基准两边递归调用快速排序
quickSort(a, low, pos-1);
quickSort(a, pos+1, high);
}
}
int main()
{
int i, array[MAX_SIZE];
for(i = 0;i < MAX_SIZE; i++)
scanf("%d", &array[i]);
quickSort(array, 0, MAX_SIZE-1);
for(i = 0;i < MAX_SIZE; i++)
printf("%d ", array[i]);
printf("\n");
return 0;
}
二、qsort()函数
快速排序可以借助C语言编译器函数库自带的快速排序函数qsort( ),函数原型为:
#include<stdlib.h>
void qsort(void*base,size_t num,size_t width,int(__cdecl*compare)(const void*,const void*));
参数依次为:
- 待排序数组首地址:即数组名或指向数组的指针;
- 数组长度:size_t是标准C库中定义的unsigned int,输入待排序的数组的长度;
- 数组元素所占字节:直接用sizeof(a[0])计算字数组单个元素的节数;
- 所调用函数的指针,函数名即是函数的指针,可直接写函数名,调用函数用来确定排序的方式。
qsort要求提供一个自定义的比较函数,返回值为int。比较函数使得qsort通用性更好,有了比较函数qsort可以实现对数组、字符串、结构体等结构进行升序或降序排序。
//自定义cmp函数参数固定
//int 整型
int cmp_int(const void *a,const void *b)
{
return *(int *)a - *(int *)b;
}
//double 浮点型
int cmp_double(const void *a,const void *b)
{
return *(double*)a>*(double*)b? 1 : -1;
}
注: 这里两个浮点数相减但要返回一个整型数,如果按上面做法直接减会丢失小数点部分。
//char 字符型或字符串首字母
int cmp_char(const void *a,const void *b)
{
return *(char*)a-*(char*)b;
}
//字符串长度
int cmp_str(const void *a,const void *b)
{
return strlen((char*)a)-strlen((char*)b);
}
//字符串字典顺序
int cmp_str(const void *a, const void *b)
{
return (strcmp((char *)a, (char *)b));
}
//结构体排序
struct student{
int num;
char ch;
}stu[10];
int cmp_stu(const void *a,const void *b)
{
if((* (student* )a).num != ( * (student * )b).num)
return (*(student *)a).num - (*(student *)b).num;
else return (*(student *)a).ch - (*(student *)b).ch;
}
注意:strlen返回类型为size_t,应为unsigned int,在64位系统中为 long unsigned int。无符号整型最好不要做四则运算。这里虽然函数返回int型,会把无符号数转换为整型,但返回结果只在字符串的长度未超过int的范围时正确。这种大范围转小范围要考虑精度损失的问题。