c++中deque和list的基础知识

STL中deque和vector的构造函数,assign基本相同,重点介绍deque的特性,deque和vector的主要区别如下:

  • deque是双端队列的数据结构,可以在队首和队尾高效的添加和删除元素,这是相对于vector的优势。

  • deque内部采用分段连续的内存空间来存储元素,在插入元素的时候随时都可以重新增加一段新的空间并链接起来,因此虽然提供了随机访问操作,但访问速度和vector相比要慢。

  • deque并没有data函数,因为deque的元素并没有放在数组中。

  • deque不提供capacity和reserve操作。

  • deque内部的插入和删除元素要比list慢。
  • 由于deque在性能上并不是最高效的,有时候对deque元素进行排序,更高效的做法是,将deque的元素移到vector再进行排序,然后在移到回来。

  • deque为了实现整体连续的假象,导致其实现起来比较繁琐,尽量少使用它。

deque的实现原理:http://blog.csdn.net/baidu_28312631/article/details/48000123,该文叙述很清楚,可以参考。
deque的源码剖析:http://blog.csdn.net/terence1212/article/details/52326945,该文可以参考

  • deque
  • deque的初始化
    • deque的初始化,见如下代码。deque的初始化和vector完全相同
    • deque的assign函数,同样有三种方式,初始化列表,赋值若干个相同的值,任意一个序列容器的范围

      deque<int> v2;        // deque with 0 element
      deque<int> v3(20);   // deque with 20 elements whose value is 0
      deque<int> v4(20, 5);// deque with 20 elements whose value is 5
      deque<int> v5{ 20 }; // deque with 1 element whose value is 20
      deque<int> v6(v4);   // copy construct function
      deque<int> v7(v4.begin(), v4.end());//construct function
      deque<int> v8({ 1,2,3,4,5 });// construct a deque with initialize list
      deque<int> v9{ 1,2,3,4,5 };// construct a deque with initialize list
      deque<int> v10 = { 1,2,3,4,5 };// assignment construct function

  • deque的assign
    1. deque的assign有三种形式,assign

      deque<int> mydeque;
      deque<int> temp{ 1,2,4,5,6 };
      mydeque.assign(temp.begin(), temp.end());   //接受序列容器的范围
      mydeque.assign(3, 5);      //变为3个值,每个值都是5
      mydeque.assign({ 1,2,3,4,5,6 });    //赋值一个初始化列表

  • deque的添加元素
    1. deque中添加元素,除了push_back和emplace_back之外,由于是双端队列,因此可以在队首添加元素,deque中还有push_front和emplace_front等。
    deque<int> myDeque;
    myDeque.push_back(1);
    myDeque.push_front(2);
    myDeque.emplace_back(3);
    myDeque.emplace_front(6);
    copy(myDeque.begin(), myDeque.end(), ostream_iterator<double>(cout, " "));

  • list
  • list特点
    • list和deque的元素在内存的组织形式不同,以链表的形式保存

    • list和deque相同,也可以在尾部和头部加入元素,因此也支持push_back和push_front以及emplace_front和emplace_back

    • list可以高效的在内部插入元素而不需要移动元素,list是双向链表

    • list的insert函数和emplace与vector,deque的方式完全相同

  • list的特有的一些函数
    1. list独有的成员函数remove()可以移除和参数匹配的元素。例如如下代码:
    std::list<int> numbers{2,5,2,3,6,7,8,2,9};
    numbers.remove(2);// 删除元素值为2的元素
    copy(numbers.begin(), numbers.end(), ostream_iterator<int>(cout, " "));
    1. 成员函数remove_if()期望传入一个一元断言作为参数,一元断言接受一个和元素同类型的参数或引用,返回一个布尔值。断言返回true的元素都会被移除。断言可以是一个函数,也可以是一个lambda表达式。
    std::list<int> numbers{2,5,2,3,6,7,8,2,9};
    auto f = [](const int& i)->bool {return i % 2 == 0; };
    numbers.remove_if(f);//删除所有偶数
    copy(numbers.begin(), numbers.end(), ostream_iterator<int>(cout, " "));
    1. 成员函数unique,可以移除连续重复的元素 ,只留下一个,但是该函数不能删除list中不连续的重复的元素。因此,如果需要删除重复元素,则需要排序,排序之后再删除重复元素。
      unique()函数重载形式两种,一种没有参数,有参数的版本接受一个二元断言。断言返回true的元素被认为是相等的。
    //没有经过sort,直接unique
    numbers.assign({ 2,5,2,4,7,7,7,8});
    numbers.unique();// {2,5,2,4,7,8} 未删除重复但不连续的元素
    copy(numbers.begin(), numbers.end(), ostream_iterator<int>(cout, " "));
    
    // sort 之后unique
    numbers.assign({ 2,5,2,4,7,7,7,8 });
    numbers.sort();// 2,2,4,5,7,7,7,8
    numbers.unique();// 2,4,5,7,8
    copy(numbers.begin(), numbers.end(), ostream_iterator<int>(cout, " "));
    
    
    //unique 的重载形式
    numbers.assign({ 2,5,2,4,7,7,7,8 });
    numbers.sort();// 2 2 4 5 7 7 7 8
    auto f1 = [](const int& a, const int& b)->bool {return a % 2 == b % 2; };
    numbers.unique(f1);// 2 5 8
    copy(numbers.begin(), numbers.end(), ostream_iterator<int>(cout, " "));
    1. sort()函数有两个版本:无参数的sort()将所有元素升序排列,有参数版本的sort()函数接受一个函数对象或者lambda函数,用来表明排序依据。
    // 使用断言
    numbers.assign({ 2,5,2,4,7,7,7,8 });
    numbers.sort(greater<>());// 2 2 4 5 7 7 7 8
    // 使用lambda函数
    numbers.assign({ 2,5,2,4,7,7,7,8 });
    auto f3 = [](const int&a, const int& b)->bool{return a>b;};
    numbers.sort(f3);// 2 2 4 5 7 7 7 8

    上述例子中使用了functional中的模板greater<T>断言,这里可以使用gerater<int>的形式,也可以使用greater<>的形式,后者是简洁版本的函数对象,可以接受任何类型的参数,使用完美转发(perfect forwarding)可以避免参数拷贝,被比较的参数会被移动而不是复制到函数中。

    猜你喜欢

    转载自blog.csdn.net/t46414704152abc/article/details/79322896