qsort()函數詳解


參考:

https://www.cnblogs.com/laizhenghong2012/p/8442270.html

https://www.cnblogs.com/eniac12/p/4769229.html

https://www.cnblogs.com/tsingke/p/5347672.html

 

 

 

排序方法有很多種:選擇排序,冒泡排序,歸並排序,快速排序等。快速排序是目前公認的一種比較好的排序算法。因為他速度很快,所以系統也在庫里實現了這個算法,便於我們的使用。 這就是qsort函數(全稱quicksort)。它是ANSI C標准中提供的,其聲明在stdlib.h文件中,是根據二分法寫的,其時間復雜度為n*log(n)

功能: 使用快速排序例程進行排序
頭文件stdlib.h

函數原型: void qsort(voidbase,size_t  num,size_t  width,int(__cdecl*compare)(const void*,const void*)); 

參數說明

base:待排序數組,排序之后的結果仍放在這個數組中
num: 數組中待排序元素數量
width: 各元素的占用空間大小(單位為字節)
compare: 指向函數的指針,用於確定排序的順序(需要用戶自定義一個子函數)

函數返回值:無
注意:如果兩個元素的值是相同的,那么它們的前后順序是不確定的。也就是說qsort()是一個不穩定的排序算法

 compar參數詳細規則

 compar參數是一個函數指針,指向一個比較兩個元素的函數。比較函數的原型應該像下面這樣。注意兩個形參必須是const void *型。另外,因為qsort( )內部在調用compar 函數(compar實質為函數指針,這里稱它所指向的函數也為compar)時,傳入的實參也已經轉換成const void *型,所以在compar函數內部必須將const void *型轉換成待排序數組的實際類型,見下文。

int cmp(const void *p1, const void *p2);

如果cmp返回值小於0(< 0),那么p1所指向元素會被排在p2所指向元素的前面
如果cmp返回值等於0(= 0),那么p1所指向元素與p2所指向元素的順序不確定
如果cmp返回值大於0(> 0),那么p1所指向元素會被排在p2所指向元素的后面

 所以,實現cmp函數時,謹記:
