以下內容來自《C/C++程序設計實用案例教程》
1、排序
1.1使用qsort函數
C/C++庫函數提供了快速排序函數qsort(q時quick的簡寫),需要引入頭文件<stdlib.h>(注:C++中盡量使用<cstdlib>)
C/C++中庫函數qsort函數聲明如下:
void qsort(void* base, size_t num, size_t size, int(*compar)(const void*, const void*));
第一個參數base:待排序的元素數組起始地址
第二個參數num:待排序的數組中元素個數
第三個參數size:每個元素的大小(字節數)
最后一個參數:排序的比較函數
例子:整形數組的qsort
#include <stdlib.h>
int compare(const void* a, const void* b) //這里要注意的是參數的類型必須為const void*
{
if (*(int*)a < *(int*)b)
return -1;
else if (*(int*)a == *(int*)b)
return 0;
else
return 1;
}
int main()
{
int a[] = { 12, 46, 154, 4, 86, 5, 78, 5, 8, 16, 879, 4, 78, 5, 45, 12, 45, 45, 71, 1, 4, 78, 979, 46, 7, 9 };
size_t num = sizeof(a) / sizeof(int);
size_t size = sizeof(int);
qsort(a, num, size, compare);
return 0;
}
結果

例子:字符串數組的qsort
#include <stdlib.h> //qsort
#include <string.h> //strcmp
//字符串數組的qsort
int compare(const void* a, const void* b)
{
return strcmp(*(char**)a, *(char**)b);
}
int main()
{
char* str[] = { "fad", "fdfetr", "qwtwt", "nbdf", "twtyw", "wywr", "rwew", "sfb" };
qsort(str, sizeof(str) / sizeof(char*), sizeof(char*), compare);
return 0;
}
結果

1.2使用std::sort排序
在C++中,更推薦使用STL庫函數中的std::sort。因為C++STL中並沒有明確指明std::sort使用的排序算法,這也意味不同的平台在std::sort函數實現時可能采用不同的排序算法。
std::sort兩個重載函數聲明如下,需引入頭文件<algorithm>
template<class RandomAccessIterator> void sort(RandomAccessIterator first, RandomAccessIterator last); template<class RandomAccessIterator,class Compare> void sort(RandomAccessIterator first,RandomAccessIterator last,Compare comp)
第一個重載函數只需傳入一個迭代器區間,也就是開始和終止位置的兩個隨機訪問迭代器。它只能進行升序排列。
第二個重載函數還需要傳入比較函數。
這里再次涉及迭代器區間,在STL的所有庫函數中,如果涉及迭代器區間,那么這個區間一定是半閉半開區間,也就是[first,last)。
在qsort函數中,一定要傳入一個比較函數,但是在std::sort的第一個重載函數中,並沒有比較函數。這是因為qsort處理的數據都是無符號類型的指針,在編譯時候它無法知道數據元素的確切類型。
而std::sort采用的是C++模板方法,當數據傳入到比較函數時,它的類型在編譯時就確定了。
第二個重載函數中如何定義比較函數?
comp實際上是一個二元函數,它的參數應該是待排序區間中的兩個元素,而不是元素的指針;
comp的返回值是bool類型,當返回值為true時,表示a排在b的前面,因此,std:;sort的比較函數相比於qsort的比較函數顯得比較簡捷,因為qsort比較函數的返回值包括0、負整數、正整數,分別表示等於、小於和大於;
同樣,std::sort的比較函數可以是一個函數指針,也可以是一個函數對象。
示例代碼如下:
#include <iostream>
#include <algorithm>
//雙精度升序比較函數
bool DoubleAscend(double i, double j)
{
return i < j;
}
//雙精度降序比較函數
bool DoubleDescend(double i, double j)
{
return j < i;
}
//函數對象做比較函數
struct CompareClass
{
bool operator()(double i, double j){ return j < i; }
} compareDescendObject;
int main()
{
double data[] = { 32.5, 71.3, 12.1, 45.4, 26.8, 80.9, 53.2, 32.5 };
int n = sizeof(data) / sizeof(double);
//使用double默認升序
std::sort(data, data + n);
for (int i = 0; i < n; i++)
std::cout << data[i] << " ";
std::cout << std::endl;
//對前四個元素按降序排序
std::sort(data, data + 4, DoubleDescend);
for (int i = 0; i < n; i++)
std::cout << data[i] << " ";
std::cout << std::endl;
//對后四個元素按降序排序
std::sort(data + n - 4, data + n, DoubleDescend);
for (int i = 0; i < n; i++)
std::cout << data[i] << " ";
std::cout << std::endl;
//使用自定義比較類的一個實例化對象對所有元素按降序排序
std::sort(data, data + n, compareDescendObject);
for (int i = 0; i < n; i++)
std::cout << data[i] << " ";
std::cout << std::endl;
}
結果:

補充:
對於基本數據,STL已經准備了降序排序的函數模板std::greater。對於非基本數據類型,如結構體或類,只要其重載operator<函數,則可以直接使用std::greater進行降序排序。
使用std::greater時需要引入頭文件<functional>。
與降序相對應的是升序std::less(可以用,但沒必要,因為默認就是升序的)。
例子
#include <iostream>
#include <algorithm>
#include <functional>
int main()
{
double data[] = { 32.5, 71.3, 12.1, 45.4, 26.8, 80.9, 53.2, 32.5 };
int n = sizeof(data) / sizeof(double);
//按降序排序
std::sort(data, data + n, std::greater<double>());
for (int i = 0; i < n; i++)
std::cout << data[i] << " ";
std::cout << std::endl;
}
結果

2、查找
2.1使用bsearch函數
C語言庫函數提供了一個二分查找函數bsearch,需要引入頭文件<stdlib.h>
函數聲明如下:
void* bsearch(const void* key, const void* base, size_t num, size_t size, int(*compar)(const void*, const void*));
bsearch的函數參數列表和qsort非常類似,只是它多了第一個參數:一個待查找值的指針,如果在數組中成功查找該值,則返回該值所在空間的地址;如果數組中有多個相同的待查找值,則可能返回其中任意一個值的地址,如果查找失敗,返回null指針。
示例代碼:
#include <stdlib.h> //qsort,bsearch
int compareInt(const void* a, const void* b)
{
return *(int*)a - *(int*)b;
}
int main()
{
int values[] = { 50, 20, 60, 40, 10, 30 };
int key;
int *pltem;
key = 30;
qsort(values, sizeof(values) / sizeof(int), sizeof(int), compareInt); //使用二分法查找需要先進行排序
pltem = (int*)bsearch(&key, values, sizeof(values) / sizeof(int), sizeof(int), compareInt);
return 0;
}
結果

2.2std::find查找
std::find是C++ STL庫函數中一個通用的查找函數,這個函數並不要求輸入的數據集合是已排序的。
std::find需引入頭文件<algorithm>
其函數聲明如下:
template<class InputIterator,class T> InputIterator find(InputIterator first, InputIterator last, const T& val);
它會返回[first,last)區間內第一個和val相等的元素的迭代器。如果沒有找到該元素,函數返回的是last迭代器。
示例代碼:
#include <algorithm>
int main()
{
int data[] = { 35, 25, 10, 15, 45 };
int *p, n;
n = sizeof(data) / sizeof(int);
p = std::find(data, data + n, 15);
return 0;
}
結果

