ACM程序设计(第2版)
上QQ阅读APP看书,第一时间看更新

2.8 deque双端队列容器

deque双端队列容器与vector一样,采用线性表顺序存储结构。但与vector唯一不同的是,deque采用分块的线性存储结构来存储数据,每块的大小一般为512字节,称为一个deque块,所有的deque块使用一个Map块进行管理,每个Map数据项记录各个deque块的首地址。这样一来,deque块在头部和尾部都可插入和删除元素,而不需移动其他元素(使用push_back()方法在尾部插入元素,会扩张队列;而使用push_front()方法在首部插入元素和使用insert()方法在中间插入元素,只是将原位置上的元素值覆盖,不会增加新元素)。一般来说,当考虑到容器元素的内存分配策略和操作的性能时,deque相对于vector更有优势。双端队列容器结构示意图如图2-6所示。

图2-6 双端队列容器结构示意图

使用deque需要声明头文件包含“#include <deque>”,文件deque在C:\Program Files\Microsoft Visual Studio\VC98\Include文件夹中。

2.8.1 创建deque对象

创建deque对象的方法通常有三种。

(1)创建没有任何元素的deque对象,如:

        deque<int> d;
        deque<float> dd;

(2)创建具有n个元素的deque对象,如:

        deque<int> d(10); //创建具有10个整型元素的deque对象d

(3)创建具有n个元素的deque对象,并赋初值,如:

        deque<int> d(10,8.5); //创建具有10个整型元素的deque对象d,每个元素值为8.5

2.8.2 插入元素

(1)使用push_back()方法从尾部插入元素,会不断扩张队列。

        #include <deque>
        #include <iostream>
        using namespace std;

       int main(int argc, char * argv[])
        {
          //定义deque对象,元素类型是整型
          deque<int> d;
          //从尾部连续插入三个元素
          d.push_back(1);
          d.push_back(2);

        d.push_back(3);
        //以数组方式输出元素
        cout<<d[0]<<" "<<d[1]<<" "<<d[2]<<endl;
        return 0;
      }

运行结果:

      1 2 3

(2)从头部插入元素,不会增加新元素,只将原有的元素覆盖。

      #include <deque>
      #include <iostream>
      using namespace std;

     int main(int argc, char * argv[])
      {
        //定义deque对象,元素类型是整型
        deque<int> d;
        //从尾部连续插入三个元素
        d.push_back(1);
        d.push_back(2);
        d.push_back(3);
        //从头部插入元素,不会增加新元素,只将原有的元素覆盖
        d.push_front(10);
        d.push_front(20);
        //以数组方式输出元素
        cout<<d[0]<<" "<<d[1]<<" "<<d[2]<<endl;
        return 0;
      }

运行结果:

      20 10 1

(3)从中间插入元素,不会增加新元素,只将原有的元素覆盖。

      #include <deque>
      #include <iostream>
      using namespace std;

     int main(int argc, char * argv[])
      {
        //定义deque对象,元素类型是整型
        deque<int> d;
        //从尾部连续插入三个元素
        d.push_back(1);
        d.push_back(2);
        d.push_back(3);
        //中间插入元素,不会增加新元素,只将原有的元素覆盖
        d.insert(d.begin()+1,88);
        //以数组方式输出元素

        cout<<d[0]<<" "<<d[1]<<" "<<d[2]<<endl;
        return 0;
      }

运行结果:

        1 88 2

2.8.3 前向遍历

(1)以数组方式遍历。

        #include <deque>
        #include <iostream>
        using namespace std;

       int main(int argc, char * argv[])
        {
          //定义deque对象,元素类型是整型
          deque<int> d;
          //从尾部连续插入三个元素
          d.push_back(1);
          d.push_back(2);
          d.push_back(3);
          //以数组方式输出元素
          int i;
          for(i=0; i<d.size(); i++)
          {
              cout<<d[i]<<" ";
          }
          //回车换行
          cout<<endl;
          return 0;
        }

运行结果:

        1 2 3

