冒泡排序法是初学者接触的常用排序法,但是其只能排序整型数组,float或者char类型则都不能比较
void bubble_sort(int arr[],int sz)
{
int i, j = 0;
for (i = 0;i<sz - 1; i++)
{
for (j = 0; j < sz - i-1; j++)
{
int temp = 0;
if (arr[j] > arr[j + 1])
{
temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
}
int main()
{
int arr[] = { 10,9,8,7,6,5,4,3,2,1 };
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
bubble_sort(arr,sz);
for (i = 0; i < sz; i++)
{
printf("%d ",arr[i]);
}
return 0;
}
C语言提供了qsort函数来对不同类型的数据进行排序
void qsort(void* base,//目标数组起始位置
size_t num,//数组大小
size_t width,//元素大小
int(_cdc1*compare)((const void* elem1,const void* elem2))//比较函数的函数指针,函数是一个自定义函数,要求是elment1大时返回大于0的数,相等返回0,小于返回小于0的数,对于不同的类型比较,要自定义不同的函数来进行处理
void * 的解释说明
对于int a=10;来说
应该用int p=&a;来接收a的地址
当然也可以char p=&a,int 和char只是决定p指针能访问空间的大小
而void *p 是能接收任何类型的指针,比如char int float double等都可以
因为qsort是一个泛化函数,需要接收各种数组类型,所以就需要用void *来接收地址
void *p的使用需要注意的是,void型的指针在使用时不能做解引用操作和地址加减操作,因为void型的指针不知道指针p能够访问空间的大小,仅仅作为接收首地址使用
int com_int(const void *element1, const void *element2)//qsort的泛化性要求其函数的参数是void*,所以具体自定义函数在接收的时候也要用void来接收
{
//比较两个整型值
return *((int*)element1) - *((int*)element2);
//但是具体的自定义函数是知道所比较的类型的,所以要对void指针进行强转后再进行解引用操作,函数要返回一个数
}
int main()
{
int arr[] = { 10,9,8,7,6,5,4,3,2,1 };
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
qsort(arr,sz,sizeof(arr[0]),com_int);
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
在上述代码基础上加入了float型数组的比较
int com_int(const void *element1, const void *element2)
{
//比较两个整型值
return *((int*)element1) - *((int*)element2);
//qsort的泛化性要求其函数的参数是void*,所以具体自定义函数在接收的时候也要用void来接收
//但是具体的自定义函数是知道所比较的类型的,所以要对void指针进行强转后再进行解引用操作
}
int com_float(const void* element1, const void* element2)
{
if (*((float*)element1) > *((float*)element2))
return 1;
else if (*((float*)element1) == *((float*)element2))
return 0;
else
return -1;
//或者return (int)(*((float*)element1)) - (int)(*((float*)element2));
}
void test1()
{
int arr[] = { 10,9,8,7,6,5,4,3,2,1 };
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
qsort(arr, sz, sizeof(arr[0]), com_int);
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
void test2()
{
float f[] = {10.0,9.0,8.0,7.0,6.0};
int sz = sizeof(f) / sizeof(f[0]);
int i = 0;
qsort(f, sz, sizeof(f[0]), com_float);
for (i = 0; i < sz; i++)
{
printf("%f ", f[i]);
}
printf("\n");
}
int main()
{
test1();
test2();
return 0;
}
结构体排序
struct Stu
{
char name[20];
int age;
};
int com_by_age(const void* e1, const void* e2)
{
return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
int com_by_name(const void* e1, const void* e2)
{
//比较名字就是比较字符串,要用strcmp来比较
return strcmp(((struct Stu*)e1)->name , ((struct Stu*)e2)->name);
}
void test3()
{
struct Stu s[3] = { {"zhangsan",23},{"lisi",43},{"wangxianglong",22}};
int sz = sizeof(s) / sizeof(s[3]);
qsort(s,sz,sizeof(s[0]),com_by_age);
qsort(s, sz, sizeof(s[0]), com_by_name);
}
int main()
{
test3();
return 0;
}
尝试自定义sort相关函数进行泛化排序
struct Stu
{
char name[20];
int age;
};
void Swap(char* buf1, char* buf2, int width)//逐字节交换
{
int i = 0;
for (i = 0; i < width; i++)
{
char temp = *buf1;
*buf1 = *buf2;
*buf2 = temp;
buf1++;
buf2++;
}
}
void bubble_sort(void* base, int sz, int width, int(*cmp_fun)(const void* e1, const void* e2))
{
int i = 0;
for (i = 0; i < sz - 1; i++)
{
int j = 0;
for (j = 0; j < sz - i - 1; j++)
{
if (cmp_fun((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
{
//交换
Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
}
}
}
}
int com_int(const void* element1, const void* element2)//qsort的泛化性要求其函数的参数是void*,所以具体自定义函数在接收的时候也要用void来接收
{
//比较两个整型值
return *((int*)element1) - *((int*)element2);
//但是具体的自定义函数是知道所比较的类型的,所以要对void指针进行强转后再进行解引用操作,函数要返回一个数
}
int com_float(const void* element1, const void* element2)
{
if (*((float*)element1) > *((float*)element2))
return 1;
else if (*((float*)element1) == *((float*)element2))
return 0;
else
return -1;
//或者return (int)(*((float*)element1)) - (int)(*((float*)element2));
}
int com_by_age(const void* e1, const void* e2)
{
return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
int com_by_name(const void* e1, const void* e2)
{
//比较名字就是比较字符串,要用strcmp来比较
return strcmp(((struct Stu*)e1)->name , ((struct Stu*)e2)->name);
}
void test1()
{
float f[] = { 10.0,9.0,8.0,7.0,6.0 };
int sz = sizeof(f) / sizeof(f[0]);
int i = 0;
bubble_sort(f, sz, sizeof(f[0]), com_float);
for (i = 0; i < sz; i++)
{
printf("%f ", f[i]);
}
printf("\n");
}
void test2()
{
struct Stu s[3] = { {"zhangsan",23},{"lisi",43},{"wangxianglong",22} };
int sz = sizeof(s) / sizeof(s[3]);
bubble_sort(s,sz,sizeof(s[0]),com_by_age);
}
void test3()
{
struct Stu s[3] = { {"zhangsan",23},{"lisi",43},{"wangxianglong",22} };
int sz = sizeof(s) / sizeof(s[3]);
//qsort(s,sz,sizeof(s[0]),com_by_age);
bubble_sort(s, sz, sizeof(s[0]), com_by_name);
}
void test4()
{
int arr[] = {1,2,3,4,5,6,7,8,9};
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
bubble_sort(arr,sz,sizeof(arr[0]),com_int);
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main()
{
test1();//float排序
test2();//age排序
test3();//int 排序
test4();// name排序
return 0;
}