STL概念
STL是C++標準庫最重要的組成部分,STL即標準模板庫,不僅是一個可複用的組件庫,而且是一個包羅算法和數據結構的軟件框架。
STL的六大組件
- 容器 - 一些數據結構
- 迭代器
- 空間配置器
- 適配器
- 算法
- 仿函數
以算法和容器爲核心。
容器
容器是用來存放數據的,因爲現實中我們考慮到不同的應用場景,所以需要最合適的容器來存放數據。
常見的數據結構:array、list、tree、stack、queue、hash table、map、set等,因此STL中的 容器便是對各種不同數據結構的封裝。
根據數據在容器中的排序特性,容器分爲序列式容器和關聯式容器。
序列式容器:序列式容器中的元素次序:即是按照其加入容器中的先後次序,不一定有序,典型的就像vector,list
關聯式容器:關聯式容器中存放的是一個一個的鍵值對。 鍵值對其實是一個結構體,該結構體中有兩個字段,一個爲key,一個爲value,key和 value具有一一對應的關係。因此關聯式容器中實際存放的是鍵值對的結構體。典型的就像 avl樹
適配器
適配器也是一種設計模式,這種模式是將一個類的接口轉換成用戶希望的另外一個接口。可以理解爲將一個已經實現的類的結構包裝爲我們當前所需要的結構,就達到了適配的目的。
- 容器適配器,比如stack和queue就是對 deque的接口進行了轉調;
- 迭代器適配器,比如反向迭代器就是對迭 代器的接口進行了轉調;
- 應用於仿函數的即函數適配器
棧和隊列都是特殊的數據結構,因爲要在特殊的位置進行插入和刪除。
deque是雙端隊列,彌補了vector刪除和插入時間複雜度大還有擴容的不足,同時也彌補了不能隨機訪問的缺點。
以上截圖來源於cplusplus
迭代器
迭代器是一種抽象的設計概念,是設計模式的一種,其定義如下:提供一種方法,使之能夠依次尋訪某個容器中所包含的所有元素,而又無需暴露該容器底層的結構。
STL設計的中心思想在於:將數據容器和算法分離開,彼此獨立設計,算法要操作容器中的元素時,通過迭代器去訪問即可。因此,算法不需要去關心所操作數據底 層的結構,只要能夠按照迭代器去尋訪到所需的數據即可,實現其通用性。
//現有一順序表 vector<int> v,利用迭代器遍歷順序表的方法如下
vector<int>::iterator it = v.begin();
while(it != v.end())
{
cout<<*it<<endl;
++it;
}
//現有一鏈表 list<int> l,利用迭代器遍歷鏈表的方法如下
list<int>::iterator l = l.begin();
while(it != l.end())
{
cout<<*it<<endl;
++it;
}
觀察上述兩個代碼,遍歷不同的數據結構,但是用了幾乎一模一樣的代碼去完成的,其實順序表的迭代器就是一個原生的指針,在完成解引用和++操作,鏈表的迭代器就是一個函數調用,當你解引用時,他會調用函數返回鏈表節點的data,當你++時,他會調用函數返回當前節點的next,這就是迭代器的優點,他並不把底層的實現告訴你,你只管使用就好了,這樣做也降低了學習成本,更是體現了封裝性。
仿函數
仿函數:又叫函數對象,一種行爲類似函數的對象,調用者可以向函數一樣使用該對象。 其實現起來也比較簡單:用戶只需要實現一種新類型,在類中重載()即可,參數根據用戶所要進行的操作選擇匹配。
下面以冒泡排序舉例
#include <iostream>
using namespace std;
template<class T>
class Less
{
public:
bool operator()(const T& left,const T& right)
{
return left < right;
}
};
template<class T>
class Greater
{
public:
bool operator()(const T& left,const T& right)
{
return left > right;
}
};
template<class T,class Com>
void BubbleSort(T* array,size_t size,Com Compare)
{
for(size_t i = 0; i < size - 1; ++i)
{
bool flag = false;
for(size_t j = 0; j < size - i - 1; ++j)
{
if(Compare(array[j],array[j+1]))
{
swap(array[j],array[j+1]);
flag = true;
}
}
if(flag == false)
return;
}
}
void PrintArr(int* array,size_t size)
{
for(size_t i = 0; i < size; ++i)
{
cout<<array[i]<<" ";
}
cout<<endl;
}
int main()
{
int arr[] = {5,4,6,3,9,1,2,5,8,0};
BubbleSort<int>(arr,sizeof(arr)/sizeof(arr[0]),Less<int>());
PrintArr(arr,sizeof(arr)/sizeof(arr[0]));
BubbleSort<int>(arr,sizeof(arr)/sizeof(arr[0]),Greater<int>());
PrintArr(arr,sizeof(arr)/sizeof(arr[0]));
return 0;
}
這時候的排序結果會根據所傳入的函數進行排序。
算法
算法是以有限的步驟,解決數學或邏輯中的問題。 算法只關心操作的步驟,與數據的結構沒有任何 的關係,而且STL在設計時就有一個目標,就是算法可複用,效率要儘可能的高。STL中 收錄了極具複用價值的70多個算法,包括:排序,查找,排列組合,數據移動,拷貝, 刪除,比較組合,運算等。
舉一個用sort算法排序的例子
#include <iostream>
using namespace std;
#include <algorithm>
#include <vector>
void PrintVector(vector<int> v)
{
vector<int>::iterator it = v.begin();
while(it != v.end())
{
cout<<*it<<" ";
++it;
}
cout<<endl;
}
void test_sort()
{
vector<int> v;
for(size_t i = 0; i < 50; ++i)
{
v.push_back(rand()%100);
}
cout<<"before sort"<<endl;
PrintVector(v);
sort(v.begin(),v.end(),less<int>());
cout<<"after sort"<<endl;
PrintVector(v);
}
int main()
{
srand((unsigned)time(NULL));
test_sort();
return 0;
}