(2)以前向迭代器的方式遍历。

        #include <deque>
        #include <iostream>
        using namespace std;

       int main(int argc, char * argv[])
        {
          //定义deque对象,元素类型是整型
          deque<int> d;
          //从尾部连续插入三个元素
          d.push_back(1);
          d.push_back(2);
          d.push_back(3);

            //以前向迭代器的方式遍历
            deque<int>::iterator it;
            for(it=d.begin(); it! =d.end(); it++)
            {
                cout<<*it<<" ";
            }
            //回车换行
            cout<<endl;
            return 0;
          }

运行结果:

        1 2 3

2.8.4 反向遍历

采用反向迭代器对双端队列容器进行反向遍历。

        #include <deque>
        #include <iostream>
        using namespace std;

       int main(int argc, char * argv[])
        {
          //定义deque对象,元素类型是整型
          deque<int> d;
          //从尾部连续插入三个元素
          d.push_back(1);
          d.push_back(2);
          d.push_back(3);
          //以反向迭代器的方式遍历
          deque<int>::reverse_iterator rit;
          for(rit=d.rbegin(); rit! =d.rend(); rit++)
          {
              cout<<*rit<<" ";
          }
          //回车换行
          cout<<endl;
          return 0;
        }

运行结果:

        3 2 1

2.8.5 删除元素

可以从双端队列容器的首部、尾部、中部删除元素,并可以清空双端队列容器。下面分别举例说明这4种删除元素的操作方法。

(1)采用pop_front()方法从头部删除元素。

      #include <deque>
      #include <iostream>
      using namespace std;

     int main(int argc, char * argv[])
      {
        //定义deque对象,元素类型是整型
        deque<int> d;
        //从尾部连续插入五个元素
        d.push_back(1);
        d.push_back(2);
        d.push_back(3);
        d.push_back(4);
        d.push_back(5);
        //从头部删除元素
        d.pop_front();
        d.pop_front();
        //以前向迭代器的方式遍历
        deque<int>::iterator it;
        for(it=d.begin(); it! =d.end(); it++)
        {
            cout<<*it<<" ";
        }
        //回车换行
        cout<<endl;
        return 0;
      }

运行结果:

      3 4 5

(2)采用pop_back()方法从尾部删除元素。

      #include <deque>
      #include <iostream>
      using namespace std;

     int main(int argc, char * argv[])
      {
        //定义deque对象,元素类型是整型
        deque<int> d;
        //从尾部连续插入五个元素
        d.push_back(1);
        d.push_back(2);
        d.push_back(3);
        d.push_back(4);
        d.push_back(5);
        //从尾部删除元素
        d.pop_back();

        //以前向迭代器的方式遍历
        deque<int>::iterator it;
        for(it=d.begin(); it! =d.end(); it++)
        {
            cout<<*it<<" ";
        }
        //回车换行
        cout<<endl;
        return 0;
      }

运行结果:

      1 2 3 4

(3)使用erase()方法从中间删除元素,其参数是迭代器位置。

      #include <deque>
      #include <iostream>
      using namespace std;

     int main(int argc, char * argv[])
      {
        //定义deque对象,元素类型是整型
        deque<int> d;
        //从尾部连续插入五个元素
        d.push_back(1);
        d.push_back(2);
        d.push_back(3);
        d.push_back(4);
        d.push_back(5);
        //从中间删除元素,erase的参数是迭代器位置
        d.erase(d.begin()+1);
        //以前向迭代器的方式遍历
        deque<int>::iterator it;
        for(it=d.begin(); it! =d.end(); it++)
        {
            cout<<*it<<" ";
        }
        //回车换行
        cout<<endl;
        return 0;
      }

运行结果:

      1 3 4 5

(4)使用clear()方法清空deque对象。

      #include <deque>
      #include <iostream>
      using namespace std;

        int main(int argc, char * argv[])
        {
          //定义deque对象,元素类型是整型
          deque<int> d;
          //从尾部连续插入五个元素
          d.push_back(1);
          d.push_back(2);
          d.push_back(3);
          d.push_back(4);
          d.push_back(5);
          //清空元素
          d.clear();
          //输出元素的个数
          cout<<d.size()<<endl;
          return 0;
        }

运行结果:

        0