包括 vector、deque、list、queue和stack、priority_queue、bitset、set和multiset、map和multimap等等。
vector 使用代碼如下:
#include#include using namespace std; //使用迭代器正序輸出 vector 元素 void print(vector v,char s[]) { vector ::iterator it; cout< v1; //默認構造函數,創建一個空的 vector vectorv2(2); //創建一個大小為2的 vector vector v3(3,0); //穿件一個 vector,並填充3個0 vector v4(v3); //拷貝構造函數,創建v3的副本v4 v1.push_back(1); //在尾部添加1,此時v1:1 v1.insert(v1.end(),2); //在尾部添加2,此時v1:12 v1.insert(v1.begin(),2,0); //在首部添加2個0,此時v1:0012 v1.insert(v1.begin(),v1.begin(),v1.end()); //在首部添加v1所有內容,此時v1:00120012 print(v1,"v1"); cout<
template可以發現構造 stack 時傳入的容器對象即為 stack 類的成員函數 _Container c,棧的各元素都存儲於 c 中。查看 push() 函數得知, stack 的 push() 實際上是調用了 c.push__back(),也就是說,stack 實際上只是調用了傳入的容器對象的原有函數而已,它的各種操作函數只是起到一個適配器的作用,幾乎沒有自己獨有的功能。廣而言之,stack 類是對基礎容器類的再封裝,不是重新定義,queue 類也很相似。注意!由於 queue 類有 T& front() 函數,因此要求封裝的容器必須有 pop_front()函數,因此 vector 不能被封裝為 queue。> class stack { protected: _Container c; // the underlying container public: ...... stack(): c() { // 使用容器類的默認構造函數 } explicit stack(const _Container& _Cont): c(_Cont) { //使用容器類的拷貝構造函數 } void push(value_type&& _Val) { c.push_back(_STD move(_Val)); } size_type size() const { return (c.size()); } ...... };
#include <iostream> #include <queue> #include <string> #include <vector> using namespace std; class student { public: int number; //學號 string name; //姓名 int math; //數學成績 int chinese; //語文成績 public: student(int number,const string &name,int math,int chinese) { this->number=number; this->name=name; this->math=math; this->chinese=chinese; } friend ostream& operator << (ostream& out,const student& s) { cout<<"學號:"<<s.number<<"\t姓名:"<<s.name<<"\t數學:\t"<<s.math<<"\t語文:"<<s.chinese<<endl; return out; } bool operator < (const student& s) const { //先比較數學成績,相同再比較語文成績,相同再比較學號 //return this->number < s.number; if(this->math < s.math) return true; if(this->math == s.math && this->chinese < s.chinese) return true; if(this->math == s.math && this->chinese == s.chinese && this->number < s.number) return true; return false; } }; int main() { priority_queue<student,vector<student>,less<student> > p; p.push(student(3,"李世民",60,70)); p.push(student(1,"秦始皇",70,90)); p.push(student(2,"康熙",70,50)); while(!p.empty()) { cout<<p.top(); p.pop(); } return 0; }
輸出:
學號:1 姓名:秦始皇 數學: 70 語文:90
學號:2 姓名:康熙 數學: 70 語文:50
學號:3 姓名:李世民 數學: 60 語文:70
上述程序中有一個 student 類,主函數以 vector 為內置容器建立了一個優先隊列,並使用 less
bitset 容器
C 是一種"接近硬件"的語言,但 C 語言並沒有固定的二進制表示法。bitset 可以看做是二進制位的容器,並提供了位的相關操作數。
bitset常用函數如下所示:
(1)構造函數
bitset
bitset
bitset
bitset
bitset& operator= (const bitset&); //賦值操作
(2)邏輯運算操作
bitset& operator &= (const bitset&); //返回兩個位容器 & 運算後的引用,並修改第一個位容器值
bitset& operator |= (const bitset&);
bitset& operator ^= (const bitset&);
bitset& operator << = (size_t n); //返回位容器左移 n 位後的引用,並修改第一個位容器值
bitset& operator >> = (size_t n);
bitset operator << (size_t n) const; //返回位容器左移 n 位後的備份
bitset operator >> (size_t n) const;
bitset operator & (const bitset&,const bitset&); //返回兩個位容器 & 運算後的備份
bitset operator | (const bitset&,const bitset&);
bitset operator ^ (const bitset&,const bitset&);
(3)其他操作函數
string to_string(); //將位容器內容轉換成字符串
size_t size() const; //返回位容器大小
size_t count() const; //返回設置成 1 的位個數
bool any() const; //是否有位設置 1
bool none() const; //是否沒有為設置 1
bool test(size_t n)const; //測試某位是否為 1
bool operator[](size_t n)const; //隨機訪問位元素
unsigned long to_ulong() const; //若沒有溢出異常,返回無符號長整型數
bitset& set(); //位容器所有位置 1
bitset& flip(); //位容器所有位翻轉
bitset& reset(); //位容器所有位置 0
bitset& set(size_t n,int val=1); //設置某位為 1 或 0,默認為 1
bitset& reset(size_t n); //復位某位為 0
bitset& flip(size_t n); //翻轉某位
bitset 容器的使用比較簡單,這裡直接給出一個它的簡易應用。已知有 n 個整形數組,長度都是 10,元素都在[1,20]之間,且均遞增排列,無重復數據。試利用 bitset 壓縮這些數組,並存入文件中。
分析:一個數組大小=4*10=40字節,而每一位數字其實都能用一個20位大小的 bitset 容器存儲,數字是幾位容器的第幾位就是幾。如一個數n=5,則存儲為 00000000000000010000。20位相當於2.5字節,與原先的40字節相比,壓縮成了原來的1/16。但實際上文件操作的最小單位是字節,無法讀寫2.5字節,因此位容器需要選擇24位大小,這樣讀寫操作正好是3字節了。
使用 bitset 壓縮數組代碼如下:
#include <bitset> #include <iostream> #include <fstream> using namespace std; template <size_t N> class Mynum { public: bitset<N> b; public: void set(int array[],int nSize) { b.reset(); for(int i=0;i<nSize;i++) { b.set(array[i]-1,1); } } }; int main() { int a[4][10]={ {1,2,3,4,5,6,7,8,9,10}, {11,12,13,14,15,16,17,18,19,20}, {2,4,6,8,10,12,14,16,18,20}, {1,3,5,7,9,11,13,15,17,19}}; fstream out("test.txt"); Mynum<24> m; for(int i=0;i<4;i++) { m.set(a[i],(sizeof(a[i])/sizeof(int))); out.write((char*)&(m.b),3); //將bitset寫入文件 } out.close(); ifstream in("test.txt"); bitset<24> b; if(!in) return 0; else { for(int k=0;k<4;k++) { in.read((char*)(&b),3); //從文件中讀出並存儲到bitset中 for(int i=0;i<24;i++) { if(b.test(i)) { cout<<i+1<<"\t"; } } cout<<endl; } } in.close(); return 0; }
輸出:
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
2 4 6 8 10 12 14 16 18 20
1 3 5 7 9 11 13 15 17 19
實際中應該把 main 函數中的寫入讀出功能封裝至 Mynum 類中,這裡為了簡便就這麼寫了。可以在程序目錄下找到"test.txt",可以看到其大小為12字節,而正常存儲40個int應該為160字節。
set和multiset
multiset 與 set 的區別就是 multiset 允許重復元素存在,兩者都是有序集合。
大部分函數與之前介紹的容器的函數類似,這裡就介紹下獨有的函數。
首先需要介紹 pair 數據結構,定義如下:
template <class T,class U> struct pair : public _Pair_base<T, U> { typedef T first_type; typedef U second_type; T first; U second; pair(); pair(const T&x,const U& y); template <class V,class W> pair(const pair<V,W>& pr); }
在父結構 _Pair_base 中定義了 T first;U second; 簡單地說 pair 是有著兩個動態類型成員變量的數據結構。
(1)插入函數:
pair
(2)操作函數
const_iterator lower_bound(const Key& key); //返回容器元素大於等於 key 的迭代指針,否則返回 end()
const_iterator upper_bound(const Key& key); //返回容器元素大於 key 的迭代指針,否則返回 end()
pair
可以發現,equal_range() 返回的 pair 的first 即是 lower_bound(),其 second 即是 upper_bound()。
map和multimap
在之前的容器中,僅保存著一樣東西,但是在 map和multimap 中將會得到兩樣東西,關鍵字 Key 和以關鍵字查詢得到的結果值 Value,即一對值
map和multimap使用代碼如下:
#include <map> #include <string> #include <iostream> using namespace std; int main() { map<string,string> m; m["1-1"]="元旦節"; //使用賦值形式添加映射,鍵在[]內,值在賦值號右側 m["5-1"]="勞動節"; pair<string,string> p("8-1","建軍節"); //使用鍵值對通過 insert() 添加 m.insert(p); cout<<m["8-1"]; return 0; }