C++ STL 线性容器的用法

举报
兔老大 发表于 2021/04/23 23:08:37 2021/04/23
2.4k+ 0 0
【摘要】 vector vector 是顺序容器的一种,是可变长的动态数组,支持随机访问迭代器,所有stl算法都能对 vector 进行操作。 vector 容器在实现时,动态分配的存储空间一般都大于存放元素所需的空间。例如,哪怕容器中只有一个元素,也会分配 32 个元素的存储空间。这样做的好处是,在尾部添加一个新元素时不必重新分配空间,直接将新元素写入适当位置即可。在这种情况下,添...

vector

vector 是顺序容器的一种,是可变长的动态数组,支持随机访问迭代器,所有stl算法都能对 vector 进行操作。
vector 容器在实现时,动态分配的存储空间一般都大于存放元素所需的空间。例如,哪怕容器中只有一个元素,也会分配 32 个元素的存储空间。这样做的好处是,在尾部添加一个新元素时不必重新分配空间,直接将新元素写入适当位置即可。在这种情况下,添加新元素的时间也是常数。但是,多出来的空间用完再添加新元素,就不得不重新分配内存空间,把原有内容复制过去后再添加新的元素。

vector中常用的成员函数
成员函数 作 用
vector() 无参构造函数,将容器初始化为空
vector(int n) 将容器初始化为有 n 个元素
vector(int n, const T & val) 假定元素的类型是 T,此构造函数将容器初始化为有 n 个元素,每 个元素的值都是 val
vector(iterator first, iterator last) first 和 last 可以是其他容器的迭代器。一般来说,本构造函数初始化的结果就是将 vector 容器的内容变成与其他容器上的区间 [first, last) —致
void clear() 删除所有元素
bool empty() 判断容器是否为空
void pop_back() 删除容器末尾的元素
void push_back( const T & val) 将 val 添加到容器末尾
int size() 返回容器中元素的个数
T & front() 返回容器中第一个元素的引用
T & back() 返回容器中最后一个元素的引用
iterator insert(iterator i, const T & val) 将 val 插入迭代器 i 指向的位置,返回 i
iterator insert( iterator i, iterator first, iterator last) 将其他容器上的区间 [first, last) 中的元素插入迭代器 i 指向的位置
iterator erase(iterator i) 删除迭代器 i 指向的元素,返回值是被删元素后面的元素的迭代器
iterator erase(iterator first, iterator last) 删除容器中的区间 [first, last)
void swap( vector <T> & v) 将容器自身的内容和另一个同类型的容器 v 互换

      #include <iostream>
      #include <vector> //使用vector需要包含此头文件
      using namespace std;
      template <class T>
      void PrintVector(const vector <T> & v)
      {  //用于输出vector容器的全部元素的函数模板
      typename vector <T>::const_iterator i;
      //typename 用来说明 vector <T>::const_iterator 是一个类型,在 Visual Studio 中不写也可以
      for (i = v.begin(); i != v.end(); ++i)
      cout << *i << " ";
      cout << endl;
      }
      int main()
      {
      int a[5] = { 1, 2, 3, 4, 5 };
      vector <int> v(a, a + 5);  //将数组a的内容放入v
      cout << "1) " << v.end() - v.begin() << endl;  //两个随机迭代器可以相减,输出:1)5
      cout << "2)"; PrintVector(v);  //输出:2)1 2 3 4 5
       v.insert(v.begin() + 2, 13);  //在 begin()+2 位置插人 13
      cout << "3)"; PrintVector(v);  //输出:3)1 2 13 3 4 5
       v.erase(v.begin() + 2);  //删除位于 begin()+2 位置的元素
      cout << "4)"; PrintVector(v);  //输出:4)1 2 3 4 5
      vector<int> v2(4, 100);  //v2 有 4 个元素,都是 100
       v2.insert(v2.begin(), v.begin() + 1, v.begin() + 3);  //将v的一段插入v2开头
      cout << "5)v2:"; PrintVector(v2);  //输出:5)v2:2 3 100 100 100 100
       v.erase(v.begin() + 1, v.begin() + 3);  //删除 v 上的一个区间,即 [2,3)
      cout << "6)"; PrintVector(v);  //输出:6)1 4 5
      return 0;
      }
  
 

      #include <iostream>
      #include <vector>
      using namespace std;
      int main()
      {
      vector<vector<int> > v(3); //v有3个元素,每个元素都是vector<int> 容器
      for(int i = 0;i < v.size(); ++i)
      for(int j = 0; j < 4; ++j)
       v[i].push_back(j);
      for(int i = 0;i < v.size(); ++i) {
      for(int j = 0; j < v[i].size(); ++j)
      cout << v[i][j] << " ";
      cout << endl;
       }
      return 0;
      }
  
 

