STL容器
stl提供了大量成熟的容器供我們存儲數據,在連接各自容器的特點的情況下,選擇性的使用最合適的容器,會使代碼質量與性能大大提升,下面記錄下各自常用容器的特性:
1. std::vector
vector是一種非常常用的數組類型的容器,使用非常方便,但在某些場景下,其數據結構並不能帶來良好的性能優勢。
2. rb_tree(紅黑樹)
這裏不過深的探究紅黑樹的數據結構及其旋轉樹形邏輯,主要是因爲stl中常用的容器如map,set,內部都是封裝的rb_tree來實現其功能的,所以有必要提前瞭解一下紅黑樹的一些規則及簡單使用。
3. set/multiset
set/multiset相當於紅黑樹的一種容器適配器(container adapter),因爲其底層封裝了一個紅黑樹對象,其所有的操作都是由該對象來完成的
#include <set>
#include <stdlib.h> // rand()
#include <time.h>
void TestSet()
{
std::set<int> mySet = {1, 5,2,8,4};
for (const auto& i : mySet) {
std::cout << i << " ";
}// 1 2 4 5 8
mySet.insert(5); // b不報錯,但也不會插入
std::multiset<int> myMultiSet = { 1, 5,2,8,4 };
for (const auto& i : mySet) {
std::cout << i << " ";
}// 1 2 4 5 8
myMultiSet.insert(5);// 1 2 4 5 5 8
std::cout << std::endl;
auto itr = myMultiSet.begin();
std::cout << *itr;
// *itr = 2; // 編譯不通過
// 測試集合的搜索效率
// 插入100,0000個隨機元素,可能會存在重複值
std::multiset<int> bigSet;
// int 4個字節 取值範圍 -2147483648~2147483647[-2^31~2^31-1]
// rand() 返回值範圍0~32767
clock_t start, end;
start = clock();
int length = 1000000;
for (int i = 0; i < length; ++i) {
bigSet.insert(rand());
}
end = clock();
std::cout << "insert element cost time: " << double(end - start) << "個CPU時鐘單元";//14502
int findVal = 3456;
// 用std::find算法查找
start = clock();
auto res = std::find(bigSet.begin(), bigSet.end(), findVal);
end = clock();
std::cout << "std::find cost time: " << double(end - start) << "個CPU時鐘單元";//27
if (res != bigSet.end()) {
std::cout << "Find;";
}
else {
std::cout << "Not Find;";
}
//用集合自帶的find接口查找
start = clock();
res = bigSet.find(findVal);
end = clock();
std::cout << "set.find cost time: " << double(end - start) << "個CPU時鐘單元";//0
if (res != bigSet.end()) {
std::cout << "Find;";
}
else {
std::cout << "Not Find;";
}
}
4. map/multimap
map/mmultimap也相當於紅黑樹的一種容器適配器(container adapter),因爲其底層封裝了一個紅黑樹對象,其所有的操作都是由該對象來完成的,與set/multiset的區別在於key與value不同,需要傳入key和data兩個值
#include <map>
void TestMap()
{
std::map<int, std::string> myMap = { {1, "a"}, {5, "e"}, {3, "c"},{9,"d"} };
for (const auto& iEle : myMap) {
std::cout << iEle.first<< " ";
}// 1 3 5 9
myMap.insert(std::pair<int, std::string>(5, "g")); // b不報錯,但也不會插入
myMap[15] = "dfd";
myMap[1] = "op";
std::multimap<int, std::string> myMultiMap = { {1, "a"}, {5, "e"}, {3, "c"},{9,"d"} };
for (const auto& iEle : myMultiMap) {
std::cout << iEle.first << " ";
}// 1 2 4 5 8
myMultiMap.insert(std::pair<int, std::string>(5, "g"));// 1 2 4 5 5 8
std::cout << std::endl;
auto itr = myMultiMap.begin();
itr->second = "gh";
// myMultiMap[1] = "787"; // 編譯報錯
}
5. std::list
list是一種環狀的雙向鏈表,其插入和刪除元素比較高效