如果滿足某個條件時,p1元素應在p2元素前面,那么此時返回負數,比如-1
如果滿足某個條件時,p1元素應在p2元素后面,那么此時返回正數,比如1
如果滿足某個條件時,p1元素和p2元素順序不影響,那么返回0.(這個時候一般是表示p1==p2

使用qsort()函數的例子

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<time.h>
  4 #include<string.h> 
  5 typedef struct
  6 {
  7     int No;
  8     int yuWen,shuXue,yingYu,zongFen;
  9 }stu;
 10 typedef struct
 11 {
 12     int x,y;
 13 }point;
 14 
 15 //----------隨機數相關子函數-----------------------------
 16 int getRandomInt(int a,int b)//返回[a,b]之間一個隨機整數
 17 {   return (rand() % (b-a+1))+ a;   }
 18 double getRandomDouble()//返回0~1之間隨機浮點數 
 19 {   return rand()/double(RAND_MAX); }
 20 char getUpChar()//返回隨機大寫字母
 21 {   return ((char)(rand()%26+'A')); } 
 22 char getDownChar()//返回隨機小寫字母
 23 {   return ((char)(rand()%26+'a')); } 
 24 void InitRandom()
 25 {  srand((unsigned)time(0)); }
 26 //-------------------------------------------------------
 27 
 28 
 29 int cmp1(const void *a,const void *b)//int數組從小到大排序
 30 {   return *(int*)a -*(int*)b; }
 31 int cmp2(const void *a,const void *b)//int數組從大到小排序
 32 {   return *(int*)b -*(int*)a; }
 33 
 34 /*在對浮點或者double型的數據比較時一定要用三目運算符,
 35 因為要是使用像整型那樣相減的話,如果是兩個很接近的數, 
 36 則可能返回一個很小的小數(大於-1,小於1),而cmp的返
 37 回值是int型,因此會將這個小數返回0,系統認為是相等,
 38 失去了本來存在的大小關系 */ 
 39 int cmp3(const void *a,const void *b)//double數組從小到大排序 
 40 {
 41     //return *(double*)a -*(double*)b;//這種寫法比較危險。因為無法直接判定兩個浮點數相等。 
 42     return *(double *)a > *(double *)b ? 1 : -1; 
 43 }
 44 
 45 int cmp4(const void *a,const void *b)//char數組從小到大排序
 46 {   return *(char*)a -*(char*)b; }
 47 
 48 int cmp5(const void *a,const void *b)//對字符串數組排序
 49 {    
 50     char *x=(char*)a;
 51     char *y=(char*)b;
 52     return strcmp(x,y);
 53 }
 54 
 55 int cmp6(const void *a,const void *b)//對stu結構體類型數組排序
 56 {//優先按總分從大到小,總分相等則按學號從小到大 
 57     stu x=*(stu*)a;
 58     stu y=*(stu*)b;
 59     if(x.zongFen<y.zongFen)return 1;
 60     else if(x.zongFen>y.zongFen) return -1;
 61     else
 62     {
 63         if(x.No<y.No)return -1;//返回負數-1表示參數一應該排在參數二前面 
 64         else if(x.No>y.No) return 1;//返回正數1表示參數一應該排在參數二后面 
 65         else return 0;//返回0表示參數一和參數二相等,最終排序結果中,兩者的順序不確定。 
 66     }
 67 }
 68 int cmp7(const void *a,const void *b)//對point結構體類型數組元素排序 
 69 {    //優先按x從小到大排序,當x相等則按y從大到小排序。 
 70     point *p1=(point*)a;
 71     point *p2=(point*)b;
 72     if(p1->x < p2->x) return -1;//返回負數-1表示參數一應該排在參數二前面
 73     else if(p1->x > p2->x)return 1;//返回正數1表示參數一應該排在參數二后面
 74     else
 75     {
 76         if(p1->y > p2->y)return -1;
 77         else if(p1->y < p2->y)return 1;
 78         else return 0;//返回0表示參數一和參數二相等,最終排序結果中,兩者的順序不確定。
 79     }
 80 }
 81 
 82 int main()
 83 { 
 84     int IntArr[15],IntArr2[15],IntArr3[15],i,n=15;
 85     double dArr[15];
 86     char cArr[15];
 87     char strArr[100][100];//每行一個字符串
 88     stu stuArr[50];//每個元素表示一個學生的數據
 89     point pArr[50];//每個元素表示一個整數點的數據(x,y) 
 90     InitRandom();
 91     //-------------------------------------------------------
 92     for(i=0;i<n;i++)//生成隨機整數數組 
 93     {
 94         IntArr3[i]=IntArr2[i]=IntArr[i]=getRandomInt(1,1000);
 95         printf("%d ",IntArr[i]);
 96     }
 97     printf("\n");
 98     //-------------------------------------------------------
 99     qsort(IntArr,n,sizeof(IntArr[0]),cmp1);//int[]從小到大排序 
100     for(i=0;i<n;i++)
101         printf("%d ",IntArr[i]);
102     printf("\n");
103     //-------------------------------------------------------
104     qsort(IntArr2,n,sizeof(IntArr2[0]),cmp2);//int[]從大到小排序
105     for(i=0;i<n;i++)
106         printf("%d ",IntArr2[i]);
107     printf("\n");
108     //-------------------------------------------------------
109     qsort(IntArr3+1,n-1,sizeof(IntArr3[1]),cmp2);//int[]從大到小排序,第0號元素不參與排序 
110     for(i=0;i<n;i++)
111         printf("%d ",IntArr3[i]);
112     printf("\n\n\n");
113     
114     
115     
116     //-------------------------------------------------------
117     n=10;
118     for(i=0;i<n;i++)//生成隨機浮點數數組 
119     {
120         dArr[i]=getRandomDouble()*1000;
121         printf("%.2lf ",dArr[i]);
122     }
123     printf("\n");
124     //-------------------------------------------------------
125     qsort(dArr,n,sizeof(dArr[0]),cmp3);//double[]從小到大排序
126     for(i=0;i<n;i++)
127         printf("%.2lf ",dArr[i]);
128     printf("\n\n\n");
129     //-------------------------------------------------------
130     
131     
132     
133     
134     //-------------------------------------------------------
135     n=15;
136     for(i=0;i<n;i++)//生成隨機字符數組 
137     {
138         cArr[i]=getUpChar();
139         printf("%c ",cArr[i]);
140     }
141     printf("\n");
142     //-------------------------------------------------------
143     qsort(cArr,n,sizeof(cArr[0]),cmp4);//char[]從小到大排序
144     for(i=0;i<n;i++)
145         printf("%c ",cArr[i]);
146     printf("\n\n\n");
147     //-------------------------------------------------------
148     
149     
150     
151     
152     //-------------------------------------------------------
153     n=10;
154     for(i=0;i<n;i++)//生成隨機字符串數組 
155     {
156         int len=getRandomInt(5,15);
157         for(int j=0;j<len;j++)
158             strArr[i][j]=getDownChar();
159         strArr[i][len]='\0';
160         printf("%s\n",strArr[i]);
161     }
162     printf("\n");    
163     //-------------------------------------------------------
164     qsort(strArr,n,sizeof(strArr[0]),cmp5);//字符串數組從小到大排序 
165     for(i=0;i<n;i++)
166         printf("%s\n",strArr[i]);
167     printf("\n\n\n");
168     //-------------------------------------------------------
169     
170     
171     
172     //-------------------------------------------------------
173     n=10;
174     for(i=0;i<n;i++)//生成stu結構體類型的隨機數據
175     {
176         stuArr[i].No=1000+i;
177         stuArr[i].yuWen=getRandomInt(90,150);
178         stuArr[i].shuXue=getRandomInt(90,150);
179         stuArr[i].yingYu=getRandomInt(90,150);
180         stuArr[i].zongFen=stuArr[i].yuWen+stuArr[i].shuXue+stuArr[i].yingYu;
181         printf("%d %3d %3d %3d %3d\n",stuArr[i].No,stuArr[i].yuWen,stuArr[i].shuXue,stuArr[i].yingYu,stuArr[i].zongFen);
182     }
183     printf("\n");
184     //-------------------------------------------------------
185     qsort(stuArr,n,sizeof(stuArr[0]),cmp6);//對stu類型數組排序 
186     for(i=0;i<n;i++)
187         printf("%d %3d %3d %3d %3d\n",stuArr[i].No,stuArr[i].yuWen,stuArr[i].shuXue,stuArr[i].yingYu,stuArr[i].zongFen);
188     printf("\n\n\n");
189     //-------------------------------------------------------
190     
191     
192     
193     //-------------------------------------------------------
194     n=10;
195     for(i=0;i<n;i++)//生成point結構體類型的隨機數據 
196     {
197         pArr[i].x=getRandomInt(80,100);
198         pArr[i].y=getRandomInt(1,100);
199         printf("%2d %2d\n",pArr[i].x,pArr[i].y);
200     }
201     printf("\n");
202     //-------------------------------------------------------
203     qsort(pArr,n,sizeof(pArr[0]),cmp7);//對point類型數組排序 
204     for(i=0;i<n;i++)
205         printf("%2d %2d\n",pArr[i].x,pArr[i].y);
206     printf("\n\n\n");
207     
208     
209     
210     
211     return 0;
212 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM