zoukankan      html  css  js  c++  java
  • 《STL源码剖析》--- deque1

    参考文献:

      《STL源码剖析》

    ...........................................................................................................................................................

    一. deque 概述

           vector是单向开口的连续性线性空间,deque则是一种双开的连续性空间,即两边都可以进行插入和删除操作(vector也可进行头部的删除、插入操作,但效率很差,不被接受)。

      下图为deque示意图:

     

            deque和vector最大差异,一是deque允许在常数时间内对头部元素进行插入和移除操作,二在于deque没有所谓的容量的概念,因为它是动态地以分段连续空间组合而成,随时可以增加一段新的空间并链接起来。
            虽然deque也提供Random Access Iterator,但它的迭代器并不是普通指针,其复杂度远高于vector,所以除非必要尽可 能使用vector。为了deque排序效率最高,deuqe会先将所有的元素复制到vector中,进行排序后,再复制回deque

    二. deque 的中控器

            deque是一段一段连续的空间构成,一旦在deque前端或尾端增加新空间,便配置一段定量连续空间,串联在头端和尾端。deque的最大任务就是将这些定量的空间,维护成连续的假象,并提供随机存储的接口,避开了“重新配置、复制、释放”的轮回,代价即是复杂的迭代器架构。
            既然是分段连续的线性空间,就必须要有中央控制,而为了维持连续的假象,数据结构的设计及迭代器前进后退等操作都比较麻烦,所以deque的实现代码分量远比vector或list都多得多。
            deque采用一块map(不是STL的map容器)作为主控,这里的map是一块连续空间,其中每个元素都是指针,指向另一段连续线性空间,称为缓冲区。缓冲区才是deque的存储空间主体。

     1 template <class T,class Alloc=alloc,size_t BufSiz=0>
     2 class deque{
     3 public:
     4     typedef T value_type;
     5     typedef value_type* pointer;
     6     ...
     7 protected:
     8     typedef pointer* map_pointer;
     9 protected:
    10     map_pointer map; //指向map,map是连续空间,其内的每个元素都是一个指针,指向一块缓冲区
    11     size_type map_size; //map可容纳多少指针
    12     ...
    13 };

    从上面可以看出,map其实是一个T**,也就是说它是一个指针,所指向另一个指针,指向型别为T的一块空间。具体如下图:

    三. deque 使用实例(理解)

     1 #include <deque>  
     2 #include <iostream>  
     3 #include <algorithm>  
     4 #include <stdexcept>  
     5 using namespace std;  
     6   
     7 void print(int num)  
     8 {  
     9 
    10     cout << num << " ";  
    11 }  
    12   
    13 int main()  
    14 {  
    15     //1. 初始化  
    16     deque<int> v;  
    17     deque<int>::iterator iv;  
    18   
    19     v.assign(10, 2);//将10个值为2的元素赋到deque中  
    20     cout << v.size() << endl; //返回deque实际含有的元素数量  
    21     cout << endl;  
    22   
    23     //2. 添加  
    24     v.push_front(666);  
    25     for (int i = 0; i < 10; i++)  
    26         v.push_back(i);  
    27     for_each(v.begin(), v.end(), print);//需要#include <algorithm>  
    28     cout << endl;  
    29     cout << v.size() << endl;  
    30     cout << endl;  
    31   
    32 
    33 
    34     //3. 插入及遍历、逆遍历  
    35     v.insert(v.begin() + 3, 99);  
    36     v.insert(v.end() - 3, 99);  
    37     for_each(v.begin(), v.end(), print);  
    38     cout << endl;  
    39     for_each(v.rbegin(), v.rend(), print);//在逆序迭代器上做++运算将指向容器中的前一个元素  
    40     cout << endl;  
    41   
    42     //一般遍历写法  
    43     for(iv = v.begin(); iv != v.end(); ++iv)  
    44         cout << *iv << " ";  
    45     cout << endl;  
    46     cout << endl;  
    47   
    48     //4. 删除  
    49     v.erase(v.begin() + 3);  
    50 
    51    for_each(v.begin(), v.end(), print);  
    52     cout << endl;  
    53     v.insert(v.begin() + 3, 99);//还原  
    54   
    55     v.erase(v.begin(), v.begin() + 3); //注意删除了3个元素而不是4个  
    56     for_each(v.begin(), v.end(), print);  
    57     cout << endl;  
    58   
    59     v.pop_front();  
    60     v.pop_back();  
    61     for_each(v.begin(), v.end(), print);  
    62     cout << endl;  
    63     cout << endl;  
    64   
    65 
    66 
    67     //5. 查询  
    68     cout << v.front() << endl;  
    69     cout << v.back() << endl;  
    70   
    71     //危险的做法,但一般我们就像访问数组那样操作就行  
    72     //for (int i = 15; i < 25; i++)  
    73         //cout << "Element " << i << " is " << v[i] << endl;  
    74     //安全的做法  
    75     int i;  
    76     try  
    77     {  
    78         for (i = 15; i < 25; i++)  
    79             cout << "Element " << i << " is " << v.at(i) << endl;  
    80     }  
    81     catch (out_of_range err)//#include <stdexcept>  
    82     {  
    83         cout << "out_of_range at " << i << endl;  
    84     }  
    85     cout << endl;  
    86   
    87     //6. 清空  
    88     v.clear();  
    89     cout << v.size() << endl;//0  
    90     for_each(v.begin(), v.end(), print); //已经clear,v.begin()==v.end(),不会有任何结果。  
    91   
    92     return 0;  
    93 }  
  • 相关阅读:
    poj 2763 Housewife Wind
    hdu 3966 Aragorn's Story
    poj 1655 Balancing Act 求树的重心
    有上下界的网络流问题
    URAL 1277 Cops and Thieves 最小割 无向图点带权点连通度
    ZOJ 2532 Internship 网络流求关键边
    ZOJ 2760 How Many Shortest Path 最大流+floyd求最短路
    SGU 438 The Glorious Karlutka River =) 拆点+动态流+最大流
    怎么样仿写已知网址的网页?
    5-10 公路村村通 (30分)
  • 原文地址:https://www.cnblogs.com/mysky007/p/11280025.html
Copyright © 2011-2022 走看看