C++(二)— STL容器的基本用法

C++(二)— STL容器的基本用法

1、vector基本操作

  关于vector简单的讲就是一个动态增长的数组,里面有一个指针指向一片连续的内存空间,当空间装不下的时候会自动申请一片更大的空间(空间配置器)将原来的数据拷贝到新的空间,然后就会释放旧的空间。当删除的时候空间并不会被释放只是清空了里面的数据。

  • 对象初始化,使用 v1 中的数据:vector<int> vec(v1.begin(), v1.begin()+3);
  • 末尾添加元素: vec.push_back();
  • 末尾删除元素: vec.pop_back();
  • 任意位置插入元素: vec.insert();
  • 任意位置删除元素: vec.erase();
  • 交换两个向量的元素: vec.swap();
  • 清空向量元素: vec.clear();
#include<vector> //包含头文件

vector<int> vec_one;  //最简单vector实例定义

int nLen = ;
vector<int> vec_fir(nLen); //分配nLen个空间,并且每个空间初始化为0(默认值) int nData1 = vec_fir.front(); //查询vector中第一个元素
int nData2 = vec_fir.back(); //查询vector中最后一个个元素
int nData3 = vec_fir.at(); //查询vector中索引为8(即第9个)元素
int nData4 = vec_fir[]; //同上,operator[]运算符重载 vec_fir.assign(,); //重新赋值vec_fir实例中数据为10个2
vec_fir.assign(vec_sed.begin(),vec_sed.end()); //重新赋值vec_fir为vec_sed vec_fir.push_back() //vector尾部添加一个10数据
vec_fir.pop_back() //删除vector尾部一个数据 vec_fir.erase(vec_fir.begin()); //删除vec_fir第一个数据(索引删除),指定位置删除,返回下一个数据的位置 vec_fir.erase(vec_fir.begin(),vec_fir.begin()+); //删除vec_fir第一个到第五个间断数据,返回下一个数据的位置 vec_fir.insert(vec_fir.begin(),); //开始位置插入一个10086数据 vec_fir.insert(vec_fir.begin(),,); //开始位置插入10个初始化为99的数据集 vec_fir.insert(vec_fir.begin(),vec_sed.begin(), vec_sed.begin()+); //将vec_sed开始的5个数插入在vec_fir开头

vec_fir.size(); //求解vector数据个数
//重新定义空间大小为100个空间,空间增加了则新增空间初始化为0,缩小了就仅保留前100个数据
vec_fir.resize();
vec_fir.clear(); // 清空vector
vec_fir.swap(vec_sed); //交换两个vector中所有数据

(1)vector容器实现迭代器,元素遍历

  • 开始指针:vec.begin();
  • 末尾指针:vec.end(); //指向最后一个元素的下一个位置
    //正向迭代器,输出:1 3 5 7 9
vector<int>::iterator it;
for (it = vec.begin(); it != vec.end(); it++)
cout << *it << endl; //反向迭代器,输出:9 7 5 3 1
vector<int>::reverse_iterator rit;
for (rit = vec.rbegin(); rit != vec.rend(); rit++)
cout << *rit << endl; //常规的循环输出,输出:1 3 5 7 9
for (int i = ; i < vec.size(); ++i)
{
cout << vec[i] << endl;
}

(2)几种重要的操作

头文件要包含:#include<algorithm>

(1)sort(a.begin(),a.end()); //对a中的从a.begin()(包括它)到a.end()(不包括它)的元素进行从小到大排列 
(2)reverse(a.begin(),a.end()); //对a中的从a.begin()(包括它)到a.end()(不包括它)的元素倒置,但不排列,如a中元素为1,3,2,4,倒置后为4,2,3,1 
(3)copy(a.begin(),a.end(),b.begin()+1); //把a中的从a.begin()(包括它)到a.end()(不包括它)的元素复制到b中,从b.begin()+1的位置(包括它)开始复制,覆盖掉原有元素 
(4)find(a.begin(),a.end(),10); //在a中的从a.begin()(包括它)到a.end()(不包括它)的元素中查找10,若存在返回其在向量中的位置

