目錄
一、算法
(1)簡介
算法由頭文件<algorithm>,<numeric>,<functional>組成
- <algorithm> 是頭文件中最大的,包含的功能有比較、交換、查找、遍歷、複製、修改、反轉、排序、合併等
- <numeric> 只包括在序列上進行簡單數學運算的模板函數,包括加法和乘法在序列上的一些操作
- <functional> 定義了一些模板類,用來聲明函數對象
(2)STL常見算法
-
非可變序列算法
不直接修改所操作容器內容的算法
find() 查找容器元素
find_if() 條件查找容器元素
#include <algorithm>
//for_each函數的頭文件
//find()
vector<int> v1;
for(int i=0;i<10;i++)
{
v1.push_back(2*i);
}
for_each(v1.begin(),v1.end(),MyPrint); //MyPrint爲之前定義的函數
vector<int>::iterator it1 = find(v1.begin(),v1.end(),5); //查找成功返回迭代器,失敗返回v1.end()
//find_if()
bool DivBy5(int x)
{
return x%5? 0:1;
}
vector<int>::iterator it2 = find_if(v1.begin(),v1.end(),DivBy5); //返回第一個能被5整除的元素
count() 統計元素的個數
count_if() 條件統計元素的個數
//count()
int num1 = count(v1.begin(),v1.end(),3);
//count_if()
int num2 = count(v1.begin(),v1.end(),DivBy5); //第3個參數是條件函數
search() 子序列搜索,返回子序列在父序列中起始位置
search_n() 重複元素的子序列搜索
//search()
vector<int> v2; //子序列
for(int i=0;i<2;i++)
{
v2.push_back(i+8);
}
vector<int>::iterator it3 = search(v1.begin(),v1.end(),v2.begin(),v2.end());
//前2個參數是搜索序列的範圍,後2個參數是子序列範圍
//search_n()
vector<int>::iterator it4 = search(v1.begin(),v1.end(),3,8);
//在v1中搜索子序列 8 8 8
-
可變序列算法
修改所操作容器內容的算法
copy() 元素複製
transform() 元素變換,也是複製,按照某種方案複製
//copy()
vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(5);
list<int> l;
l.push_back(2);
l.push_back(4);
l.push_back(6);
l.push_back(8);
copy(v.begin(),v.end(),l.begin()); //把v拷貝到l的頭部,會覆蓋l的數據
//transform(),按照規則拷貝
int square(int x)
{
return x*x;
}
transform(v.begin(),v.end(),l.begin(),square); //把v的平方拷貝到l的頭部,會覆蓋l的數據
replace() 替換元素
replace_if() 條件替換
//replace()
replace(v.begin(),v.end(),5,100); //將所有5替換成100
//replace_if()
bool odd(int x)
{
return x%2;
}
replace_if(v.begin(),v.end(),odd,100); //將奇數替換成100
remove() 刪除元素
remove_if() 條件刪除
//remove()
remove(v.begin(),v.end(),5); //刪除值爲5的元素,但數組大小不變
//刪除前 1 3 5 7
//刪除後 1 3 7 7
//remove_if()
bool even(int x)
{
return x%2?0:1;
}
remove_if(v.begin(),v.end(),even) //刪除奇數
//刪除前 1 2 3 4 5 6 7 8 9 10
//刪除後 1 3 5 7 9 6 7 8 9 10
-
排序算法
sort() 普通排序
make_heap() 將一個區間轉換成堆
sort_heap() 對堆進行排序,排序後就不是堆了
//sort()
sort(v.begin(),v.end()); //參數爲要排序的區間,默認升序排列
//make_heap()
make_heap(v.begin(),v.end()); //將區間轉換成大根堆
//sort_heap()
sort_heap(v.begin(),v.end()); //對堆進行排序,默認升序排列
二、迭代器
(1)簡介
迭代器用於指向容器中的一個元素,有const和非const兩種
通過迭代器可以讀取它指向的元素,通過非const迭代器可以修改它指向的元素
不同容器支持的迭代器功能強弱不同,迭代器功能強弱決定了該容器是否支持STL中的某種算法
定義迭代器:
容器類名:: iterator 變量名 ,如 vector<int>::iterator v;
容器類名:: const_iterator 變量名 ,如 vector<int>::const_iterator v;
訪問迭代器指向的元素:
* 迭代器變量名
迭代器功能由弱到強分爲5種
1.輸入:Input iterators 提供對數據的只讀訪問
1.輸出:Output iterators 提供對數據的寫訪問
2.正向:Forward iterators 提供讀寫操作,並能向前推進迭代器
3.雙向:Bidirectional iterators 提供讀寫操作,並能向前和向後操作
4.隨機:Random access iterators 提供讀寫操作,並能在數據種隨機移動(能使用[ ]操作符)
編號大的迭代器擁有編號小的迭代器的功能,能當編號小的迭代器使用
不同迭代器能進行的操作
所有迭代器: ++p,p++
輸入迭代器:*p,p=p1,p==p1,p!=p1
輸出迭代器:*p,p=p1
正向迭代器:上面全部
雙向迭代器:上面全部,--p,p--
隨機訪問迭代器:上面全部,
p+=i,p-=i, p+i,p-i,p[i],
p<p1,p<=p1,p>p1,p>=p1 (迭代器比較操作)
容器 | 迭代器類別 |
vector | 隨機 |
deque | 隨機 |
list | 雙向 |
set / multiset | 雙向 |
map / multimap | 雙向 |
stack | 不支持 |
queue | 不支持 |
priority_queue | 不支持 |
(2)迭代器操作
//p<p1,p<=p1,p>p1,p>=p1
int arr[] = {11,12,13,14,15,16,17,18,19,20};
vector<int> v(arr,arr+9);
vector<int>::const_iterator it1 = v.begin(); //常量迭代器,指向第一個元素11
vector<int>::const_iterator it2 = v.cbegin(); //常量迭代器,指向第一個元素11
//cbegin()和cend()方法,返回一個const的迭代器,不能用於修改元素
vector<int>::iterator it3 = v.begin();
*it3 = 10; //修改第一個元素值爲10
it3++; //指向第二個元素
//迭代器的比較是按照迭代器指向的值來進行比較
(3)STL使用自定義對象
向vector,deque,list,stack,queue添加自定義對象,實際是將對象複製到容器中,要調用對象的拷貝函數;
如果定義了拷貝函數就調用定義的拷貝函數,否則就調用默認的拷貝函數;
向set和map容器添加自定義對象也是將對象複製到容器中,不同的是set和map容器要實現比較器函數;
- vector容器
class member
{
private:
string m_str;
int m_id;
public:
member(const string str,const int id):m_str(str),m_id(id){}; //構造函數
void MyPrint()
{
cout<< m_str << ":" << m_id;
}
};
vector<member> v1;
v1.push_back(member("123",1));
v1.push_back(member("456",2));
vector<member> v2(v1); //用v1初始化v2
vector<member>::iterator it = v2.begin();
it-> MyPrint(); //打印結果爲123:1
- set容器
class student
{
private:
int s_str; string s_id;
public:
student(const int id,const string str)
{
s_id= id; s_str = str;
}
void MyPrint()const //const成員函數
{
cout<< s_str << ":" << s_id;
}
};
//小於比較器
struct stuFun
{
bool operator()(const student& stu1,const student& stu2)
{
return(stu1.s_id < stu2.s_id)
}
};
set<student,stuFun> s1;
s1.insert(student(7,"小A"));
s1.insert(student(5,"小B"));
s1.insert(student(3,"小C"));
s1.insert(student(1,"小D")); //按id進行升序排列
set<student,stuFun> s2(s1);
set<student,stuFun>::iterator it = s2.begin();
it-> MyPrint(); //打印結果爲 小D:1
三、類中成員函數聲明後面接 const
- const 表示對類中成員函數屬性的聲明;
- 表示不會修改類中的數據成員;
- 在編寫const成員函數時,若不慎修改了數據成員,或者調用了非const成員函數,編譯器報錯;
class S
{
private:
int num;
int data[100];
public:
void Push(int elem);
int Pop(void);
int GetCount(void) const; //const成員函數
};
//注意:在實現的時候需要帶有const修飾
int S::GetCount(void)const
{
++num; //編譯錯誤,企圖修改數據成員num
Pop(); //編譯錯誤,企圖調用非const函數
return num;
}
類中被const聲明的成員函數只能訪問const成員函數,而非const函數可以訪問任意的成員函數,包括const成員函數
類中被const聲明的成員函數不可以修改對象的數據,不管對象是否具有const性質,它在編譯時,會檢查是否修改成員數據
加上mutable修飾符的數據成員,對於任何情況下通過任何手段都可修改,自然此時的const成員函數是可以修改它的