list

list 是顺序容器的一种。list 是一个双向链表。使用 list 需要包含头文件 list。双向链表的每个元素中都有一个指针指向后一个元素,也有一个指针指向前一个元素。

list 容器不支持根据下标随机存取元素。

list 的构造函数和许多成员函数的用法都与 vector 类似,此处不再列举。除了顺序容器都有的成员函数外,list 还独有如下函数

成员函数或成员函数模板 作  用
void push_front(const T & val) 将 val 插入链表最前面
void pop_front() 删除链表最前面的元素
void sort() 将链表从小到大排序
void remove (const T & val) 删除和 val 相等的元素
remove_if 删除符合某种条件的元素
void unique() 删除所有和前一个元素相等的元素
void merge(list <T> & x) 将链表 x 合并进来并清空 x。要求链表自身和 x 都是有序的
void splice(iterator i, list <T> & x, iterator first, iterator last) 在位置 i 前面插入链表 x 中的区间 [first, last),并在链表 x 中删除该区间。链表自身和链表 x 可以是同一个链表,只要 i 不在 [first, last) 中即可

STL 中的算法 sort 可以用来对 vector 和 deque 排序,它需要随机访问迭代器的支持。因为 list 不支持随机访问迭代器,所以不能用算法 sort 对 list 容器排序。因此,list 容器引入了 sort 成员函数以完成排序。


      #include <list> //使用 list 需要包含此头文件
      #include <iostream>
      #include <algorithm> //使用STL中的算法需要包含此头文件
      using namespace std;
      class A {
      private: int n;
      public:
       A(int n_) { n = n_; }
      friend bool operator < (const A & a1, const A & a2);
      friend bool operator == (const A & a1, const A & a2);
      friend ostream & operator << (ostream & o, const A & a);
      };
      bool operator < (const A & a1, const A & a2) {
      return a1.n < a2.n;
      }
      bool operator == (const A & a1, const A & a2) {
      return a1.n == a2.n;
      }
      ostream & operator << (ostream & o, const A & a) {
       o << a.n;
      return o;
      }
      template <class T>
      void Print(T first, T last)
      {
      for (; first != last; ++first)
      cout << *first << " ";
      cout << endl;
      }
      int main()
      {
       A a[5] = { 1, 3, 2, 4, 2 };
       A b[7] = { 10, 30, 20, 30, 30, 40, 40 };
      list<A> lst1(a, a + 5), lst2(b, b + 7);
       lst1.sort();
      cout << "1)"; Print(lst1.begin(), lst1.end());  //输出:1)1 2 2 3 4
       lst1.remove(2);  //删除所有和A(2)相等的元素
      cout << "2)"; Print(lst1.begin(), lst1.end());  //输出:2)1 3 4
       lst2.pop_front();  //删除第一个元素
      cout << "3)"; Print(lst2.begin(), lst2.end());  //输出:3)30 20 30 30 40 40
       lst2.unique();  //删除所有和前一个元素相等的元素
      cout << "4)"; Print(lst2.begin(), lst2.end());  //输出:4)30 20 30 40
       lst2.sort();
       lst1.merge(lst2);  //合并 lst2 到 lst1 并清空 lst2
      cout << "5)"; Print(lst1.begin(), lst1.end());  //输出:5)1 3 4 20 30 30 40
      cout << "6)"; Print(lst2.begin(), lst2.end());  //lst2是空的,输出:6)
       lst1.reverse();  //将 lst1 前后颠倒
      cout << "7)"; Print(lst1.begin(), lst1.end());  //输出 7)40 30 30 20 4 3 1
       lst2.insert(lst2.begin(), a + 1, a + 4);  //在 lst2 中插入 3,2,4 三个元素
      list <A>::iterator p1, p2, p3;
       p1 = find(lst1.begin(), lst1.end(), 30);
       p2 = find(lst2.begin(), lst2.end(), 2);
       p3 = find(lst2.begin(), lst2.end(), 4);
       lst1.splice(p1, lst2, p2, p3);  //将[p2, p3)插入p1之前,并从 lst2 中删除[p2,p3)
      cout << "8)"; Print(lst1.begin(), lst1.end());  //输出:8)40 2 30 30 20 4 3 1
      cout << "9)"; Print(lst2.begin(), lst2.end());  //输出:9)3 4
      return 0;
      }
  
 

