qsort 函數的使用——對普通數組、指針數組、二維數組中的元素進行排序


在ANSI C中,qsort函數的原型是

#include <stdlib.h>

void qsort(void *base, size_t nmemb, size_t size, int (*compar) (const void *, const void *));

解釋:qsort函數對含有nmemb個元素的數組進行排序,而base指針指向數組的第一個元素。這個數組的元素個數由size指定。

compar函數對qsort的比較操作進行定義,所以可以定制數字的比較,字符串的比較,甚至結構體的比較,等等。compar的寫法見下面幾個例子。

 

一、使用qsort函數對普通數組進行排序。

代碼如下:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 int compare(const void *arg1, const void *arg2);
 5 
 6 int 
 7 main(int argc, char** argv)
 8 {
 9     int i;
10     
11     int arr[5] = { 13, 17, 2, 7, 71 };
12     
13     qsort(arr, sizeof(arr)/sizeof(arr[0]), sizeof(int), compare);
14     
15     for (i = 0; i < 5; i++) {
16         printf("%d ", arr[i]);
17     }
18     printf("\n");
19 }
20 
21 
22 int compare(const void *arg1, const void *arg2) {
23     int a = *(int*)arg1;
24     int b = *(int*)arg2;
25     if (a > b) {
26         return 1;
27     }
28     else if (a < b) {
29         return -1;
30     }
31     else {
32         return 0;
33     }
34 }

講一下參數compar的定義,由於qsort要求傳入一個函數指針,所以這個函數的名字我們可以自己設置,就跟其他形參的名字一樣,一般用cmp或者compare。

qsort函數把我們傳入的arr當做指向數組第一個元素的指針,所以相應地,在代碼第22行,形參表中的arg1和arg2,就是指向數組某個元素的指針

在第23行和第24行,我們將void*轉換為int*,並且將指針解引用之后的值賦予a和b,進行比較。

如果a>b返回1,a<b返回-1,就意味着我們進行元素的升序排序,將元素從小到大進行排序。

 

二、使用qsort函數對指針數組進行排序。

代碼如下:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4 
 5 int compare(const void *arg1, const void *arg2);
 6 
 7 int 
 8 main(int argc, char** argv)
 9 {
10     int i;
11     
12     char *arr[5] = { "i", "love", "c", "programming", "language" };
13     
14     qsort(arr, sizeof(arr)/sizeof(arr[0]), sizeof(char *), compare);
15     
16     for (i = 0; i < 5; i++) {
17         printf("%s ", arr[i]);
18     }
19     printf("\n");
20     /* getchar(); */
21 }
22 
23 int compare(const void *arg1, const void *arg2) {
24     char *a = *(char**)arg1;
25     char *b = *(char**)arg2;
26     int result = strcmp(a, b);
27     if (result > 0) {
28         return 1;
29     }
30     else if (result < 0) {
31         return -1;
32     }
33     else {
34         return 0;
35     }
36 }

 

與平常我們所用的數組相比,指針數組有些難理解,其實第12行的arr數組,它就是存放着5個指針,第1個元素存放指向常量字符串"i"的地址,第2個元素存放指向常量字符串"love"的地址,依此類推。

那么我們向qsort傳入arr之后,qsort將arr理解為指向數組中第一個元素的指針,所以第23行形參表中,arg1和arg2其實是指向指向常量字符串的指針的指針,是char**。而我們需要傳給strcmp這個字符串比較函數的,是“指向字符串的指針”,是char*,所以我們將void*轉換為char**,然后解引用,得到char*,賦予a和b。接下來使用strcmp對a和b進行比較。

 

三、使用qsort函數對指針數組進行排序。

代碼如下:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4 
 5 int compare(const void *arg1, const void *arg2);
 6 
 7 int 
 8 main(int argc, char** argv)
 9 {
10     int i;
11     
12     char arr[5][16] = { "i", "love", "c", "programming", "language" };
13     
14     qsort(arr, sizeof(arr)/sizeof(arr[0]), sizeof(arr[0]), compare);
15     printf("%s\n", arr[0]);
16     for (i = 0; i < 5; i++) {
17         printf("%s ", arr[i]);
18     }
19     printf("\n");
20     /* getchar(); */
21 }
22 
23 int compare(const void *arg1, const void *arg2) {
24     char *a = (char*)arg1;
25     char *b = (char*)arg2;
26     int result = strcmp(a, b);
27     if (result > 0) {
28         return 1;
29     }
30     else if (result < 0) {
31         return -1;
32     }
33     else {
34         return 0;
35     }
36 }

 

二維數組比較常見,但是在qsort函數中要對這個數組中的元素進行排序,理解起來稍微有些難度。不過一步一步分析,思路也就自然了。

這里對二維數組進行排序,其實是對二維數組的第二維中存放的字符串進行排序。所以在第14行對qsort函數的調用中,第二個參數是待排元素的個數(5個),第三個參數是待排元素的大小(16)。

我們將arr傳入qsort函數,qsort函數將arr理解為指向數組第一個元素的指針,arr的第一個元素是arr[0][0],所以參數arg1和arg2指的是指向"a[i][0]"的指針,我們知道,a[i][0]是字符,就是char,所以arg1和arg2指的是char *。我們將void*轉換為char*,賦予a和b,調用strcmp函數對a和b進行比較。

 

就是這樣。


免責聲明!

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



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