2、list基本操作

  list中各个元素之间也存在一个线性的逻辑次序,但是与vector极其不同的是,各单元的物理地址可以任意,无需是连续的空间分配。 

  这个算是一个技巧的介绍,有时候为了方便程序维护与以后修改,我们可以在程序头类型定义对应的模板类为一个简化名称(一般大写表示),如下。这样的好处就是一旦后面我们想用list<long>定义我们的变量,只需在此修改list<int>list<long>,从而不需要整个程序中修改了。此外取一个通俗易懂的名称也会增加程序的通读行。

#include<list>

typedef list<int> INTLIST;
typerdef vector<long> LONGVECTOR;
typerdef list<int>::iterator INTLISTITER; INTLIST list_fir; //声明一个list<int>对象
list<int> list_fir; //或者INTLIST list_fir,这里不去简写

list<int> list_sed(,);     // 申请10个空间,全部初始化为2

list<int> list_thd(list_fir); //拷贝构造

vector<int> vec(,);
list<int> list_for(vec.begin(),vec.end()); //拷贝vector一段数据初始化

//拼接方法
list_fir.merge(list_sed); // 拼接加在list_fir上,而list_sed变为空 list_fir.splice(list_fir.begin(),list_sed); //在list_fir初始位置拼接上list_sed list_fir.push_back(); //尾部增加一个110数
list_fir.push_front(); //首部增加一个1数 list_fir.pop_back(); //尾部删除一个数
list_fir.pop_front(); //首部删除一个数 //访问
int data1 = list_fir.front(); // 第一个数 int data2 = list_fir.back(); // 最后一个数 list<int>::iterator iter;
for(iter=list_fir.begin();iter!=list_end();iter++)
{
cout<<*iter<<endl; //就像指针一样*间接访问每个数 }

size_t = list_fir.size(); // 统计list中数据个数 list_fir.unique(); // 链表中每个连续出现的数仅保留第一次出现的那个 if(!list_fir.empty()) // 判断链表中是否为空
{
list_fir.clear(); // 清空链表
} list_fir.swap(list_sed);// 交换两个链表所有数据 list_fir.sort(); // 增序排序整个链表 list_fir.insert(list_fir.front()+3, 100); // 插入元素100,是将第三个元素放到第四个上,依次类推,把100放到第三个元素上
list_fir.erase(beg, end) // 删除区间内的数据,左闭右开,返回下一个数据的位置,比如:0 1 2 3 4 5,beg=0,end=3 ,删除后结果为:3 4 5
list_fir.erase(pos) // 删除该位置的数据,返回下一个数据的位置
list_fir.remove(elem) // 删除容器中 所有与 elem 值相匹配的元素

3、双向队列 — deque

  deque双向队列是一种双向开口的连续线性空间,可以高效的在头尾两端插入和删除元素,deque在STL中接口上和vector非常相似,此外它还是STL中queue和stack的底层依赖组件。

  deque拥有一个bitmap结构(称之为map,并不是STL中容器map),map中每一个元素指向一块连续的内存块,后者才是真正存储deque元素的地方,因为每个块都是固定大小的,但是每个块之间不要求是连续的,所以扩充空间的时候,就没有vector那样的副作用了,即无需“配置新空间 / 移动旧数据 / 释放旧空间”的一套过程。

#include<deque>
deque<string> deq_fir; cout<<deq_fir[]<<endl; //同样是查询下标为2的元素,即第三个元素
cout<<deq_fir.front()<<endl; //查询第一个元素
cout<<deq_fir.back()<<endl; //查询最后一个元素 deq_fir.erase(deq_fir.begin()+); //删除第五个元素
deq_fir.erase(deq_fir.begin(),deq_fir.begin()+); //删除前三个元素 deq_fir.insert(deq_fir.begin(),,"banana!"); //首部插入10个"banana!"字符串
deq_Fir.insert(deq_fir.end(),"apple!"); //尾部插入一个“apple!”字符串 deq_fir.push_back("hello"); //尾部添加字符串
deq_fir.push_front("world!");//首部添加字符串 deq_fir.pop_back(); //尾部删除一个元素
deq_fir.pop_front(); //首部删除一个元素 if(!deq_fir.empty()) // 判断是否为空deque
{
deq_fir.clear(); // 清空操作
}
if(deq_fir.size() > ) // 查询空间元素个数
deq_fir.resize(); // 重新定义deque空间大小到10 deq_fir.swap(deq_sed); // 交换两个deque中所有数据
    //正向迭代器,输出:1 3 5 7 9
deque<int>::iterator it;
for (it = deq.begin(); it != deq.end(); it++)
cout << *it << endl; // 查找数组中 某个元素 的位置下标
it = find(deq.begin(), deq.end(), );
if (it != deq.end())
{
cout << "5数组的下标为:" << distance(deq.begin(), it) << endl;
}
else
{
cout << "n没有找到5的元素" << endl;
}

4、queue基本操作

  它是一种先进先出(First In First Out ,简称FIFO)的线性表。只允许在表的尾端进行入队,而在首端进行出队。

#include<queue>
queue<int> que_fir;
queue<double> que_sed;
que_fir.push(); // 放入一个元素1在队列尾部
que_fir.pop(); // 删除队首一个元素
que_fir.back(); // 访问队尾元素
que_fir.front(); // 访问队首元素 if(!que_fir.empty()); // 判断队列是否为空
que_fir.swap(que_sed); // 完全交换两个队列中数据,当然两个队列中保存的必须是一种数据类型 que_fir.size(); // 队列中元素个数

5、stack基本操作

  栈只有一个出口,像下面一摞椅子一样,只能在栈顶上增加元素,也只能从栈顶移出元素和访问元素。

#include<stack>
stack<int> stk_fir;
stack<string> stk_sed; stk_fir.push(); // 栈顶入栈元素10086 stk_fir.pop(); // 删除一个栈顶元素 stk_fir.top(); // 访问栈顶一个元素(而queue可以访问队首和队尾,分别是front()和back()方法) stk_fir.size(); // 返回栈中元素个数 stk_fir.swap(stk_thd); // 交换两个相同类型的stack中所有数据 stk_fir.empty(); // 栈中为空则返回true

6、priority_queue基本操作

#include<queue>
priority_queue<int> que1; // 普通构造,默认是大顶堆
priority_queue<int, vector<int>, less<int>> //大顶堆:表示其他都比堆顶小
priority_queue<int, vector<int>, greater<int>> //小顶堆:表示其他都比堆顶大
que1.empty( ); // 判断队列是否为空 que1.pop( ); // 删除队顶元素 que1.push( ); // 加入一个元素 que1.size( ); // 返回优先队列中拥有的元素个数 que1.top( ); // 返回队顶元素,接口和stack名一样。而queue中是front()和back()

7、map(红黑树)

#include<map>

map<int,float> map_sed;

map_sed.insert(pair<int,float>( , 0.1234)); //方法一,当map中有这个关键字就不可以操作

map_sed.insert(map<int,float>::value_type(,100.86)); //方法二,同方法一

map_sed[] = ; // 方法三,可以重载

  当然前两种方式是一样的,都是用insert函数插入数据。但是数据的插入涉及到集合的唯一性这个概念,即当map中有这个关键字时,insert操作是插入数据不了的,但是用operator[]重载的方式就不同了,它可以覆盖以前该关键字对应的值。

map<int,float> map_fir;

map_fir.swap(map_sed); // 交换所有数据,需要确保map中元素类型相同

map_fir.clear();       // 清空map_fir

map_fir.size();        // 统计map_fir中元素个数

map_fir.empty();       // 判断map中是否为空,如果是空则返回1

  参考:https://blog.csdn.net/column/details/16577.html

上一篇:我的Android 4 学习系列之开始入手:配置开发环境与理解Hello World!


下一篇:L3-002 特殊堆栈 (30分) vector容器的模拟、vector容器的一些用法