stack 是容器适配器的一种。要使用 stack,必须包含头文件 <stack>。
stack就是“栈”。是一种后进先出的元素序列,访问、添加和删除都只能对栈顶的元素行。栈内的元素不能访问。
stack的定义如下:


      template < class T, class Cont == deque <T> >
      class stack{
       ...
      };
  
 

第二个参数表明,在默认情况下,stack 就是用 deque 实现的。当然,也可以指定用 vector 或 list 实现。

虽然 stack 使用顺序容器实现,但它不提供顺序容器具有的成员函数。除了 size、 empty 这两个所有容器都有的成员函数外,stack 还有以下三个成员函数
 

stack的成员函数
成员函数 功  能
void pop(); 弹出(即删除)栈顶元素
T & top(); 返回栈顶元素的引用。通过此函数可以读取栈顶元素的值,也可以修改栈顶元素
void push (const T & x); 将 x 压入栈顶

      #include <iostream>
      #include <stack> //使用stack需要包含此头文件
      using namespace std;
      int main()
      {
      int n, k;
      stack <int> stk;
      cin >> n >> k;  //将n转换为k进制数
      if (n == 0) {
      cout << 0;
      return 0;
       }
      while (n) {
       stk.push(n%k);
       n /= k;
       }
      while (!stk.empty()) {
      cout << stk.top();
       stk.pop();
       }
      return 0;
      }
  
 

queue

queue 就是“队列”。队列是先进先出的。队头的访问和删除操作只能在队头进行,添加操作只能在队尾进行。不能访问队列中间的元素。

queue 可以用 list 和 deque 实现,默认情况下用 deque 实现。
queue 的定义如下:


      template < class T, class Cont = deque<T> >
      class queue{
          ...
      };
  
 

queue 同样也有和 stack 类似的 push、pop、top 函数。区别在于,queue 的 push 发生在队尾,pop 和 top 发生在队头。

priority_queue

priority_queue 是“优先队列”。它和普通队列的区别在于,优先队列的队头元素总是最大的——即执行 pop 操作时,删除的总是最大的元素;执行 top 操作时,返回的是最大元素的引用。

priority_queue 可以用 vector 和 deque 实现,默认情况下用 vector 实现。

priority_queue 默认的元素比较器是 less <T>。也就是说,在默认情况下,要放入 priority_queue 的元素必须是能用“<”运算符进行比较的,而且 priority _queue 保证以下条件总是成立:对于队头的元素 x 和任意非队头的元素 y,表达式“x<y”必为 false。

priority_queue 定义如下:


      template < class T, class Container = vector <T>, class Compare = less<T> >
      class priority_queue{
          ...
      };
  
 

priority_queue 的第三个类型参数可以用来指定排序规则。

priority_queue 是使用“堆排序”技术实现的,其内部并非完全有序,但却能确保最大元素总在队头。因此,priority_queue 特别适用于“不停地在一堆元素中取走最大的元素”这种情况。

文章来源: fantianzuo.blog.csdn.net,作者:兔老大RabbitMQ,版权归原作者所有,如需转载,请联系作者。

原文链接:fantianzuo.blog.csdn.net/article/details/105996260

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。