C++STL中的常用的数据结构
STL中常用的数据结构:
[1] stack、queue默认的底层实现为deque结构。
[2] deque:用map管理多个size大小的连续内存块,方便头尾插入。
[3] vector:变长动态数组,每次增大1.5倍,删除元素时不释放空间。
[4] priority_queue底层默认采用vector向量O(nlogn)。
[5] list:双向链表容器。
[6] slist:单向链表容器。
[7] bit_vector:一个bit位元素的序列容器,常用于硬件端口的控制。区别于vector<bool>重要特性是节省空间。
[8] set集合容器、multiset多重集合容器均采用红黑树实现,后者允许相同元素。
[9] map、multimap为映照容器,底层为红黑树。后者允许相同元素。
[10] hash_set哈希集合容器/hash_map哈希映照容器均采用hashtable。
[11] string基本字符序列容器。
1、C++ vector使用方法
1.1 基本操作
(1)头文件#include<vector>
(2)创建vector对象,vector<int> vec;
(3)尾部插入数字:vec.push_back(a);
(4)使用下标访问元素,cout<<vec[0]<<endl;
记住下标是从0开始的。
(5)使用迭代器访问元素.
vector<int>::iterator it;
for(it=vec.begin();it!=vec.end();it++)
cout<<*it<<endl;
(6)插入元素:vec.insert(vec.begin()+i,a);
在第i+1个元素前面插入a;
(7)删除元素:vec.erase(vec.begin()+2);
删除第3个元素vec.erase(vec.begin()+i,vec.end()+j);
删除区间[i,j-1];区间从0开始
(8)向量大小:vec.size();
(9)清空:vec.clear();
特别提示:这里有begin()
与end()
函数、front()
与back()
的差别
1.2重要说明
vector的元素不仅仅可以是int,double,string,还可以是结构体,但是要注意:结构体要定义为全局的,否则会出错。
1.3算法
(1) 使用reverse将元素翻转:需要头文件
#include<algorithm>
reverse(vec.begin(),vec.end());
将元素翻转,即逆序排列!
(在vector中,如果一个函数中需要两个迭代器,一般后一个都不包含)
(2)使用sort排序:需要头文件
#include<algorithm>,
sort(vec.begin(),vec.end());
(默认是按升序排列,即从小到大).
可以通过重写排序比较函数按照降序比较,如下:
定义排序比较函数:
bool Comp(const int &a,const int &b)
{
return a>b;
}
调用时:sort(vec.begin(),vec.end(),Comp)
,这样就降序排序。
输出Vector的中的元素
vector<float> vecClass;
int nSize = vecClass.size();
//打印vecClass,方法一:
for(int i=0;i<nSize;i++)
{
cout<<vecClass[i]<<" ";
}
cout<<endl;
需要注意的是:以方法一进行输出时,数组的下表必须保证是整数。
//打印vecClass,方法二:
for(int i=0;i<nSize;i++)
{
cout<<vecClass.at(i)<<" ";
}
cout<<endl;
//打印vecClass,方法三:输出某一指定的数值时不方便
for(vector<float>::iterator it = vecClass.begin();it!=vecClass.end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
2.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) 中即可
3.deque的用法
deque 也是顺序容器的一种,同时也是一个可变长数组。要使用 deque,需要包含头文件 deque。所有适用于 vector 的操作都适用于 deque。push_back
从尾部插入元素push_front
从头部插入元素pop_back
从尾部删除元素pop_front
从头部删除元素
它有两种 vector 没有的成员函数:void push_front (const T & val);
//将 val 插入容器的头部void pop_front();
//删除容器头部的元素
distance
函数可以求出当前的迭代器指针it距离头部的位置,也就是容器的指针
用法: distance(v1.begin(), it)
4.stack的用法size();
大小empty();
是否为空void pop();
弹出(即删除)栈顶元素T & top();
返回栈顶元素的引用。通过此函数可以读取栈顶元素的值,也可以修改栈顶元素void push (const T & x);
将 x 压入栈顶
5.queue和priority_queue
queue
queue 就是“队列”。队列是先进先出的,和排队类似。队头的访问和删除操作只能在队头进行,添加操作只能在队尾进行。不能访问队列中间的元素。
queue 同样也有和 stack 类似的 push
、pop
、top
函数。区别在于,queue 的 push 发生在队尾,pop 和 top 发生在队头。
priority_queue
priority_queue 是“优先队列”。它和普通队列的区别在于,优先队列的队头元素总是最大的——即执行 pop
操作时,删除的总是最大的元素;执行 top
操作时,返回的是最大元素的引用。
priority_queue<int>
默认定义int类型的最大值队列priority_queue<int, vector<int>, less<int>>
定义int型的最大值优先队列priority_queue<int, vector<int>, greater<int>>
定义int型的最小值队列
priority_queue 默认的元素比较器是 less 。也就是说,在默认情况下,要放入 priority_queue 的元素必须是能用“<”运算符进行比较的,而且 priority _queue 保证以下条件总是成立:对于队头的元素 x 和任意非队头的元素 y,表达式“x<y”必为 false。
priority_queue 的第三个类型参数可以用来指定排序规则。
priority_queue 队头的元素只能被查看或者修改,不能被删除。
6.pair用法
pair实例化出来的类都有两个成员变量,一个是 first, 一个是 second。
STL 中还有一个函数模板 make_pair,其功能是生成一个 pair 模板类对象。make_pair 的源代码如下:
template <class T1, class T2>
pair<T1, T2 > make_pair(T1 x, T2 y)
{
return ( pair<T1, T2> (x, y) );
}
下面的程序演示了 pair 和 make_pair 的用法。
#include <iostream>
using namespace std;
int main()
{
pair<int,double> p1;
cout << p1.first << "," << p1.second << endl; //输出 0,0
pair<string,int> p2("this",20);
cout << p2.first << "," << p2.second << endl; //输出 this,20
pair<int,int> p3(pair<char,char>('a','b'));
cout << p3.first << "," << p3.second << endl; //输出 97,98
pair<int,string> p4 = make_pair(200,"hello");
cout << p4.first << "," << p4.second << endl; //输出 200,hello
return 0;
}
7.map的用法
基本操作:
C ++ Maps是一种关联式容器,包含“关键字/值”对
begin()返回指向地图右侧的继承器
clear()删除所有元素
begin()返回指向地图右侧的继承器
clear()删除所有元素
count()返回指定元素出现的次数
empty()如果map为空则返回true
end()返回指向地图末尾的继承器
equal_range()返回特殊的的继承器对
delete()删除一个元素
find()发现一个元素
get_allocator()返回地图的配置器
insert()插入元素
key_comp()返回比较元素key的函数
lower_bound()返回键值> =给定元素的第一个位置
max_size()返回可以容纳的最大元素个数
rbegin()返回一个指向地图尾部的逆向迭代器
rend()返回一个指向地图头部的逆向迭代器
size()返回地图中元素的个数
swap()交换两个地图
upper_bound()返回键值>给定元素的第一个位置
value_comp()返回比较元素value的函数
用法示例
//通过pair<int, string>(1,”chenhua“) 构造pair元素
map1.insert(pair<int, string>(0,"zero"));
//通过make_pair构造pair元素
map1.insert(make_pair(1,"m"));
//通过value_type构造pair元素
map1.insert(map<int, string>::value_type(3,"ming"));
//[]直接插入
map1[4] = "hello";
8、set的用法
C++的set容器,其中包含的元素是唯一的,而且是有序的。
C++的set容器,是按照顺序插入的,不能在指定位置插入。
C++的set容器,其结构是红黑二叉树,插入数据的效率比vector快
创建集合的方式:
set<int>
创建默认的从小到大的int类型的集合set<int,less<int>>
创建一个从小打到大的int类型的集合set<int,greater<int>>
创建一个从大到小的int类型的集合
set提供了insert
和erase
函数,用来对元素进行插入和删除操作。
set容器提供了多个函数用来查找元素:iterator find(const key_type& __k)
find函数查找元素为k的迭代器位置iterator lower_bound(const key_type& __k)
lower_bound函数查找小于等于元素k的迭代器位置iterator upper_bound(const key_type& __k)
upper_bound函数查找大于元素k的迭代器位置pair<iterator,iterator> equal_range(const key_type& __k)
equal_range函数返回一个pair类型,第一个属性表示大于等于k的迭代器位置,第二个是大于k的迭代器位置
9.multiset容器
multiset容器,与set容器相似,但是multiset容器中的元素可以重复。另外,他也是自动排序的,容器内部的值不能随便修改,因为有顺序的。
multimap容器,与map容器的唯一区别是:multimap支持多个键值。