日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言-怎么写一个自己的qsort函数

發布時間:2024/1/1 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言-怎么写一个自己的qsort函数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本篇是用冒泡排序的方法來實現qsort函數(排序函數)的功能

要寫一個自己的qsort函數,我們首先要知道qsort函數的功能與使用方法

由上面的介紹我們可以知道,qsort函數的作用是用來對數組里的元素進行排序,一共有4個參數,分別是他們的作用是先把數組的地址以void*的形式傳過去,然后再傳入這個數組的元素個數與每個元素的大小(單位字節),最后的參數是一個函數指針,這個函數指針指向的函數的作用是要告訴程序我們數組中的元素要如何進行比較,有兩個參數,p1與p2,如果p1<p2該函數返回-1,如果p1=p2該函數返回0,如果p1>p2該函數返回1,那么這到底該怎么使用呢,下面我們來舉個例子使用一下就明白了。

我們首先以排序一個結構體為例,我們創建一個結構體類型struct S,成員有名字和年齡,我們以年齡為標準對三個結構體變量進行排序,我們先放出代碼

struct S //創建結構體類型 {char name[20];int age; }; int cmp_age(const void* e1, const void* e2) //寫出比較函數 {return (((struct S*)e1)->age - ((struct S*)e2)->age); } void Swap(void* df1, void* df2,int width) //交換函數,在進行排序時如果兩個元素符合交換條件,則使用該函數對兩個元素進行交換 {int i;for (i = 0;i < width;i++){char tmp = *((char*)df1+i);*((char*)df1+i) = *((char*)df2+i);*((char*)df2+i) = tmp;} } void my_bubblesort(void* base, int num, int width, int(*cmp)(const void* e1, const void* e2)) { //使用冒泡排序的方法對數組的元素進行排序int i;for (i = 0;i < num - 1;i++){int j;for (j = 0;j < num-1-i;j++){if (cmp((char*)base + j * width, (char*)base + (j + 1) * width)>0){Swap((char*)base + j * width,(char*)base + (j + 1) * width,width);}}} } int main() {int i;struct S a[3] = {{"zhangsan",28},{"lisi",21},{"wangwu",25}};//struct S* p = &a[0];int sz=sizeof(a)/sizeof(a[0]);int width = sizeof(a[0]);/*my_bubblesort(a,sz,width,cmp_age);*/my_bubblesort(a, sz, width, cmp_age);for (i = 0; i < 3;i++){printf("%d\n", (a[i]).age);}return 0; }

這個代碼分為五個部分,首先,我們要先創建一個結構體類型,我創建的是struct S,然后在主函數中我們創建了一個元素類型為結構體的數組,假設該數組為a,有三個元素,如代碼。現在我們要以年齡為標準,對a數組的三個元素進行排序,我們要以qsort的方式來創建一個my_bubblesort函數,那么我們自建的函數的參數和返回類型就也與qsort相同,也為4個參數如qsort,返回值為void。然后我們就可以著手用冒泡排序的方法實現對數組元素的排序。

冒泡排序,我們首先要知道冒泡排序的過程,我們先用一個數組的第一個元素與第二個元素進行比較,如果第一個元素大于第二個元素,那么我們就把這兩個元素交換位置,然后比較第二個元素與第三個元素,以此往復,一直比較到倒數第二個元素與倒數第一個元素,完成這一趟,就是完成了一次冒泡排序,而我們要完成冒泡排序的次數應該是元素個數減一個,我們就可以使用一個for循環來完成這個目的,在我們進行一次冒泡排序時,我們還要使數組中的相鄰兩個元素進行比較,那我們就可以再用一個for循環來實現,而這時的循環次數就應該是num-1-i,因為之前的i次排序已經把后面的i個數排好了,所以就不用再循環num-1次了。而當我們每次兩個元素進行比較時,我們就需要用到我們函數的第四個參數:比較函數了。

為什么要使用比較函數呢,因為數組里的元素可能是各種類型的,而每種類型的比較方法都不一樣,比如我們結構體的比較方法和整型的比較方法就不同,而就算都是結構體,以上圖為例,我們也可以用age為標準或者以name為標準進行比較,所以我們就無法寫一個統一的函數來實現這個比較的功能,所以我們需要函數的使用者自己寫一個比較函數作為參數,再函數調用時告訴函數我們進行排序的數組兩個元素之間應該如何進行比較。

我們是以結構體中的age為標準進行比較的,所以我們就要再寫一個函數,來實現兩個結構體類型的元素如何以age為標準進行比較,我寫的是cmp_age,參數為const void* e1與const void* e2,我們使用void*類型的意義是這個函數可以接收任何類型的指針作為參數,但是我們不能解引用他,在前面加上const的意義是使我們無法通過指針改變這個指針指向的內容,因為我們只是要對這兩個元素進行比較,并不希望它指向的內容被改變,所以加上const會使我們的指針更加安全。而我們要使用這兩個指針,首先就要對他們進行強制類型轉換,因為我比較的是以年齡為標準的結構體變量,所以我就把e1和e2強制類型轉換成struct S*,然后找到結構體變量中的成員age,然后對兩個元素進行比較,如果e1>e2,返回一個大于0的數,相等返回0,e1<e2返回一個小于0的數,以上就完成了比較函數。

當我們完成比較后,發現我們正在比較的元素符合交換的條件時,我們就要對這兩個元素進行交換,這時我們可以再寫一個交換函數,因為我們同樣不知道我們要進行交換的元素是什么類型的,所以我們同樣使用void*作為參數來接收這來接收這兩個元素的地址,然后我們還需要一個參數就是這個元素的寬度,而交換函數如何實現呢,首先,因為我們不知道元素的類型,那么我們如果要實現元素的交換,我們就可以把兩個元素逐字節的進行交換,這時候就用到了元素的寬度,當我們逐個元素進行交換時,一直要交換到一個元素寬度,這時表示我們已經完全的交換了一個元素。

完成以上內容,我們就基本寫完了my_bubblesort函數的內容,下面我們來使用一下看看效果。

?下面我們再寫一個例子,這次我們以name為標準進行比較,同樣,我們先放代碼

struct S {char name[20];int age; }; int cmp_name(const void* e1, const void* e2) {return strcmp((((struct S*)e1)->name),(((struct S*)e2)->name)); } void Swap(void*bf1,void* bf2,int width) {int i;for (i = 0;i < width;i++){char tmp = *((char*)bf1 + i);*((char*)bf1 + i) = *((char*)bf2 + i);*((char*)bf2 + i) = tmp;} } void my_bubblesort(void* base, int num, int width, int(*cmp)(const void* e1, const void* e2)) {int i;for (i = 0;i < num - 1;i++){int j;for (j = 0;j < num - 1 - i;j++){if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0){Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);}}} } int main() {int i;struct S a[3] = { {"zhangsan",28},{"lisi",21},{"wangwu",25} };//struct S* p = &a[0];int sz = sizeof(a) / sizeof(a[0]);int width = sizeof(a[0]);/*my_bubblesort(a,sz,width,cmp_age);*/my_bubblesort(a, sz, width, cmp_name);for (i = 0; i < 3;i++){printf("%s\n", (a[i]).name);}return 0; }

我們以name為標準進行比較時,需要注意的是name是一個元素類型為字符的數組,也是一個字符串,而字符串之間的比較需要用到一個庫函數strcmp,頭文件為<string.h>,我們把兩個字符串的地址作為strcmp的兩個參數,strcmp會對這兩個字符串的元素從頭開始逐個字符進行比較,如果相同,則向下比較,直到找到不同的元素,然后比較他們的ASCII值,如果第一個字符串的那個元素大,則返回1,第一個小則返回-1,后面的元素就不再進行比較了,如果兩個字符串的每一個元素都進行了比較并且他們的每一個元素都相同,則返回0,而我們要完成對兩個結構體變量的成員name進行比較時,我們只需要對兩個地址進行強制類型轉換,然后找到name,再把這兩個地址作為參數給strcmp函數進行比較,就完成了比較函數,然后再把這個函數指針作為參數傳給my_bubblesort函數就可以實現排序,其他內容與上面的過程類似,我們運行一下看看結果

?我們發現這就實現了以name為標準對數組的元素進行排序,我們發現,當我們想要排序不同元素類型的數組時,我們只需要寫一個比較函數告訴程序我們要如何對兩個元素進行比較,然后把這個比較函數作為參數傳給排序函數,就可以實現排序

同樣,我們也可以練習一下排序別的元素類型的數組來熟悉一下實現數組內容排序函數的過程,我們就不寫了,大家可以自己練習一下。

如果我的文章對你有幫助,希望多多點贊,關注!!

?

總結

以上是生活随笔為你收集整理的C语言-怎么写一个自己的qsort函数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。