摘要:一前言我們學習過的冒泡排序,插入排序,選擇排序等經(jīng)典排序方法,為我們數(shù)據(jù)排序提供了穩(wěn)定思路,但局限在于排序數(shù)據(jù)類型的單一。
? ?我們學習過的冒泡排序,插入排序,選擇排序等經(jīng)典排序方法,為我們數(shù)據(jù)排序提供了穩(wěn)定思路,但局限在于排序數(shù)據(jù)類型的單一。為了解決這一問題,c語言中提供了庫函數(shù)qsort解決。我們今天就通過自定義函數(shù)實現(xiàn)qsort的功能,排序方法采用基本的冒泡排序
我們需要傳入四個變量:base——待排序數(shù)組的首元素地址;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? num——數(shù)組內(nèi)的元素個數(shù);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? width——每個元素的大小(單位為字節(jié));
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?函數(shù)指針——傳入兩個數(shù)的地址,比較二者大小(需自己設計)
1.可以傳入任何類型的指針而不會報警告,適合我們實現(xiàn)任何數(shù)據(jù)類型排序的目的;
2.不可以對其進行解引用操作,除非通過強制類型轉(zhuǎn)換()確定其具體類型;
3.不可以對其進行加減運算,原因是不知道類型所以不知道步長,因此還是需要強制類型轉(zhuǎn)換
注意:都需要先進行強制類型轉(zhuǎn)換才可以解引用
int cmp_int(const void* e1, const void* e2){ return *(int*)e1 - *(int*)e2;}
char類型數(shù)據(jù)不可以用<>=進行比較,所以要用函數(shù)strcmp庫函數(shù),頭文件為#include
int cmp_char(const void*e1, const void*e2){ return strcmp((char*)e1, (char*)e2);}
因為返回的是int類型,所以我們加入了判斷語句。用數(shù)的正負表示數(shù)的大小情況
int cmp_float(const void*e1, const void*e2){ if ((float*)e1 > (float*)e2) return 1; else if ((float*)e1 ==(float*)e2) return 0; else return -1;}
結(jié)構(gòu)體數(shù)組元素不可以直接比較,必須先選出結(jié)構(gòu)體某一內(nèi)容進行比較
typedef struct book{ char name[20]; int prince; }b;//重命名struct book為bint cmp_stru_price(const void*e1, const void*e2){ return ((b*)e1)->prince - ((b*)e2)->prince;}
注意?。。。╞*)e1外面的括號不可以省略,因為->的優(yōu)先級比強制類型轉(zhuǎn)換高
首先思考一個問題:既然傳入的指針為void*類型,如何實現(xiàn)步長的確定?聰明的科學家想到利用width作為我們的標準
void bubble_sort(void*base,int sz,int width,int(*cmp)(void*,void*)){ int i; int j; for (i = 0; i < sz - 1; i++) { for (j = 0; j < sz - 1-i; j++) { if (cmp((char*)base + width*j, (char*)base + width*(j + 1))>0) { swap((char*)base + width*j, (char*)base + width*(j + 1),width); } } }}
1.int(*)(void*,void*)是一個函數(shù)指針,指向我們之前設計的大小比較函數(shù)
2.在使用base的時候要先強制類型轉(zhuǎn)換才可以作加減運算
3.漂亮的地方在于,不管實際傳入的base是什么類型,我們都將其轉(zhuǎn)化為char*類型的指針,因為char*的步長最小為1,加上width就可以準確指向下一個?
以int為例,width為4,所及就可以指向下一個元素
?
?
void swap(char*buff1,char*buff2,int width){ int i; for (i = 0; i < width; i++) { int tmp = *buff1; *buff1 = *buff2; *buff2 = tmp; buff1++; buff2++; }}
值得關注的是,交換不是一次就可以了,因為我們現(xiàn)在是char*類型的指針,如上圖所畫,一次只能交換一格,如交換int的,要交換4次
1.函數(shù)指針的使用,使我們每次只需導入大小比較函數(shù)的地址即可,而不必寫多個函數(shù),分別含有不同的大小比較函數(shù),減少了重復代碼的出現(xiàn)
?2.width的使用相當于告訴了我們進行比較的數(shù)組元素的類型,滿足我們實現(xiàn)各種數(shù)據(jù)類型排序的需求
3.void*函數(shù)海納百川,方便了我們的輸入,只是注意在使用時的強制類型轉(zhuǎn)化,否則無法使用
希望上述的總結(jié)對大家的理解有幫助,也更好的欣賞回調(diào)函數(shù)(這里為用函數(shù)指針調(diào)用函數(shù))的魅力。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/118801.html
摘要:故使用無具體類型,又稱通用類型,即可以接收任意類型的指針,但是無法進行指針運算解引用,整數(shù)等。求指針所占字節(jié)而不是解引用訪問權(quán)限大小。數(shù)組就是整個數(shù)組的大小,數(shù)組元素則是數(shù)組元素的大小,指針大小都為。 ...
摘要:參數(shù)含義上圖是函數(shù)各個參數(shù)的含義,讓我們一個個來看。使用方式頭文件要使用函數(shù)我們首先需要引用一個頭文件的實現(xiàn)函數(shù)給函數(shù)規(guī)定了特定的參數(shù)。因此我們設計函數(shù)時要嚴格遵守其參數(shù)設定。 目錄 1.參數(shù)含義 1.首元素地址base 2.元素個數(shù)num 3.元素大小size 4.自定義比較函數(shù)compa...
摘要:回調(diào)函數(shù)不是由該函數(shù)的實現(xiàn)方直接調(diào)用,而是在特定的事件或條件發(fā)生時由另外的一方調(diào)用的,用于對該事件或條件進行響應。 目錄 前言無類型指針結(jié)構(gòu)體指針枚舉變量指針函數(shù)...
摘要:如果你把函數(shù)的指針地址作為參數(shù)傳遞給另一個函數(shù),當這個指針被用來調(diào)用其所指向的函數(shù)時,我們就說這是回調(diào)函數(shù)?;卣{(diào)函數(shù)不是由該函數(shù)的實現(xiàn)方直接調(diào)用,而是在特定的事件或條件發(fā)生時由另外的一方調(diào)用的,用于對該事件或條件進行響應。 ...
閱讀 3405·2021-09-22 15:17
閱讀 2761·2021-09-02 15:15
閱讀 1794·2019-08-30 15:54
閱讀 2014·2019-08-30 14:02
閱讀 2544·2019-08-29 16:58
閱讀 3003·2019-08-29 16:08
閱讀 1345·2019-08-26 12:24
閱讀 1670·2019-08-26 10:41