參考:
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(void* base,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 }