本篇是要自己写一个qsort函数,首先我们要知道qsort函数的功能和使用方法。
可以在c++网站上进行了解。
经了解之后可以知道, qsort函数的作用是用来对数组里的元素进行排序。
一共有4个参数,分别是他们的作用是先把数组的地址传过去(void*)形式,然后再传入这个数组的元素个数和元素的大小,单位是字节,最后的参数是一个函数指针,这个函数指针指向的函数的作用是要告诉程序我们数组中的元素要如何进行比较,有两个参数p1和p2。
函数使用示列
#include#include int cmp_int(const void* e1, const void* e2) { //强制类型转换成整型指针 return * (int*) e1 - * (int *) e2; } void print(int arr[], int sz) { int i = 0; for (i = 0; i < sz; i++) { printf("%d ", arr[i]); } printf("n"); } void test1() { int arr[ ] = { 9,8,7,6,5,4,3,2,1,0 }; int sz = sizeof(arr) / sizeof(arr[0]); qsort(arr, sz, sizeof(arr[0]), cmp_int); print(arr, sz); } int main() { test1( ); return 0; }
由图可知: 有两个参数,p1与p2,如果p1
了解这个函数的功能和使用方法后,接下来就是用自己的代码实现qsort函数。
用自己的代码实现函数。
//模拟qsort函数实现冒泡排序的通用算法 #includeint cmp_int(const void* e1, const void* e2) { //强制类型转换成整型指针 return * (int*) e1 - * (int *) e2; } void swap(char* buf1, char* buf2, int width) { int i = 0; for (i = 1; i <= width; i++)//字节交换 { char tmp = *buf1; *buf1 = *buf2; *buf2 = tmp; buf1++; buf2++; } } void bubble_sort(void* base, int sz, int width, int(*cmp)(const void *e1, const void *e2)) //接收首地址、元素个数、元素大小、用来比较排序数据的函数这四个参数 { int i = 0; for (i = 0; i < sz-1; i++) { int j = 0; for (j = 0; j < sz - 1 - i; j++) { //两个元素比较 //base强制类型转换成char*, if (cmp((char*)base + j*width , (char*)base + (j + 1)*width)>0) { //交换函数 swap((char*)base + j*width, (char*)base + (j + 1)*width, width); } } } } void print(int arr[], int sz) { int i = 0; for (i = 0; i < sz; i++) { printf("%d ", arr[i]); } printf("n"); } void test1( ) { int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 10 }; int sz = sizeof(arr) / sizeof(arr[0]); bubble_sort(arr, sz, sizeof(arr[0]), cmp_int); print(arr, sz); } int main( ) { test1( ); return 0; }
我这里创建的是一个整型数组进行排序,首先创建自己的函数bubble_sort,以qsort的方式来创建,那么我们自己创建的函数的参数和返回类型就也与qsort一样的,也为4个参数如qsort,返回值为void。
我们这里使用的冒泡排序,我们先用一个数组的第一个元素与第二个元素进行比较,如果第一个元素大于第二个元素,那么我们就把这两个元素交换位置,然后比较第二个元素与第三个元素,以此往复,一直比较到倒数第二个元素与倒数第一个元素,完成这一趟,就是完成了一次冒泡排序,而我们要完成冒泡排序的次数应该是元素个数减一个,我们就可以使用一个for循环来完成这个目的,在我们进行一次冒泡排序时,我们还要使数组中的相邻两个元素进行比较,那我们就可以再用一个for循环来实现,而这时的循环次数就应该是sz-1-i,因为之前的i次排序已经把后面的i个数排好了,所以就不用再循环sz-1次了。
当我们进行元素比较是就要用到比较函数了,因为进行比较的元素类型有很多种,列如字符串、结构体等等。每一种的类型比较方式也不一样,所以我们需要函数的使用者自己写一个比较函数作为参数,再函数调用时告诉函数我们进行排序的数组两个元素之间应该如何进行比较。
我这里的代码的参数为const void* e1与const void* e2,这里使用void*类型的意义是这个函数可以接收任何类型的指针作为参数,但是我们不能直接解引用,在前面加上const的意义是使我们无法通过指针改变这个指针指向的内容,因为我们只是要对这两个元素进行比较,并不希望它指向的内容被改变,所以加上const会使我们的指针更加安全。而我们要使用这两个指针,首先就要对他们进行强制类型转换,所以我就把e1和e2强制类型转换成int*,然后对两个元素进行比较,如果e1>e2,返回一个大于0的数,相等返回0,e1 比较两个元素完接下来就是交换了,创建交换函数Swap,这里我们同样不知道要进行交换的元素是什么类型的,所以同样使用void*作为参数来接收这来接收这两个元素的地址,然后我们还需要一个参数就是这个元素的宽度。因为我们不知道元素的类型,那么我们如果要实现元素的交换,我们就可以把两个元素逐字节的进行交换,用字节交换就可以适应其他类型的元素,而不是局限于某一种类型。这时候就用到了元素的宽度,当我们逐个元素进行交换时,一直要交换到一个元素宽度,这时表示我们已经完全的交换了一个元素,然后指针加1往后走,继续交换,最后变量排序后的数组。 最后示例:



