1. 程式人生 > >C++學習:STL-介面卡

C++學習:STL-介面卡

一、介面卡分類二、容器介面卡三、迭代器介面卡四、演算法介面卡介面卡是一種設計模式。一、介面卡分類 容器介面卡:  stack                   預設基於deque容器實現  queue                  預設基於deque容器實現  priority_queue     預設基於vector容器實現迭代器介面卡  流迭代器  反向迭代器  插入迭代器演算法介面卡(函式介面卡)  繫結器  否定器  成員函式介面卡介面卡並不是第一類容器,因為它們並沒有提供與元素的儲存形式有關的真正資料結構實現,並且介面卡不支援迭代器。介面卡的優點是:能夠使程式設計師選擇一種合適的底層資料結構。這三個介面卡類都提供了成員函式push和pop,能夠在每個介面卡資料結構中正確地插入和刪除元素。二、容器介面卡  
沒有full的方法,是因為可以無限放資料。                  stack       queue      priority_queuefront             0              1                 0                                 //返回佇列中的第一個元素top               1               0                1 empty           1               1                1 size              1               1                1 push             1               1                1pop              1               1                 1 emplace        1               1                1swap            1               1                1queue的使用 
先進先出  #include <iostream>#include <queue>using std::cout;using std::endl;using std::queue;int main(void){        queue<int> queInt;        for(int idx = 0; idx < 10; ++idx){                queInt.push(idx);                                                 //元素入隊                cout << queInt.back() << "已經入隊" << endl;        }        cout << queInt.size() << "個元素已經入隊" << endl;    //當前佇列中有多少元素        while(!queInt.empty()){                                               //不為空                cout << queInt.front() << "出隊" << endl;             //返回佇列中的第一個元素                queInt.pop();                                                       //出隊        }        cout << queInt.size() << endl;        return 0;}priority_queue的使用  
優先順序佇列。satck和queue不會根據優先順序排序。優先順序佇列會排序。預設情況下采用"<"進行排序。採用堆排序進行調整。堆頂元素優先順序最高。所以priority_queue底層採用vector實現,因為二叉樹容易使用陣列實現。例1:預設情況下使用"<"進行排序。#include <iostream>#include <queue>#include <utility>#include <vector>using std::cout;using std::endl;using std::priority_queue;using std::pair;using std::vector;int main(void){        int arr[10] = {0, 1, 3, 2, 5, 6, 9, 8, 7, 4};        priority_queue<int> pqueInt;                                                 //建立優先順序佇列        for(int idx = 0; idx != 10; ++idx){                pqueInt.push(arr[idx]);                                                  //入隊。入隊的時候,就會比較,然後按照優先順序進行插入。                cout << pqueInt.top() << "是優先級別最高的" << endl; //打印出當前優先順序最高的元素。優先順序佇列採用堆排序進行元素的調                                                                                                     整。預設情況下,比較函式是"<"符號。堆頂的元素要與新進來的元素                                                                                                     比較,如果為true(堆頂<新元素),則將新元素放到堆頂,然後調整堆。                                                                                                   如果為false,則放到最後。如1進來時,0<1,滿足條件,則調整堆,1成為堆                                                                                                       頂。所以採用"<",數字越大優先順序越高。        }        while(!pqueInt.empty()){                cout << pqueInt.top() << "出隊" << endl;                       //獲取隊首元素(優先順序最高的元素)                pqueInt.pop();                                                              //出隊:9 8 7 6 5 4 3 2 1 0        }        return 0;}例2:自定義型別,過載比較函式#include <iostream>#include <queue>#include <utility>#include <vector>using std::cout;using std::endl;using std::priority_queue;using std::pair;using std::vector;struct MyCompare{        bool operator()(const pair<int, bool> & lhs,const pair<int, bool> & rhs){              //定義一個類,過載函式呼叫運算子                 return lhs.first > rhs.first;        }};int main(void){        priority_queue<pair<int, bool>,vector<pair<int, bool> >,MyCompare>  quePair;    //建立優先順序佇列,儲存的是pair.          quePair.push(std::make_pair(5, true));                                      //make_pair的返回值是pair。將5和true拼成一個pair,並返回         quePair.push(std::make_pair(3, false));        quePair.push(std::make_pair(7, true));        while(!quePair.empty()){                const pair<int, bool> & elem = quePair.top();                   //elem是pair型別。pop的返回值是const的引用。                 cout << elem.first << "-->" << elem.second << endl;                quePair.pop();                                                                 //3-->0 5-->1 7-->1         }        cout << endl;        return 0;}三、迭代器介面卡  反向迭代器的使用反向迭代器的開始位置在最後面,最後位置在最前面。例:#include <iostream>#include <vector>#include <iterator>using std::cout;using std::endl;using std::vector;using std::ostream_iterator;int main(void){        vector<int> vecInt = {1, 2, 3, 4, 5};        ostream_iterator<int> osi(cout, " ");                         //定義輸出流迭代器        vector<int>::reverse_iterator rit = vecInt.rbegin();     //定義反向迭代器。        copy(rit, vecInt.rend(), osi);                                    //5 4 3 2 1 。copy演算法,將rit到vecInt.end()的資料放到osi開始的容器中。                        cout << endl;                          return 0;}插入迭代器的使用  插入迭代器分為:頭插法迭代器、尾插法迭代器、中間插入迭代器。例: #include <iostream>#include <iterator>#include <vector>#include <list>using std::cout;using std::endl;using std::vector;using std::list;template <typename T>void printElements(T c){        typename T::iterator it;        for(it = c.begin(); it != c.end(); ++it){                cout << *it << " ";        }        cout << endl;}int main(){        vector<int> vecSrc = {1, 2, 3};        list<int> listDest;        copy(vecSrc.begin(), vecSrc.end(),std::back_insert_iterator<list<int> >(listDest));                     //尾插法         printElements(listDest);                                                                                                         //1 2 3         copy(vecSrc.begin(), vecSrc.end(),std::front_insert_iterator<list<int> >(listDest));                     //頭插法         printElements(listDest);                                                                                                         // 3 2 1 1 2 3          copy(vecSrc.begin(), vecSrc.end(),std::insert_iterator<list<int> >(listDest++listDest.begin())); //指定一個具體的位置。在第二個位置        printElements(listDest);                                                                                                         //3 1 2 3 2 1 1 2 3         return 0;}
四、函式介面卡  
繫結器     band1st          //已過時band2nd         //已過時band              //上面兩個在c++11已經過時。由band代替。std::band的返回值就是一個函式物件。繫結的引數的個數不受限制;對於不事先繫結的引數,需要傳std::placeholders進去,從_1開始,依次遞增   例1:對自由函式進行繫結#include <iostream>#include <functional>                                               //band函式的標頭檔案 using std::cout;using std::endl;int func(int x, int y){        return x + y;}int main(void){        using namespace std::placeholders;                    //這樣下面就不用寫:std::placeholders::_1了。        auto f = std::bind(func, 10);                               //錯誤。要寫上佔位符。   cout << f(20) << endl;        auto f1 = std::bind(func, 10, _1);                       //func表示繫結到函式func。_1是佔位符。佔位符有兩層含義。第一層含義是,本身                                                                                  的位置表示在函式中形參的位置:這裡_1在(func,10,_1)中是第2個引數,所以佔著int                                                                                  func(int x,int y); 的第二個引數的位置。而10就會傳給x。第二層含義是,_1表示第一                                                                               個實參,所以下面f1(20)的20會傳給_1.綜上,當呼叫f1(20)時,會執行func(10,20)函式。         cout << f1(20) << endl;                                     //f1是一個函式物件。        return 0;}例2:對成員函式也可以繫結#include <iostream>#include <functional>              using std::cout;using std::endl;int func(int x, int y){        return x + y;}struct A{        A(){                cout << "A()" << endl;        }        A(const A & rhs){                                         //拷貝建構函式                cout << "A(const A&)" << endl;        }        int func(int x, int y){                cout << "A::func(int,int)" << endl;                cout << " x = " << x << endl;                cout << " y = " << y << endl;                return x + y;        }};int main(void){        using namespace std::placeholders;        A a;        auto f2 = std::bind(&A::func, a, _2, _1);         //bind的形參的繫結以值傳遞的形式進行的。繫結到類的成員函式func,注意寫法。                                                                                  第二個引數把物件傳過去。後面_1和_2才是兩個引數。//bind的形參的繫結以值傳遞的形式進行的。a會以值傳遞的形式繫結到func,所以要  先根據a,執行拷貝建構函式,建立一個物件。所以這裡可以使用&a,這樣就不會再創    新的物件了。        cout << f2(1, 2) << endl;                               //會執行成員函式。func(2,1) 。形參的第一個位置是第二個實參。形參的第二個位置是第一個實參。        return 0;}例3:#include <iostream>#include <functional>              using std::cout;using std::endl;void f(int n1, int n2, int n3, const int & n4, int n5){        cout << "(" << n1<< "," << n2<< "," << n3<< "," << n4<< "," << n5<< ")" << endl;}int main(void){        using namespace std::placeholders;        int n = 7;        auto f1 = std::bind(f, _2, _1, 42, std::cref(n), n);   //繫結函式f。第一個形參是第二個實參,第二個形參是第一個實參。第三個形參是                                                                                 42,第四個形參是n的引用,cref表示const reference。第五個引數將n傳過去。        n = 10;        f1(1, 2, 1001, 1002, 1003);                                 //呼叫f1之後相當於執行f( 2, 1, 42, 10, 7),第二個實參傳個第一個形參,為2;第1個實參                                                                                傳個第二個形參,為1;第三個形參傳42,第四個形參是n的引用,n變成了10,所以是10.                                                                                  第五個引數繫結的是當時的n的值7.                                                                                //實參呼叫時,可以傳遞多餘的引數,但是無效。這裡的1001,1002,1003都沒用。         return 0;}例4:繫結資料成員的值#include <iostream>#include <functional>        using std::cout;using std::endl;struct Foo{        int data = 10;                                                       //直接初始化,這是C++11新特性。不建議這麼寫。};int main(void){        using namespace std::placeholders;        Foo foo;        foo.data = 12;        auto f3 = std::bind(&Foo::data, _1);                      //繫結資料成員。        cout << f3(foo) << endl;                                      //12。傳的是物件。        return 0;}成員函式介面卡  mem_fun()          //已過時mem_fun_ref()    //已過時         mem_fn()            //上面兩個在c++11已經過時。