您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關C++如何實現STL容器的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
1.可以用下標訪問的容器有(既可以插入也可以賦值):vector、deque、map;
特別要注意一下,vector和deque如果沒有預先指定大小,是不能用下標法插入元素的!
2. 序列式容器才可以在容器初始化的時候制定大小,關聯式容器不行;
3.注意,關聯容器的迭代器不支持it+n操作,僅支持it++操作。
適配器的意思就是將某些已經存在的東西進行限制或者組合變成一個新的東西,這個新的東西體現一些新的特性,但底層都是由一些已經存在的東西實現的。
vector :矢量(并非數學意義上的) STL最簡單的序列類型,也是一些適配器的默認底層類
deque:雙端隊列可從頭尾出隊入隊
list:雙向鏈表
forwardd_list:單向鏈表,功能少一些,不可反轉。
queue:隊列,一個適配器類(底層模板類默認deque),不允許隨機訪問和歷遍;展示隊列的接口
priority_queue:優(yōu)先隊列,一個適配器類(底層模板類默認vector),默認大根堆(最大的元素在最前面)。
stack:棧,一個適配器類(底層模板類默認vector),給底層類提供典型的棧接口。
特別的
array:并非STL容器,長度固定,但也能使用一些STL算法
容器基本都有以下幾種功能,具體情況視容器而定
p,q,i,j表示迭代器
序列基本要求,拿vector舉例,p , q , i , j 表示迭代器
vector <int> vec (n,t); //創(chuàng)建并初始化 vector <int> (n,t); //創(chuàng)建匿名對象并初始化 vector <int> vec (i,j); //創(chuàng)建并初始化為另一個容器[i,j)內容 vector <int> (i,j); //創(chuàng)建匿名對象并初始化為另一個容器[i,j)內容 vec.insert(p,t); //插入t到p的前面 vec.insert(p,n,t); //插入n個t到p的前面 vec.insert(p,i,j); //將區(qū)間[i,j)插入到p的前面(可以為自己的區(qū)間后者其他容器的區(qū)間) vec.erase(p); //刪除p指向的元素 vec.erase(p,q); //刪除[p,q)區(qū)間的元素 vec.clear(); //清空容器,等價于vec.erase(vec.begin(),vec.end());
一些可選要求,見名知義了,不解釋。
.front(); .back(); .push_front(); .push_back(); .pop_front(); .pop_back(); [n] .at(n);
.at()和 [ ]很像,不過前者在越界是會引發(fā)一個異常,我們可以進行捕獲
用雙端隊列演示上面的一些
#include <iostream> #include <deque> #include <algorithm> using namespace std; void show(int & t) { cout << t << " "; } int main() { deque<int> a(10,5); a.push_front(10); a.push_back(20); for_each(a.begin(),a.end(),show); cout << endl; a.pop_front(); a.pop_back(); for_each(a.begin(),a.end(),show); a.push_back(999); cout << endl << a.at(10) << " " << a[10]; try{ cout << endl << a.at(100); } catch (out_of_range){ cout << "越界訪問"; } return 0; }
運行結果
一些queue的方法
可以用其進行堆排序
int main() { srand((unsigned)time(NULL)); priority_queue<int> pq; for(int i=0;i<100;i++){ int x = rand() %1000+1; pq.push(x); } for(int i=0;i<100;i++){ cout << pq.top() << " "; if(i%10 == 0) cout << endl; pq.pop(); } return 0; }
運行結果
時間復雜度O(nlogn),因為是基于樹形結構,每次pop時間復雜度O(logn),進行n次。
一些方法
list的一些基本成員函數
void merge(list<T, Alloc> & X)
鏈表x與調用鏈表合并,在合并之前必須進行排序。合并后的鏈表存儲在調用鏈表中,x變?yōu)榭真湵?。線性時間復雜度
void remove(const T &val)
刪除表中的所有val,線性時間復雜讀。
void sort()
因為 list 不支持隨機訪問,不能使用 std::sort(),但是可以使用自帶的 sotr,時間復雜度 O(nlogn)
void (iterator pos, list <T, Alloc> x)
將x鏈表插入到pos的前面,x變?yōu)榭?。固定時間復雜度。
void unique() 將連續(xù)的相同元素壓縮為單個元素。線性時間復雜度
示例
#include <iostream> #include <list> #include <algorithm> using namespace std; void show(int & t) { cout << t << " "; } ostream & operator<<(ostream & os, list<int> & s) { for_each(s.begin(),s.end(),show); return os; } int main() { list <int> one (5,2); list <int> two (5,3); list <int> three; int num[5] = {1,6,3,5,2}; three.insert(three.begin(),num,num+5); cout << "list one is " << one << endl; cout << "list two is " << two << endl; cout << "list three is(use insert) " << three << endl; three.sort(); cout << "list three use sort " << three << endl; three.merge(two); cout << "list three use merge to list two \n" << "now list two is empty: "; cout << "list two is " << two << endl; cout << "now list three is " << three << endl; three.splice(three.begin(),one); cout << "three use splice to one \n" << "now list one is empty: "; cout << "now list one is " << one << endl; cout << "now list three is " << three << endl; three.unique(); cout << "three use unique is " << three << endl; three.sort(); cout << "list three use sort and unique: " << three << endl; three.remove(3); cout << "now use remove delete 3: " << three; return 0; }
運行結果
注意merge(),不是簡單的拼接,是有順序的合并。而spille()才是拼接(插入)。
一些方法
一些方法
關聯容器是隊容器概念的另一個改進,關聯容器將數據和關鍵字(key)存放在一起,用關鍵字來快速的查找數據。
STL提供了四種關聯容器,set, multiset, map, multimap。
set(關聯集合)
可翻轉,可排序,并且存儲進去的時候自動排好序。關鍵字唯一即一個數據有且只有一個關鍵字并且與存儲類型相同。
#include <iostream> #include <algorithm> #include <set> #include <iterator> using namespace std; int main() { const int n =6; string str[n] = {"hello", "world", "i am", "set use","C++","union"}; //構造函數接受兩個迭代器表示區(qū)間,初始化為區(qū)間內的內容 set<string> A(str,str+6); ostream_iterator<string,char> out(cout,"\n"); copy(A.begin(),A.end(),out); return 0; }
運行結果
可以看見其已經自動排序
一些set的類方法
lower_bound()——接受一個關鍵字參數,返回一個迭代器,該迭代器指向第一個不小于關鍵字成員的參數(可能以關鍵字對應數開頭,也可能不是)。
upper_bound()——同上,該迭代器指向第一個大于關鍵詞的成員(類似超尾)。
演示
#include <iostream> #include <algorithm> #include <set> #include <iterator> using namespace std; int main() { const int n =6; string str[n] = {"hello", "world", "i am", "set use","C++","union"}; set<string> A(str,str+6); ostream_iterator<string,char> out(cout,"\n"); //find string from b to r copy(A.lower_bound("b"),A.upper_bound("s"),out); return 0; }
運行結果
因為upper_bound()返回的是類似超尾迭代器的迭代器,所以不包括以‘s’開頭的字符串
因為底層以樹形結構實現得以快速查找,所以用戶不能指定插入位置。并且插入后自動排序。
可反轉,自動排序,關鍵字可與數據類型不同,一個關鍵字可與多個數據關聯。
//<const key,type_name> mutimap <int,string> mp;
為了將信息結合在一起,數據與關鍵字用一個pair存儲,所以插入等操作要插入pair
一些方法
count()——接受一個關鍵字參數,返回該關鍵字所對應得數據個數。
lower_bound(), upper_bound(),同set。
equal_range()——接受一個關鍵字參數,返回兩個迭代器,表示與該關鍵字所對應的區(qū)間,并且用一個二元組封裝。
演示
#include <iostream> #include <iterator> #include <map> using namespace std; typedef pair<int,string> Pair; int main() { Pair p[6]={{6,"啤酒"}, {10,"炒飯"}, {80,"烤豬頭"}, {10,"冷面"}, {5,"早餐"}, {80,"給你一錘子"}}; multimap<int,string> mulmap; // no operator < cout << "現在圖中存儲的關鍵字和數據是:" << endl; multimap<int,string> ::iterator i; for(int i =0;i<6;i++){ mulmap.insert(p[i]); } for(auto i=mulmap.begin(); i!=mulmap.end(); i++){ cout << i->first << " " << i->second << endl; } cout << "使用count函數找到價格為80的菜品個數為:" << mulmap.count(80) << endl; pair<multimap<int,string>::iterator,multimap<int,string>::iterator> temp; cout << "使用equal_range函數找到價格為80的菜品" << endl; temp = mulmap.equal_range(80); for(auto i = temp.first;i!=temp.second;i++){ cout << i->second; } return 0; }
運行結果
map(圖)和multiset(多關聯集合)的使用與上面類似。
可以感覺到,關聯容器底層基于某種數據結構,像樹,能使其快速的進項操作。但又是因為樹的原因,使得每個節(jié)點必須有著嚴格規(guī)定。
還有無序關聯容器,底層數據結構基于哈希表(每個元素對應其映射,就像關鍵字一樣)。
有四種:
unordered_set
unordered_multiset
unordered_map
unordered_multimap
和關聯序列的方大同小異,在應用場景上會有些許不同。
感謝各位的閱讀!關于“C++如何實現STL容器”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。