C/C++中的排序和查找


以下內容來自《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;
}

結果

 


免責聲明!

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



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