標準模板類(STL)(二),具體容器簡介

(二)容器的具體介紹

A、順序式容器

1、vector

該標準容器是一個定義在 namespace std 中的模板,該模板的原型聲明在頭文件 <vector> 中。它的數據結構很像一個數組,所以與其他容器相比,vector 能非常方便和高效訪問單個元素。因此,在 vector 中提供隨機訪問循環子。

說明:實際上就是個動態數組。隨機存取任何元素都能在常數時間完成。在尾端增刪元素具有較佳的性能。例1:

int main()  

{ int i;

 int a[5] = {1,2,3,4,5 };    

    vector<int>  v(5);

 cout << v.end()-v.begin() << endl;

 for( i = 0;i < v.size();i ++ )  v[i] = i;

 v.at(4) = 100;

 for( i = 0;i < v.size();i ++ )

 cout << v[i] << "," ;

 cout << endl;

 vector<int> v2(a,a+5);  //構造函數

 v2.insert( v2.begin() + 2, 13 ); //在begin()+2位置插入 13

 for( i = 0;i < v2.size();i ++ )

 cout << v2[i] << "," ;    

return 0;

}

輸出:

5

0,1,2,3,100,

1,2,13,3,4,5,

例2:

int main()  {

 const int SIZE = 5;

 int a[SIZE] = {1,2,3,4,5 }; 

 vector<int> v (a,a+5);  //構造函數

 try {

  v.at(100) = 7;

 }

 catch( out_of_range e) {

  cout << e.what() << endl;

 }

 cout << v.front() << “,” << v.back() << endl;

 v.erase(v.begin());

 ostream_iterator<int> output(cout ,“*");

 copy (v.begin(),v.end(),output);

 v.erase( v.begin(),v.end());  //等效於 v.clear();

 if( v.empty ())

  cout << "empty" << endl;

 v.insert (v.begin(),a,a+SIZE);

 copy (v.begin(),v.end(),output);

}  

// 輸出:

invalid vector<T> subscript

1,5

2*3*4*5*empty

1*2*3*4*5*

ostream_iterator<int> output(cout ,“*");//定義了一個 ostream_iterator 對象,可以通過cout輸出以 * 分隔的一個個整數

copy (v.begin(),v.end(),output);//導致v的內容在 cout上輸出

copy 函數模板(算法):

template<class InIt, class OutIt> 

OutIt copy(InIt first, InIt last, OutIt x); //本函數對每個在區間[0, last - first)中的N執行一次 *(x+N) = * ( first + N) ,返回 x + N

對於copy (v.begin(),v.end(),output);

first 和 last 的類型是  vector<int>::const_iterator,output 的類型是 ostream_iterator<int> 

例3

#include "iostream"

#include "vector"

#include "algorithm"

using namespace std;

int main()

{

istream_iterator<int>inputInt(cin);

int n1,n2;

n1=*inputInt;

inputInt++;

n2=*inputInt;

cout<<n1<<" "<<n2<<endl;

ostream_iterator<int>outputInt(cout);

*outputInt=n1+n2;

cout<<endl;

int a[5]={1,2,3,4,5};

copy(a,a+5,outputInt);

return 1;

}

輸出結果爲:

78,90

168

12345

2、list

該標準容器是一個定義在 namespace std 中的模板,該模板的原型聲明在頭文件 <list> 中。list 是一個對容器元素的插入和刪除操作進行了優化的序列。但與 vector 和 deque 相比,對元素的下標訪問操作的低效是不能容忍的,因此 list 不提供這類操作,即不提供隨機訪問循環子,而提供雙向循環子。這意味着 list 是典型的通過使用雙鏈表實現的序列結構。

說明:雙向鏈表,在任何位置增刪元素都能在常數時間完成。不支持隨機存取。  

對於 list,front 操作和 back 操作都同樣高效和方便。因此,如果希望使用 list 編寫的代碼演變爲能應用於多種其他容器的通用代碼,則使用更具廣泛適用性的 back 操作是最好的選擇。list 元素的插入和刪除操作尤爲高效,所以 list 更適合在插入和刪除操作頻繁的應用中使用。

#include "list"

#include "iostream"

using namespace std;

typedef list<int> LISTINT;

int main()

{

int rgTest1[] = {5,6,7};

int rgTest2[] = {10,11,12};

LISTINT listInt;

LISTINT::iterator i;

// Insert one at a time

listInt.insert (listInt.begin(), 2);

listInt.insert (listInt.begin(), 1);

listInt.insert (listInt.end(), 3);

// output: 1 2 3

cout << "listInt:";

for(i=listInt.begin();i!=listInt.end();i++)

 cout << " " << *i;

cout <<endl;

// Insert 3 fours

listInt.insert(listInt.end(),3,4);

// output: 1 2 3 4 4 4

cout <<"listInt:";

for (i=listInt.begin();i!=listInt.end();++i)

 cout <<" "<< *i;

cout<<endl;

// Insert an array at the end

listInt.insert(listInt.end(),rgTest1,rgTest1+3);

// output: 1 2 3 4 4 4 5 6 7

cout << "listInt:";

for (i=listInt.begin(); i!=listInt.end();++i)

 cout << " " << *i;

cout <<endl;

// Insert another LISTINT

LISTINT listAnother;

listAnother.insert (listAnother.begin(),rgTest2,rgTest2+3);

listInt.insert (listInt.end(), listAnother.begin(), listAnother.end());

// output: 1 2 3 4 4 4 5 6 7 10 11 12

cout << "listInt:";

for (i=listInt.begin();i!=listInt.end();++i)

 cout <<" "<<*i;

cout <<endl;

return 1;

}

3、deque

       該標準容器是一個定義在 namespace std 中的模板,該模板的原型聲明在頭文件 <deque> 中。deque 是一個雙向隊列,也是一個優化序列。在 deque 兩端的操作與 list 一樣高效,對元素的下標操作的效率又與 vector 類似,而對容器元素的插入和刪除操作的效率則介於 list 和 vector 之間。

說明:也是個動態數組,隨機存取任何元素都能在常數時間完成(但性能次於vector)。在兩端增刪元素具有較佳的性能。

      所有適用於vector的操作都適用於deque。deque還有push_front(將元素插入到前面)和pop_front(刪除最前面的元素)操作

上述三種容器稱爲順序容器,是因爲元素的插入位置同元素的值無關。

B、關聯式容器

關聯式容器內的元素是排序的,插入任何元素,都按相應的排序準則來確定其位置。關聯式容器的特點是在查找時具有非常好的性能。

set 即集合,set中不允許相同元素,multiset中允許存在相同的元素。

map與set的不同在於map中存放的是成對的key/value,並根據key對元素進行排序,可快速地根據key來檢索元素;map同multimap的不同在於是否允許多個元素有相同的key值。

上述4種容器通常以平衡二叉樹方式實現,插入和檢索的時間都是 O(logN)。

       內部元素有序排列,新元素插入的位置取決於它的值,查找速度快。

        map關聯數組:元素通過鍵來存儲和讀取;

      set大小可變的集合,支持通過鍵實現的快速讀取。

        multimap支持同一個鍵多次出現的map類型;

        multiset支持同一個鍵多次出現的set類型。

與順序容器的本質區別

       關聯容器是通過鍵(key)存儲和讀取元素的,它要求定義一個比較操作進行元素操作。而順序容器則通過元素在容器中的位置順序存儲和訪問元素。 

4、map該標準關聯容器是一個定義在 namespace std 中的模板,該模板的原型聲明在頭文件 <map> 中。 map 是一個元素對(關鍵字,映射值)序列(注:Hash table (key, value pairs)),它提供了以關鍵字爲基礎的快速檢索。map 中的每一個關鍵字必須是唯一的。map 提供雙向循環子。

元素按照關鍵字升序排列,缺省情況下用 less 定義“小於”。

可以用pairs[key] 訪形式問map中的元素。pairs 爲map容器名,key爲關鍵字的值。該表達式返回的是對關鍵值爲key的元素的值的引用。(我們可以理解爲map中存儲的數據類型是pairs型)

如果沒有關鍵字爲key的元素,則會往pairs裏插入一個關鍵字爲key的元素,並返回其值的引用如:

map<int,double>  pairs;

則 pairs[50] = 5; 會修改pairs中關鍵字爲50的元素,使其值變成5。

例一:

#include <iostream>

#include <map>

using namespace std;

ostream & operator <<( ostream & o,const pair<  int,double> & p)

{

 o << "(" << p.first  << "," << p.second << ")";

 return o;

}

int main()  {

 typedef map<int,double,less<int> > mmid;

 mmid pairs;

 cout << "1) " << pairs.count(15) << endl;

 pairs.insert(mmid::value_type(15,2.7));

 pairs.insert(make_pair(15,99.3));//make_pair生成pair對象

 cout << "2) " << pairs.count(15) << endl;

 pairs.insert(mmid::value_type(20,9.3));

  mmid::iterator i;

       cout << "3) ";

       for( i = pairs.begin(); i != pairs.end();i ++ )

      cout << * i  << ",";

 cout << endl;

 cout << "4) ";

 int n =  pairs[40];//如果沒有關鍵字爲40的元素,則插入一個

 for( i = pairs.begin(); i != pairs.end();i ++ )

  cout << * i  << ",";

 cout << endl;

 cout << "5) ";

 pairs[15] = 6.28; //把關鍵字爲15的元素值改成6.28

 for( i = pairs.begin(); i != pairs.end();i ++ )

  cout << * i  << ",";

            return 0;

}

例二:

#include <iostream>

#include "numeric"

#include "string"

#include "map"

using namespace std;

typedef map<int,string,less<int> > INT2STRING;

int main()

{

INT2STRING theMap;

INT2STRING::iterator theIterator;

string theString="";

int index;

theMap.insert(INT2STRING::value_type(0,"Zero"));

theMap.insert(INT2STRING::value_type(1,"One"));

theMap.insert(INT2STRING::value_type(2,"Two"));

theMap.insert(INT2STRING::value_type(3,"There"));

theMap.insert(INT2STRING::value_type(4,"Four"));

theMap.insert(INT2STRING::value_type(5,"Five"));

theMap.insert(INT2STRING::value_type(6,"Six"));

theMap.insert(INT2STRING::value_type(7,"Seven"));

theMap.insert(INT2STRING::value_type(8,"Eight"));

theMap.insert(INT2STRING::value_type(9,"Nine"));

for(;;)

   {

   cout<<"ENter \"q\" to quit,or enter a number:\n";

   cin>>theString;

   if(theString=="q")

    break;

   for(index=0;index<theString.length();index++){

   theIterator=theMap.find(theString[index]-'0');

   if(theIterator!=theMap.end())

    cout<<(*theIterator).second<<" ";

   else

    cout<<"[err]";

   }

   cout<<endl;

   }

return 1; 

}

 

發佈了208 篇原創文章 · 獲贊 31 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章