理解:STL
文章目錄
總覽
STL是std的子集
- STL(Standard Template Library),即標準模板庫
- STL的一個重要特點是資料結構和演算法的分離。例如,由於STL的sort()函式是完全通用的,你可以用它來操作幾乎任何資料集合,包括連結串列,容器和陣列;
- STL另一個重要特性是它不是面向物件的。為了具有足夠通用性,STL主要依賴於模板。
STL中六大元件:
容器(Container),是一種資料結構,如list,vector,和deques ,以模板類的方法提供。為了訪問容器中的資料,可以使用由容器類輸出的迭代器;
迭代器(Iterator),提供了訪問容器中物件的方法。例如,可以使用一對迭代器指定list或vector中的一定範圍的物件。迭代器就如同一個指標。事實上,C++的指標也是一種迭代器。但是,迭代器也可以是那些定義了operator*()以及其他類似於指標的操作符地方法的類物件;
演算法(Algorithm),是用來操作容器中的資料的模板函式。例如,STL用sort()來對一個vector中的資料進行排序,用find()來搜尋一個list中的物件,函式本身與他們操作的資料的結構和型別無關,因此他們可以在從簡單陣列到高度複雜容器的任何資料結構上使用;
仿函式(Functor)
介面卡(Adaptor)
分配器(allocator)
容器
序列式容器:Vector;Deque;List;
關聯式容器:Map/Multimap; Set/Multiset
理解:vector
動態陣列
List是stl實現的雙向連結串列,與向量(vectors)相比, 它允許快速的插入和刪除,但是隨機訪問卻比較慢.
**List不支援隨機訪問,因此訪問元素的效率較低,**list沒有at和下標運算子
push_back &pop_back:在容器最後新增和刪除
#include <string.h> #include <vector> #include <iostream> #include <algorithm>//sort演算法包含 using namespace std; int main() { vector<int>obj;//建立一個向量儲存容器 int /**********push_back*****/ for(int i=0;i<10;i++) // push_back(elem)在陣列最後新增資料 { obj.push_back(i); cout<<obj[i]<<","; } cout<<endl; /**********pop_back*****/ for(int i=0;i<5;i++)//去掉陣列最後一個數據 { obj.pop_back(); } for(int i=0;i<obj.size();i++)//size()容器中實際資料個數 { cout<<obj[i]<<","; } cout<<endl; /**********sort&reverse*****/ obj.push_back(100);obj.push_back(-9);obj.push_back(20); sort(obj.begin(),obj.end());//預設升序,也可以改變sort的定義如:sort(begin,end,compare) vector<int>::iterator iter; reverse(obj.begin(),obj.end());//只是改變方向,它不是排序 for(iter=obj.begin();iter!=obj.end();iter++) { cout<<*iter<<","; } cout<<endl; /****at形式訪問*******/ cout<<obj.at(2)<<endl;//at形式訪問 obj.clear();//清空 cout<<"size:"<<obj.size();//size為0; return 0; }
理解:List
理解:Map
C++中map提供的是一種鍵值對容器,裡面的資料都是成對出現的,如下圖:每一對中的第一個值稱之為關鍵字(key),每個關鍵字只能在map中出現一次;第二個稱之為該關鍵字的對應值。
map內部自建一顆紅黑樹(一 種非嚴格意義上的平衡二叉樹),這顆樹具有對資料自動排序的功能,所以在map內部所有的資料都是有序的。
map和multimap都需要#include
pair
也在std中(vector,list,map也在std中),但是在map中有應用,所以先講一下。
其標準庫型別–pair型別定義在#include 標頭檔案中,定義如下:
(好像utility和iostream都可以,這是為什麼呢???)
類模板:template<class T1,class T2> struct pair
引數:T1是第一個值的資料型別,T2是第二個值的資料型別。
功能:pair將一對值(T1和T2)組合成一個值,這一對值可以具有不同的資料型別(T1和T2), 兩個值可以分別用pair的兩個公有函式first和second訪問。
定義建構函式
pair<T1, T2> p1; //建立一個空的pair物件(使用預設構造),它的兩個元素分別是T1和T2型別,採用值初始化。
pair<T1, T2> p1(v1, v2); //建立一個pair物件,它的兩個元素分別是T1和T2型別,其中first成員初始化為v1,second成員初始化為v2。
make_pair(v1, v2); // 以v1和v2的值建立一個新的pair物件,其元素型別分別是v1和v2的型別。
p1 < p2; // 兩個pair物件間的小於運算,其定義遵循字典次序:如 p1.first < p2.first 或者 !(p2.first < p1.first) && (p1.second < p2.second) 則返回true。
p1 == p2; // 如果兩個物件的first和second依次相等,則這兩個物件相等;該運算使用元素的==操作符。
p1.first; // 返回物件p1中名為first的公有資料成員
p1.second; // 返回物件p1中名為second的公有資料成員
例如:
pair<string, string> anon; // 建立一個空物件anon,兩個元素型別都是string
pair<string, int> word_count; // 建立一個空物件 word_count, 兩個元素型別分別是string和int型別
pair<string, vector<int> > line; // 建立一個空物件line,兩個元素型別分別是string和vector型別
//下面是定義的時候初始化
pair<string, string> author("James","Joy"); // 建立一個author物件,兩個元素型別分別為string型別,並預設初始值為James和Joy。
pair<string, int> name_age("Tom", 18);
程式碼:
#include<iostream>
#include <tuple>//用於包含tie,std:Ltie
using namespace std;
//std::pair std::tie
std::pair<std::string, int> getPreson() {
return std::make_pair("Sven", 25);
}//這個是函式,返回值為pair型別
int main()
{
/********訪問***************/
pair<int ,double> p1;
p1.first = 1;
p1.second = 2.5;
cout<<p1.first<<' '<<p1.second<<endl;
/*****利用make_pair建立新的pair物件**/
pair<int, double> p3;
p3 = make_pair(1, 1.2);
cout << p3.first << p3.second << endl;
/*****通過std::tie獲取pair元素值***/
string name;
int ages;
tie(name, ages) = getPreson();
cout << "name: " << name << ", ages: " << ages << endl;
}
map
map中的元素是自動按Key升序排序,所以不能對map用sort函式;
程式碼理解:
#include <map>
#include <string>
#include <iostream>
using namespace std;
int main()
{
map<int, string> mapStudent =
{
{0,"student_zero"}
}; //初始化
std::pair<map<int, string>::iterator, bool> ret;
mapStudent[1] = "student_one";//陣列插入
ret = mapStudent.insert(pair<int, string>(1, "student_two")); //pair插入,並返回是否插入成功
mapStudent.insert(map<int, string>::value_type (2, "student_two"));//value_type插入
map<int, string>::iterator iter; //迭代器訪問
for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
cout<<iter->first<<' '<<iter->second<<endl;
if(!mapStudent.empty())
{
cout<<"size:"<<mapStudent.size()<<endl;//map的大小
cout<<"max_size:"<<mapStudent.max_size()<<endl;//最多存多少,和記憶體有關?
cout<<"map count"<<mapStudent.count(3)<<endl;//查詢key的value個數,map非0即1
}
/********find*****/
iter = mapStudent.find(1);
cout<<"find num 1:"<<iter->second<<endl;
/*****erase*****/
map<int, string>::iterator iter_1; //迭代器訪問
iter_1 = mapStudent.erase(iter);
cout<<"iter:"<<iter->second<<endl;//原來的迭代器還在指向
cout<<"num 1:"<<iter_1->second<<endl<<endl;
for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
cout<<iter->first<<' '<<iter->second<<endl;
}