天天看點

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

一、疊代器

list的疊代器不支援算術運算,也不支援關系運算符(<=,<,>=,>),他隻提供前置和後置的自增、自減以及相等和不相等運算。list的記憶體不連續。

vector和deque容器的疊代器是一種類型,vector能做的DEQUE也可以。

二、容器擴充卡

queue,priority_queue,stack.

預設的queue和stack實在deque基礎上實作,而PRIORITY_QUEUE則是在vector基礎上實作。

queue需要提供PUSH_FRONT函數,隻能由deque和list初始化。

stack可以由vector,deque,list初始化。

priority_queue需要提供随即通路功能,由vector和deque初始化。

在優先隊列中,優先級高的元素先出隊列。

标準庫預設使用元素類型的<操作符來确定它們之間的優先級關系。

優先隊列的第一種用法,也是最常用的用法:

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

priority_queue<int> qi;

通過<操作符可知在整數中元素大的優先級高。

故示例1中輸出結果為:9 6 5 3 2

第二種方法:

在示例1中,如果我們要把元素從小到大輸出怎麼辦呢?

這時我們可以傳入一個比較函數,使用functional.h函數對象作為比較函數。

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

priority_queue<int, vector<int>, greater<int> >qi2;

其中

第二個參數為容器類型。

第二個參數為比較函數。greater是内部函數,也可以less

故示例2中輸出結果為:2 3 5 6 9

第三種方法:

自定義優先級。

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

struct node

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

 {

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     friend bool operator< (node n1, node n2)

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     {

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

         return n1.priority < n2.priority;

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     }

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     int priority;

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     int value;

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

 };

在該結構中,value為值,priority為優先級。

通過自定義operator<操作符來比較元素中的優先級。

在示例3中輸出結果為:

優先級  值

9         5

8         2

6          1

2          3

1          4

但如果結構定義如下:

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

struct node

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

 {

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     friend bool operator> (node n1, node n2)

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     {

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

         return n1.priority > n2.priority;

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     }

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     int priority;

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     int value;

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

 };

則會編譯不過(G++編譯器)

因為标準庫預設使用元素類型的<操作符來确定它們之間的優先級關系。

而且自定義類型的<操作符與>操作符并無直接聯系,故會編譯不過。

//代碼清單

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

#include<iostream>

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

 #include<functional>

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

 #include<queue>

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

using namespace std;

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

 struct node

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

 {

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     friend bool operator< (node n1, node n2)

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     {

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

         return n1.priority < n2.priority;

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     }

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     int priority;

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     int value;

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

 };

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

 int main()

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

 {

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     const int len = 5;

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     int i;

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     int a[len] = {3,5,9,6,2};

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     //示例1

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     priority_queue<int> qi;

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     for(i = 0; i < len; i++)

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

         qi.push(a[i]);

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     for(i = 0; i < len; i++)

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     {

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

         cout<<qi.top()<<" ";

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

         qi.pop();

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     }

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     cout<<endl;

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     //示例2

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     priority_queue<int, vector<int>, greater<int> >qi2;

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     for(i = 0; i < len; i++)

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

         qi2.push(a[i]);

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     for(i = 0; i < len; i++)

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     {

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

         cout<<qi2.top()<<" ";

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

         qi2.pop();

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     }

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     cout<<endl;

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     //示例3

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     priority_queue<node> qn;

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     node b[len];

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     b[0].priority = 6; b[0].value = 1; 

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     b[1].priority = 9; b[1].value = 5; 

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     b[2].priority = 2; b[2].value = 3; 

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     b[3].priority = 8; b[3].value = 2; 

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     b[4].priority = 1; b[4].value = 4; 

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解
stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     for(i = 0; i < len; i++)

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

         qn.push(b[i]);

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     cout<<"優先級"<<'\t'<<"值"<<endl;

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     for(i = 0; i < len; i++)

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     {

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

         cout<<qn.top().priority<<'\t'<<qn.top().value<<endl;

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

         qn.pop();

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     }

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

     return 0;

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

 }

C++之函數擴充卡

C++定義了一些特殊的函數擴充卡(Function adapters),通過這些函數擴充卡我們可以将預先定義的仿函數和其他數值結合在一起或使用特殊情況。

上例子吧:

void testAdapter()

{

    std::set<int,std::greater<int> > intSet;

    std::deque<int> intDeque;

    for(int i=1;i<10;++i)

        intSet.insert(i);

    std::cout<<"Initialized Set:\n";

    copy(intSet.begin(),intSet.end(),

         std::ostream_iterator<int>(std::cout," "));

    transform(intSet.begin(),intSet.end(),

              back_inserter(intDeque),

             bind2nd(std::multiplies<int>(),10));  ///operation

    std::cout<<"\nDeque data:\n";

    copy(intDeque.begin(),intDeque.end(),

         std::ostream_iterator<int>(std::cout," "));

    replace_if(intDeque.begin(),intDeque.end(),

               bind2nd(std::equal_to<int>(),70),  ///operation

               0);

    std::cout<<"\nDeque data after replace:\n";

    copy(intDeque.begin(),intDeque.end(),

         std::ostream_iterator<int>(std::cout," "));

    intDeque.erase(remove_if(intDeque.begin(),intDeque.end(),

                             bind2nd(std::less<int>(),50)),

                   intDeque.end());

    std::cout<<"\nDeque data after erase:\n";

    copy(intDeque.begin(),intDeque.end(),

         std::ostream_iterator<int>(std::cout," "));

}

stl 容器擴充卡、疊代器擴充卡和函數擴充卡講解

函數擴充卡bind2nd的工作原理:

以    transform(intSet.begin(),intSet.end(),

              back_inserter(intDeque),

              bind2nd(std::multiplies<int>(),10));  ///operation

為例吧:

   transform()希望自己的第四個參數是一個能接納單一參數(即容器實際元素)的表達式,

   然後我們希望先将元素乘以10再傳給transform(),

   所有我們必須購置一個表達式,接受兩個參數,并以數值10作為第二個參數

   以此産生一個隻接受一個參數的表達式

   bind2nd會把表達式儲存起來,将第二個參數當内部數值儲存起來

   當算法以實際叢集元素為參數,調用bind2nd時,bind2nd将元素作為第一參數

   把原先儲存下來的數值作為第二個參數,調用保留下來的表達式,并傳回調用結果

   詳見《源源碼剖析》第8章

另外,某些仿函數可以用來調用叢集内每個元素的成員函數:

for_each(intDeque.begin(),intDeque.end(),

         mem_fun_ref(&Person::printInfo()))

仿函數mem_fun_ref将調用它所作用的每個元素的某個成員函數

當然,必須保證這些元素的類型是Person或者Person的派生類,

并且可以printInfo()函數

STL的stack擴充卡函數

c.push(const value_type&v) 将v壓入到棧中
c.pop() 移除棧頂元素
c.top() 傳回棧頂元素
c.empty() 棧空時傳回true
c.size() 傳回棧中的元素個數
== 和 < 判等運算符和按字典順序計算的小于運算符

STL的queue擴充卡函數

c.push(const value_type&v) 将v放到隊列尾部
c.pop() 從隊列前端移除元素
c.front() 傳回隊列前端元素
c.back() 傳回隊列尾部元素
c.empty() 隊列空時傳回true
c.size() 傳回隊列的元素個數
== 和 < 判等運算符和按字典順序計算的小于運算符

版權聲明:本文為CSDN部落客「weixin_34348174」的原創文章,遵循CC 4.0 BY-SA版權協定,轉載請附上原文出處連結及本聲明。

原文連結:https://blog.csdn.net/weixin_34348174/article/details/91686943