c++11容器操作

通用函数:

  1. to_string(任何类型的数) //将一个数变为string
    要#include"sstream"
    在这里插入图片描述
  2. trackback中使用:
    auto it = find(track.begin(), track.end(), nums[i])
    if(it != track.end())
    continue;

STL综述

STL中的容器就是类模板,算法就是函数模板,如sort、size、

STL中的数据结构:

1)vector size------->2*size
2)deque 双向队列
3)list 双向链表
4)queue 队列 底层:list或deque
5)stack 同queue
6)priority_queue 优先队列 底层:vector
7)map

map的三种插入元素方法:
map<string, int>map1;
map1.insert(pair<string, int>("xinsuan", 1)); //
map1.insert(map<string, int>::value_type("xinsuan1", 1));
map1["xinsuan2"] = 1; //同key覆盖
删除元素的方法
map1.erase(key)
map2.erase(iterator)
遍历容器
for(auto iter = map1.begin(); iter !+ map1.end(); ++iter)

7) 各种set和map
set、unordered_set、multiset、hash_set
set、map: 底层通过红黑树存储,不可重复,默认有序,查询时间是o(logn)
map、multi_map: 底层红黑树
unordered_set、unordered_map、hash_map、hash_set: 底层通过哈希表实现,解决冲突的方法是链地址法,

template<class Key,
	class Hash = hash<Key>,
	class Pred = equal to <Key>,
	class Alloc = allocator<Key>>
	class unordered_set;

也就是一个unordered_set的实现需要Hash函数, Pred比较函数,用来比较元素值是否相等),Alloc(内存分配函数)。
set和multiset, 包含头文件为:#include, 如果要自定义排序方式,则为:

set<int, greater<int>> set1;

迭代器
要访问顺序容器和关联容器中的元素,需要通过“迭代器”进行。迭代器是一个变量,相当于容器和操纵容器的算法之间的中介。迭代器可以指向容器中的某个元素,通过迭代器就可以读写它指向的元素。从这一点上看,迭代器和指针差不多
迭代器的分类
常用的迭代器按功能强弱可分为:输入、输出、正向、反向、双向、随机访问六种
1)正向迭代器 只支持 ++p, p ++, *p, ==, !=
2) 双向迭代器, 支持 ++p, p ++, *p,==,!=, 还支持 --p, p–
3) 随机访问迭代器,支持++p, p ++, *p, --p, p–, p +=i, p -=i, p+i, p-i, p[i], 以及<, >, <=, >=
不同容器的迭代器:
在这里插入图片描述
也就是容器的类型决定迭代器的类型,vector中的就是随机访问迭代器, list中的就是双向迭代器,从而也要遵守各自对应的规则。

set 有序,不重复
map 有序,不重复
hash_set 无,不
hash_map 无,不
unordered_set
unordered_map = hash_map, 但前者已经纳入了标准库
multiset有,可重复
multimap 有,可重复
multimap不可用下标形式,只可通过迭代器来访问key和value 如:
只有关联式容器和string有.find函数
如:

multimap<int, int> map1;
map1[0] = 1; //错误,不能使用下标形式
map1.insert({0,1}) //正确,只能通过insert pair来插入key-value
map1.insert({0,2});
map1.insert({0,3});
map1.insert({1,4});
int a = map1[0] //错误,不能通过下标访问value
auto iter = map1.find(0) //iter指向第一个key= 0的元素
auto iter1 = map1.lower_bound(0) //iter1指向第一个key = 0的元素(第一个不小于k的元素,即k本身)
auto iter2 = map1.find(0);
auto iter3 = map1.upper_bound(0) //iter2指向最后一个key = 0元素的下一个位置(第一个大于k的元素)
iter3 --;
while(++iter2 != iter3)
; //这个while循环后,iter2就指向最后一个key = 0的元素

iter只可 ++,–, 不可 += 1, -= 1.

multi 有,可
hash_multiset 无,可
hash_multimap 无,可
底层都是红黑树

string的操作
b = a.substr(开始位置, 计数)
a == b //两个字符串可以直接相等
a.insert(要插入的位置, 数量,插入的字符)
要让char变成string,与已有的string相加:

string res = "";
string a(1, pre+'0');
res = b + res;

栈stack和队列queue的操作
stack: s.top() 、s.push()、s.pop()、s.size()、s.empty()
queue: q.front()、q.push()、q.pop()、q.size()、q.empty()

关联容器操作
1)查找是否存在某个key
map.find(key) != map.end()
2) insert操作
对于不可重复的容器:
insert(item)和emplace(item)会返回一个pair, pair.first是一个迭代器,指向给定关键字的元素,pair.second是一个bool值,确定插入是否成功
map的 insert 形式:
map1.insert({key, value});
map1.insert(make_pair(key, value));
map1.insert(pair<string, int>(key, value));
set本身是不能insert一个pair的,所以要自己指定哈希函数
3)关联容器的迭代器
迭代器的申明:

