(原創) 如何使用C語言的標準函式庫進行排序? (C/C++) (C)
2008-01-28 23:44
786 查看
Abstract
一想到排序,你會想到什麼?Bubble sort?事實上ANSI C的library就帶了一個超快的排序法:Quick Sort!!
Introduction
若談到排序,大概有兩種想法,學術派的會想到資料結構所教的一堆排序法,如Bubble sort...,熟悉C++的會想到STL的sort() algorithm,其實ANSI C的stdlib.h就已經自帶一個Quick Sort演算法,由於是ANSI C的標準函式庫,跨平台不是問題。
qsort.c
1
10#include <stdio.h>
11#include <stdlib.h>
12
13#define ARR_SIZE 5
14
15
19int main() int i = 0;
21 int arr[ARR_SIZE] =
23 for(i = 0; i != ARR_SIZE; ++i)
24 printf("%d ", arr[i]);
25
26 printf("\n");
27
28 qsort((void *)arr, ARR_SIZE, sizeof(int), compare);
29
30 for(i = 0; i != ARR_SIZE; ++i)
31 printf("%d ", arr[i]);
32}
執行結果
2 3 1 3 5
1 2 3 3 5 請按任意鍵繼續 . . .
28行的qsort()是關鍵,只要一行就可以做排序了,其他的程式只是為了顯示排序前和排序後的結果,或許看到qsort()傳入的值型態有點詭異,而且還要附帶compare,這是為什麼呢?
在stdlib.h中,qsort()的原型如下
void qsort(void *base, size_t n, size_t size, int ((compare) (const void *, const void *))
base:陣列第一個元素的指標,由於qsort()要能處理各種型別,所以用void *處理,可以看成C語言對泛型的一種實踐(當然沒C++好),void*表示任何型別。
n:陣列元素的個數,不要被size_t嚇到了,他事實上是typedef int size_t,只是size_t更能表示陣列元素個數的型別,且日後若其他平台所支援的int更大,只要更改typedef即可,不需修改原來的程式碼。
size:每個陣列元素的大小,因為陣列元素型態為int,所以傳入sizeof(int)。
compare:想要qsort()排序,就面臨到一個問題,排序的規則是什麼?是要比大?還是比小呢?還是要比sin值?這些比較的規則,完全由compare這個function pointer定義,他定義了qsort()所能接受的function pointer型態。
int (*compare)(const void *, const void *)
這表示compare的function型態必須是傳回int,並且傳入兩個void *型態,為什麼是void *呢?因為比較可以是任何型別,為了支援泛型,所以用了void *。若熟悉C++的STL,對於這種方式一定不陌生,C++的algorithm為了更有彈性,最後一個參數通常傳入自定的function object(functor),相當於C語言的function pointer。
所以15行的compare()必須這樣定義
int compare(const void *arg1, const void *arg2) {
return (*(int *)arg1 - *(int *)arg2);
}
由於傳入的void *,實際比較時,必須再轉回(int *),但這還是個pointer int不能比較,所以還要一個*取int值。
Conclusion
要利用C語言作排序嗎?別忘了C語言標準程式庫的qsort(),又快又簡單喔!!
See Also
(原創) 如何使用C++的標準函式庫進行排序? (C/C++) (STL)
一想到排序,你會想到什麼?Bubble sort?事實上ANSI C的library就帶了一個超快的排序法:Quick Sort!!
Introduction
若談到排序,大概有兩種想法,學術派的會想到資料結構所教的一堆排序法,如Bubble sort...,熟悉C++的會想到STL的sort() algorithm,其實ANSI C的stdlib.h就已經自帶一個Quick Sort演算法,由於是ANSI C的標準函式庫,跨平台不是問題。
qsort.c
1
10#include <stdio.h>
11#include <stdlib.h>
12
13#define ARR_SIZE 5
14
15
19int main() int i = 0;
21 int arr[ARR_SIZE] =
23 for(i = 0; i != ARR_SIZE; ++i)
24 printf("%d ", arr[i]);
25
26 printf("\n");
27
28 qsort((void *)arr, ARR_SIZE, sizeof(int), compare);
29
30 for(i = 0; i != ARR_SIZE; ++i)
31 printf("%d ", arr[i]);
32}
執行結果
2 3 1 3 5
1 2 3 3 5 請按任意鍵繼續 . . .
28行的qsort()是關鍵,只要一行就可以做排序了,其他的程式只是為了顯示排序前和排序後的結果,或許看到qsort()傳入的值型態有點詭異,而且還要附帶compare,這是為什麼呢?
在stdlib.h中,qsort()的原型如下
void qsort(void *base, size_t n, size_t size, int ((compare) (const void *, const void *))
base:陣列第一個元素的指標,由於qsort()要能處理各種型別,所以用void *處理,可以看成C語言對泛型的一種實踐(當然沒C++好),void*表示任何型別。
n:陣列元素的個數,不要被size_t嚇到了,他事實上是typedef int size_t,只是size_t更能表示陣列元素個數的型別,且日後若其他平台所支援的int更大,只要更改typedef即可,不需修改原來的程式碼。
size:每個陣列元素的大小,因為陣列元素型態為int,所以傳入sizeof(int)。
compare:想要qsort()排序,就面臨到一個問題,排序的規則是什麼?是要比大?還是比小呢?還是要比sin值?這些比較的規則,完全由compare這個function pointer定義,他定義了qsort()所能接受的function pointer型態。
int (*compare)(const void *, const void *)
這表示compare的function型態必須是傳回int,並且傳入兩個void *型態,為什麼是void *呢?因為比較可以是任何型別,為了支援泛型,所以用了void *。若熟悉C++的STL,對於這種方式一定不陌生,C++的algorithm為了更有彈性,最後一個參數通常傳入自定的function object(functor),相當於C語言的function pointer。
所以15行的compare()必須這樣定義
int compare(const void *arg1, const void *arg2) {
return (*(int *)arg1 - *(int *)arg2);
}
由於傳入的void *,實際比較時,必須再轉回(int *),但這還是個pointer int不能比較,所以還要一個*取int值。
Conclusion
要利用C語言作排序嗎?別忘了C語言標準程式庫的qsort(),又快又簡單喔!!
See Also
(原創) 如何使用C++的標準函式庫進行排序? (C/C++) (STL)
相关文章推荐
- (原創) 如何使用C++的標準函式庫進行排序? (C/C++) (STL)
- 如何使用C++的標準函式庫進行排序? (C/C++) (STL)
- (原創) 如何解決使用preverify時,出現『Segmentation fault』的錯誤訊息? (OS) (Linux) (CentOS) (Java) (J2ME) (MIDP)
- (原創) 如何使用boost::array? (C/C++) (template) (boost)
- (原創) 如何使用Function Object? (C/C++) (STL)
- (原創) 如何使用struct? (C/C++) (.NET) (C++/CLI)
- (原創) 如何使用硬體的方式『播放SD卡內wav檔音樂』? (DE2) (Quartus II) (Nios II)
- (原創) 如何使用functional simulation? (SOC) (Quartus II)
- (原創) 如何解決在Quartus II無法使用ModelSim-Altera模擬的問題? (SOC) (Quartus II) (ModelSim)
- (原創) 如何使用參數式模組? (SOC) (Verilog) (C/C++) (template)
- (原創) 如何使用integer型別? (IC Design) (Verilog)
- (原創) 如何使用function template傳遞array? (C/C++) (template)
- (原創) 如何在curses中使用getch()? (OS) (Linux) (C/C++) (C)
- (原創) 如何让一个thread在背景不断的执行? (使用semaphore) (OS) (Linux) (C/C++) (C)
- (原創) 如何使用transform() algorithm? (C/C++) (STL)
- (原創) 如何使用reverse_iterator? (C/C++) (STL)
- (原創) 如何使用for_each() algorithm? (C/C++) (STL)
- (原創) 如何使用Nios II C2H compiler? (IC Design) (DE2) (Nios II) (Quartus II) (SOPC Builder) (C/C++) (C2H)
- (原創) 如何使用abstract base class模擬interface? (C/C++)
- (原創) 如何在DE2-70使用SSRAM? (SOC) (Nios II) (DE2-70)