常用演算法(Algorithm)概述
參看內容: VC知識庫
演算法(Algorithm)的簡介
演算法部分主要由標頭檔案<algorithm>
,<numeric>
和 <functional>
組成。
-
<algorithm>
是所有STL標頭檔案中最大的一個,其中常用到的功能範圍涉及到比較、交換、查詢、遍歷操作、複製、修改、反轉、排序、合併等等。 -
<numeric>
體積很小,只包括幾個在序列上面進行簡單數學運算的模板函式,包括加法和乘法在序列上的一些操作。 -
<functional>
中則定義了一些模板類,用以宣告函式物件。
演算法(Algorithm)的概要
- 常用的查詢演算法:
adjacent_find()( adjacent 是鄰近的意思),binary_search(),count(),
count_if(),equal_range(),find(),find_if()。
- 常用的排序演算法:
merge(),sort(),random_shuffle()(shuffle是洗牌的意思) ,reverse()。
- 常用的拷貝和替換演算法:
copy(), replace(),
replace_if(),swap()
- 常用的算術和生成演算法:
accumulate()( accumulate 是求和的意思),fill(),。
- 常用的集合演算法:
set_union(),set_intersection(),
set_difference()。
- 常用的遍歷演算法:
for_each(), transform()( transform 是變換的意思)
常用的查詢演算法
- adjacent_find()
- 在iterator對標識元素範圍內,查詢一對相鄰重複元素,找到則返回指向這對元素的第一個元素的迭代器。否則返回past-the-end。
例如:vecInt
是用vector<int>
宣告的容器,現已包含1,2,2,4,5元素。
vector<int>::iterator it=adjacent_find(vecInt.begin(),vecInt.end());
此時 *it == 2
- binary_search
- 在有序序列中查詢value,找到則返回true。
注意:在無序序列中,不可使用。
例如: setInt
是用set<int>
宣告的容器,現已包含1,3,5,7,9元素。
bool bFind = binary_search(setInt.begin(),setInt.end(),5);
此時 bFind == true
- count
- 利用等於操作符,把標誌範圍內的元素與輸入值比較,返回相等的個數。
- count_if
- 利用輸入的函式,對標誌範圍內的元素進行比較操作,返回結果為true的個數。
例如:vecInt
是用vector<int>
宣告的容器,已包含1,3,5,7,9元素,現要求求出大於等於3的元素個數
//先定義比較函式
bool GreaterThree(int iNum)
{
if(iNum>=3)
{
return true;
}
else
{
return false;
}
}
int iCount = count_if(vecIntA.begin(), vecIntA.end(), GreaterThree);
//此時iCount == 4
- equal_range
-
返回一對
iterator
,第一個表示lower_bound
,第二個表示upper_bound
。 - find
- 利用底層元素的等於操作符,對指定範圍內的元素與輸入值進行比較。當匹配時,結束搜尋,返回該元素的迭代器。
例如: vecInt
是用vector<int>
宣告的容器,已包含1,3,5,7,9
vector<int>::iterator it = find(vecInt.begin(),vecInt.end(),5);
此時*it == 5
- find_if
- 使用輸入的函式代替等於操作符執行find。返回被找到的元素的迭代器。
例如:vecInt
是用vector<int>
宣告的容器,已包含1,3,5,3,9元素。現要找出第一個大於等於3的元素的迭代器。
vector<int>::iterator it = find_if(vecInt.begin(),vecInt.end(),GreaterThree);
此時 *it==3, *(it+1)==5, *(it+2)==3, *(it+3)==9
常用的排序演算法
以下是排序和通用演算法:提供元素排序策略
- merge
- 合併兩個有序序列,存放到另一個序列。
例如:vecIntA
,vecIntB
,vecIntC
是用vector<int>
宣告的容器,vecIntA
已包含1,3,5,7,9元素,vecIntB
已包含2,4,6,8元素
vecIntC.resize(9); //擴大容量
merge(vecIntA.begin(),vecIntA.end(),vecIntB.begin(),vecIntB.end(),vecIntC.begin());
此時vecIntC
就存放了按順序的1,2,3,4,5,6,7,8,9九個元素
- sort
- 以預設升序的方式重新排列指定範圍內的元素。若要改排序規則,可以輸入比較函式。
例如: vecInt
是用vector<int>
宣告的容器,已包含2,1,4,3,6,5元素
sort(vecInt.begin(),vecInt.end());
此時,vecInt包含了1,2,3,4,5,6元素。
如果vector<T>
,T是自定義型別,則要提供T型別的比較函式。
學生類有學號跟姓名的屬性,有一個存著學生物件的vector容器,要使該容器按學號升序排序。
//學生類
Class CStudent:
{
public:
CStudent(int iID, string strName) {m_iID=iID; m_strName=strName; }
int m_iID;
string m_strName;
}
//學號比較函式
bool Compare(const CStudent &stuA,const CStudent &stuB)
{
return (stuA.m_iID<strB.m_iID);
}
void main()
{
vector<CStudent> vecStu;
vecStu.push_back(CStudent(2,"老二"));
vecStu.push_back(CStudent(1,"老大"));
vecStu.push_back(CStudent(3,"老三"));
vecStu.push_back(CStudent(4,"老四"));
sort(vecStu.begin(),vecStu.end(),Compare);
// 此時,vecStu容器包含了按順序的"老大物件","老二物件","老三物件","老四物件"
}
- random_shuffle
- 對指定範圍內的元素隨機調整次序。
- reverse
- 對指定範圍內元素重新反序排序。
常用的拷貝和替換演算法
- copy
- 複製序列
例如:vecIntA
,vecIntB
是用vector<int>
宣告的物件,vecIntA已包含1,3,5,7,9元素。
vecIntB.resize(5);
copy(vecIntA.begin(),vecIntA.end(),vecIntB.begin());
此時vecIntB
也包含了1,3,5,7,9元素
- replace(beg,end,oldValue,newValue)
- 將指定範圍內的所有等於oldValue的元素替換成newValue。
- replace_if
- 將指定範圍內所有操作結果為true的元素用新值替換。
用法舉例:
replace_if(vecIntA.begin(),vecIntA.end(),GreaterThree,newVal)
其中vecIntA
是用vector<int>
宣告的容器
GreaterThree
函式的原型是 bool GreaterThree(int iNum)
- swap
- 交換兩個容器的元素
常用的算術與生成演算法
- accumulate
- 對指定範圍內的元素求和,然後結果再加上一個由val指定的初始值
- fill
- 將輸入值賦給標誌範圍內的所有元素。
常用的集合演算法
- set_union
- 構造一個有序序列,包含兩個有序序列的並集。
- set_intersection
- 構造一個有序序列,包含兩個有序序列的交集。
- set_difference
- 構造一個有序序列,該序列保留第一個有序序列中存在而第二個有序序列中不存在的元素。
常用的遍歷演算法
- for_each
- 用指定函式依次對指定範圍內所有元素進行迭代訪問。該函式不得修改序列中的元素
- transform
- 與for_each類似,遍歷所有元素,但可對容器的元素進行修改