one: auto iter1 = map1.begin()
two: set::iterator itre1 = set1.begin();
map的迭代器如: auto = map1.begin()获得一个迭代器的初始值,是一个指向pair对象的引用, 为begin处的key-value 对,为pair类型
通过map1->first 获得key
4) 要注意的是关联容器的key是不可以改变的,为const
5)遍历关联容器
step1:定义一个迭代器,初始化为map1.cbegin()
step2: while(该迭代器 != map1.cend()) 访问
6)如果要让set的key变成pair类型
因为set的key类型没有pair类型,所以要自己为pai类型的key构造一个哈希函数

struct pair_hash{
inline size_t operator()(const pair<int, int> &p) const{
return p.first * 100 + p.second;
}
};//定义了一个哈希函数结构体
unordered_set<pair<int, int>, hash_pair> set1;
//定义了一个pair元素的set
set.insert({1, 2}) //插入一个元素
if(set1.find({1, 2}) != set1.end()) //判断是否存在这个元素

关联容器中set和unordered_set区别
涉及到底层数据结构的实现,set基于红黑树,可以进行自动排序;unordered_set用哈希表实现,并不保证有序,但后者查找更快,几乎是常数时间。至于multi_set,则是允许关键字有重复。
set和map的区别:前者只有关键字,后者是键-值组合
各种set的对比同各种map的对比
关联容器添加元素insert操作

vector<int> ivec = {2,4,6,8,2,4,6,8};
set<int> set1;
set1.insert(ivec.cbegin(), ivec.cend()); //插入了4个元素
set1.insert({1,3,5,7,1,3,5,7});  //现在8个元素

pair的介绍
pair是一个标准库类型,定义在头文件utility中
一个pair必须保存两个数据成员,且为public的,也就是通过对象.成员的方式可以访问,且第一个成员为w.first, 第二个成员w.second
pair定义及初始化的方式:pair<string , string>pair1{item1, item2}; 或者pair1(item1, item2)
make_pair(v1, v2) //返回一个用v1、v2初始化的pair

所有的vector类型的均不能直接cout,要遍历,但遍历有其自己的方法:for(auto && i: vector_name)
cout<<i<<’ ';

1. 基本操作函数
uniuqe(A.begin(), A.end()) 去除容器中中的相邻重复元素,该函数并不是删除重复的元素,而是把重复的元素放到后面,返回的是去重后的尾地址,所以应用unique函数分为两步:

1.首先对容器进行排序
2.删除挪到后边的重复元素
举例:
vector<int> nums = {4,4,2,2,2,3,1,5,5};
sort(nums.begin(), nums.end());
nums.erase(unique(nums.begin(), nums.end()), nums.end());
这样就删除了nums中的重复元素

顺序容器类型有:vector、deque、list、forward_list、array、string
判断顺序容器中是否存在某个指定元素:

vector<int> track;
auto it = find(track.begin(), track.end(), nums[i]);
if(it != track.end())
//说明track中存在nums[i]

容器类型中的array是固定大小的,所以不能进行插入删除操作

a.swap(b) = swap(a,b)   交换a和b的元素
a.size()   a中元素的数目
a.resize(n)  重置a的大小为n
a.insert(iter, args)   在iter迭代器之前插入args,如果insert只有一个参数,则就是要插入的值

list<string>lst;
auto iter = lst.begin();
while(cin >> word)
iter = lst.insert(iter, word);//等价于调用push_front,
//即永远在最新insert的那个位置前插入新元素

a.erase(iter a, iter b)   删除iter a, b之间的元素
a.erase(iter p) 删除迭代器p所指的元素
a.clear()   删除a中所有元素a
a.begin() 、a.end()  返回指向a中首元素位置、尾元素之后的位置,[begin,end)
a.assign(b.begin(), b.end())   把b中元素从[begin,end)copy到a中(array除外)
a.assign(整数n,args) 把n个args拷贝到a中
a.push_back(args)  在a的尾部追加args
a.push_front(args) 将args插入a的头部
push_front() vector并不支持
insert(pos, item)则支持

a.pop_front() 删除首元素
a.pop_back  删除尾元素
a.front() 返回首元素的引用,如果(假设vector是int型)令int &b = a.front(),则该操作可以改变首元素的值
a.back()返回尾元素的引用,不会改变尾元素

sort(a.begin(), a.end(), less或greater<int>())greater是从大到小
sort函数深入应用:

sort(参数1, 参数2, 参数3)
参数1:排序的起始位置
参数2:排序的终止位置的下一个
参数3:排序规则,一般定义了“<、>”运算符的可以直接用less<类型>、greater<类型>,除此之外的很多复杂数据类型的排序就要用到比较函数:cmp

