qsort的使用练习以及模拟实现
什么是qsotr?
qsort是排序函数,在MSDN中显示Performs a quick sort.,即执行快速排序,
具体为
void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );
void *base
目标矩阵的开始
size_t num
元素中的数组大小
size_t width
元素大小(以字节为单位)
int (__cdecl *compare )(const void *elem1, const void *elem2 )
比较函数
qsort的使用
使用函数就需要传参,根据上述描述我们可以清楚的知道传参的值,这里值得注意的是比较函数。
void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );
qsort函数传参类型多为void*
,这就意味着我们可以对不同的数据类型按给定的规则排序。
比较函数就给定了排序规则
我们又知道,void
这种类型不能加减乘数解应用,使用目的主要是为了可以排序多种数据类型,所以我们要利用好强制类型转换。
#include<stdio.h>
#include<stdlib.h>
int compare(void* elem1,void*elem2){
return *((int*)elem1) - *((int*)elem2);
}
int main(){
int arr[] = { 0, 5, 8, 4, 3, 1, 6, 9, 2, 7 };
int sz = sizeof(arr)/sizeof(arr[0]);
qsort(arr,sz,sizeof(int),compare);
int i = 0;
for (i = 0; i < sz; i++){
printf("%d ",arr[i]);
}
return 0;
}
运行结果:
qsort的模拟实现
qsort的模拟实现首先如何排序?怎么样解决不确定数据类型的排序?按何规则排序?
既然如此我们要知道数据从哪里开始到哪里结束,元素个数,元素每字节大小,还要比较函数
主函数部分:
主要是传参问题,参数需要
void *base
目标矩阵的开始
size_t num
元素中的数组大小
size_t width
元素大小(以字节为单位)
int (__cdecl *compare )(const void *elem1, const void *elem2 )
比较函数
int main(){
int arr[] = { 0, 5, 8, 4, 3, 1, 6, 9, 2, 7 };
int sz = sizeof(arr) / sizeof(arr[0]);
//qsort(arr, sz, sizeof(int), compare);
my_qsort(arr, sz, sizeof(int), compare);
//void qsort(void *base, size_t num, size_t width, int(__cdecl *compare)(const void *elem1, const void *elem2));
int i = 0;
for (i = 0; i < sz; i++){
printf("%d ", arr[i]);
}
return 0;
}
my_qsort函数部分:
既然数据类型是未知的,那我们只能用void*
来完成传参,
这里使用冒泡排序
,我们根据以上了解通过比较函数就知道如何排序,我们当比较函数大于0时就交换,完成排序
这里有个很严重的问题,我们不知道元素类型,我们怎么知道下一个元素是第几个字节开始的?
(char*)我们知道只可操作一个字节字符,只需要我们传的字符宽度就好。
void my_qsort(void* str, int num, int width, int compare(const void*(elem1), const void*(elem2))){
int i = 0, j = 0;
for (i = 0; i < num - 1; i++){
for (j = 0; j < num - i - 1; j++){
if (compare((char*)str + j*width, (char*)str + (j + 1) * width)>0){
swap(str, num, width,j );
}
}
}
}
交换代码:
当元素和后一个比较后大便交换位置,冒泡排序思想,不详细赘述。
void swap(void* str, int num, int width,int j){
char tmp = *((char*)str + j * width);
*((char*)str + j* width) = *((char*)str + (j + 1) * width);
*((char*)str + (j + 1) * width) = tmp;
}
比较函数
int compare(void* elem1, void*elem2){
return *((int*)elem1) - *((int*)elem2);
}
整体代码
#include<stdio.h>
#include<stdlib.h>
//用冒牌排序模拟实现qsort
//
int compare(void* elem1, void*elem2){
return *((int*)elem1) - *((int*)elem2);
}
void swap(void* str, int num, int width,int j){
char tmp = *((char*)str + j * width);
*((char*)str + j* width) = *((char*)str + (j + 1) * width);
*((char*)str + (j + 1) * width) = tmp;
}
void my_qsort(void* str, int num, int width, int compare(const void*(elem1), const void*(elem2))){
int i = 0, j = 0;
for (i = 0; i < num - 1; i++){
for (j = 0; j < num - i - 1; j++){
if (compare((char*)str + j*width, (char*)str + (j + 1) * width)>0){
swap(str, num, width,j );
}
}
}
}
int main(){
int arr[] = { 0, 5, 8, 4, 3, 1, 6, 9, 2, 7 };
int sz = sizeof(arr) / sizeof(arr[0]);
//qsort(arr, sz, sizeof(int), compare);
my_qsort(arr, sz, sizeof(int), compare);
//void qsort(void *base, size_t num, size_t width, int(__cdecl *compare)(const void *elem1, const void *elem2));
int i = 0;
for (i = 0; i < sz; i++){
printf("%d ", arr[i]);
}
return 0;
}
运行结果:
总结
我这里似乎有一些bug,(char*)str+j*width,如果j = 0,如果是整数大于char能接受值范围之外将会出现bug,这怎么办呢?且听下回分解;