比如要对一个元素为结构体的数组arr[100]排序,结构体定义如下:
struct node{
	int a;
	int b;
	int c;
};
排序要求为:先按照a升序, 再按照b降序,再按照c降序
cmp函数定义如下:
bool cmp(node x, node y){
	if(x.a != b.a) return x.a < x.a;
	if(x.b != y.b) return x.b > y.b;
	return x.c > y.c;
}
排序时的写法:
sort(arr, arr+100, cmp);


reverse(a.begin(), a.end());
a.find(item)//返回item的index
创建一个二维vector:
vector temp(n, 0);
vector<vector > res(m, temp) //我觉得是m×n

查看一个变量类型:typeid(a).name(), 要#include<\typeinfo>

2. 两个容器的拷贝
1) 直接拷贝整个容器,要求:两个容器的类型和元素类型必须匹配

 list<string> authors = { "Milton","Shakespeare","Austen" };
 vector<const char*> articles = { "a","an","the" };//每个元素是一个字符串

 list<string> list2(authors) //正确
 deque<string> authList(authors); //错误:容器类型不匹配
 vector<string> words(articles);//错误:容器类型不匹配

2)拷贝由一个迭代器对指定的元素范围,不要求两个容器类型相同
         两个迭代器分别标记想要拷贝的第一个元素和尾元素之后的位置

deque<string> authorList(authors.begin(), author.begin()+2)

3. 容器定义与初始化
1)

 list<string> authors = { "Milton","Shakespeare","Austen" };
 vector<const char*> articles = { "a","an","the" };

2)

vector<int> ivec(10 -1); //10个int元素,每个都初始化为-1
list<string> svec(10,"hi!"); //10个strings,每个都初始化为“hi!”
forward_list<int> ivec(10); //10个元素,每个都初始化为0
deque<string> svec(10); //10个元素,每个都是空string 

要注意的是array是固定大小的,定义形式如下:
array<int, 42>,即元素型和容器大小都要指定

4. string容器的特殊操作
1)s.substr(pos, n) //拷贝从pos位置开始的n个字符
其中pos不可缺省,n可缺省,如果只有一个参数,则默认是pos,拷贝从pos到末尾
2)string是容器所以它也是可以动态扩展的,string添加元素也是通过:string.push_back()
5.class
private:
public:如果不写,默认为private
私有的成员函数只能被本类里的其他成员函数调用
成员函数可以访问本类中任何数据(不管私有还是public)
类外定义成员函数要加上::符号(作用域限定符),如void Student::display()
inline函数(内置函数):c++会把在类内定义的 无循环等控制结构的成员函数默认是inline函数,不是调用使用成员函数,而是直接嵌入调用口
类的size不包含成员函数,成员函数是同一个类的所有成员函数公用的
2)如何引用对象成员元
三种方式(对象、对象指针、对象引用)
3)构造函数
构造函数与类名同名、无返回值、无函数类型,用于对成员进行初始化,如果自己不指定构造函数,系统自动有个构造函数,但是空的,不做任何处理
带参数的构造函数,使用方法是直接在定义对象时给出实参
构造函数有两种定义方式:
1)在函数体内通过赋值语句初始化成员
2)在这里插入图片描述
构造函数的重载:可以定义多个构造函数
1)无参 构造函数 调用无参构造函数时是Box box1; 而不是Box box1();
2)有参构造函数 Box box2(h,w,l);
使用默认参数的构造函数
在定义构造函数时给出形参的默认取值,当调用构造函数(定义对象)时,根据用户给出的实参个数来看成员的赋值。
当定义有默认参数的重构函数时,为避免歧义性,一般不会重载重构函数

析构函数
定义方式:类名::~类名()
析构函数作用是在释放对象内存空间前完成一些事情
析构函数的调用顺序
1)当对象都为局部自动对象时,先定义的对象后调用析构函数
2)当定义的对象时静态(static)局部对象时,函数调用结束,并不调用析构函数,等程序结束或exit时,才会调用析构函数。
对象的new和delete
Box *pt = new Box(h, w, l);
静态数据成员
当需要多个对象的某个成员取值一样时,把该成员设为静态数据成员
静态数据成员,该成员为所有对象共有,只占一个存储空间,而不是每个对象都存
静态数据成员只能在类外单独初始化,形式为:int Box::height =10;
因此构造函数里就不要初始化静态数据成员。

关于静态成员函数、静态成员,非静态成员函数、非静态成员之间的关系
静态成员函数只能访问静态数据成员
非静态成员函数则均可访问非静态与静态数据成员,一般做法是通过在某个非静态成员函数中更新静态数据成员的值(由于每个对象都会执行非静态成员函数)
友元函数
友元函数的作用是:以一个类friend的身份来访问该类的数据
友元函数的定义一般是 :
1)先需要在该类(类为Time)中声明友元函数: friend void display(Time &);
2)在类外进行定义:
void display(Time &t);

类模板的定义:
template
class 类模板名Compare{};
使用类模板定义对象:Compare cmp(4,7)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值