文章目录
试着简单分析总结C++的容器用法并于py3简要对比
已经学习了不少时间的C++了,在学习C++核心编程中的内容时,不自觉地想要对比在学习python3中所遇到的collection库中的容器,鉴于自己的知识水平有限,半路出家的搬砖人,不对或者不足的地方,还望大佬们耐心指出啊!先谢过了。
写在前面,学习了C++才知道STL是什么?Standard Template Library(简称:STL),中文名称是标准数据库,其功能主要是方便后续编程使用。听得黑马的C++课程,还是很顶的,明白了好多东西,像:类啊!类对象啊!模板啊!还有C++面向对象的三大特性:封装、继承、多态啊!引用啊!重载啊!感觉C++东西好多,这才觉着py3简单,不过简单也有简单的不好,好多东西学的不明不白,你说它难吧,别人都说简单,没人讲,需要自己看文档,所以啊,自力更生吧,现在把东西梳理一下,方便以后使用。再强调一遍,C++面向对象的三大特性:封装、继承和多态。
-
STL广义上分为:容器(container)算法(algorithm)迭代器(iterator)
-
六大组件:
- 容器:各种数据结构,如:string、vector、deque、stack、queue、list、set、map;
- 算法:常用算法,如:sort、find、copy、for_each等;
- 迭代器:容器和算法之间的粘合剂;
- 仿函数:类函数模板,在模板中重载小括号();
- 适配器:一种修饰容器或仿函数或迭代器接口的东西;
- 空间配置器:负责空间的配置和管理。
-
容器:
- 序列式容器:容器内每个元素都有固定位置,如:string、vector、deque、stack、queue、list;
- 关联式容器:容器内各元素之间无严格物理顺序,如:map、set。
-
算法
- 质变算法:运算过程中会更改区间内元素内容,如:copy、replace;
- 非质变算法:运算过程中不会更改区间元素内容,如:find、count、for_each。
-
迭代器
- 最常用的双向迭代器(读写可以向前向后推进)、随机访问迭代器(跳跃式访问,功能较强)
1. string容器
处理字符串的容器,string是一个类,类内部封装了char*,管理这个字符串,是一个char*型的容器,简要总结可以使用的成员方法(头文件为 <string>):
- 构造函数:
string();
//创建一个空的字符串 例如: string str;string(const string& str);
//使用一个string对象初始化另一个string对象string(int n, char c);
//使用n个字符c初始化 (这个类型的创建方式非常常见!)
- 赋值一般使用等号或者assign:
string& operator=(const string &s);
//把字符串s赋给当前的字符串string& assign(const string &s);
//把字符串s赋给当前字符串
- 拼接采用加法操作符或append函数:
string& operator+=(const string& str);
//重载+=操作符string& append(const string &s);
//同operator+=(const string& str)
- 查找:
int find(const string& str, int pos = 0) const;
//查找str第一次出现位置,从pos开始查找int rfind(const string& str, int pos = npos) const;
//查找str最后一次位置,从pos开始查找
- 替换:
string& replace(int pos, int n, const string& str);
//替换从pos开始n个字符为字符串str
- 比较进行字母的ASCII码大小对比:
int compare(const string &s) const;
//与字符串s比较
- 插入:
string& insert(int pos, const string& str);
//插入字符
- 删除:
string& erase(int pos, int n = npos);
//删除从Pos开始的n个字符
- 字串获取:
string substr(int pos = 0, int n = npos) const;
//返回由pos开始的n个字符组成的字符串
非常类似于py3中的char数据类型,还是py3省力气啊!py3中常用加号进行拼接,替换,
但是py3的字符串函数方法较多,例如:split()函数,join()函数等,这里需要整理一下。
2. vector容器*
单端数组,区别于数组的动态扩展,简要总结可以使用的成员方法(头文件为 <vector>,支持随机访问迭代器):
- 构造函数:
vector<T> v;
//采用模板实现类实现,默认构造函数vector(v.begin(), v.end());
//将v[begin(), end())区间中的元素拷贝给本身。vector(n, elem);
//构造函数将n个elem拷贝给本身。vector(const vector &vec);
//拷贝构造函数。
- 赋值一般使用等号或者assign:
vector& operator=(const vector &vec);
//重载等号操作符assign(beg, end);
//将[beg, end)区间中的数据拷贝赋值给本身。assign(n, elem);
//将n个elem拷贝赋值给本身。
- 返回容量或大小或调整大小:
empty();
//判断容器是否为空capacity();
//容器的容量size();
//返回容器中元素的个数resize(int num);
//重新指定容器的长度为num,若容器变长,则以0填充新位置;如果容器变短,则末尾超出容器长度的元素被删除。
- 插入与删除:
push_back(ele);
//尾部插入元素elepop_back();
//删除最后一个元素insert(const_iterator pos, ele);
//迭代器指向位置pos插入元素eleinsert(const_iterator pos, int count,ele);
//迭代器指向位置pos插入count个元素eleerase(const_iterator pos);
//删除迭代器指向的元素erase(const_iterator start, const_iterator end);
//删除迭代器从start到end之间的元素clear();
//删除容器中所有元素
- 存取:
at(int idx);
//返回索引idx所指的数据operator[];
//返回索引idx所指的数据front();
//返回容器中第一个数据元素back();
//返回容器中最后一个数据元素
- 交换:
swap(vec);
// 将vec与本身的元素互换
vector的功能有点像stack,但两个似乎不一样,在py3中习惯使用list了,
或是直接使用 [] 进行创建,对于数组大小的获取常用len()函数直接获取,
这一点py3特别省劲,而C++创建的数组需要使用sizeof()进行处理,
我猜测vector的创建一定程度是为了增加数组的包容性(对于自定义数据类型),
同时有效省去一些繁琐的重复操作。
3. deque容器
双端数组,在需要头插尾插的情况下,使用非常便利,简要总结可以使用的成员方法(头文件为 <deque>,支持随机访问迭代器):
- 构造函数:
deque<T>
deqT; //默认构造形式deque(beg, end);
//构造函数将[beg, end)区间中的元素拷贝给本身。deque(n, elem);
//构造函数将n个elem拷贝给本身。deque(const deque &deq);
//拷贝构造函数
- 赋值一般使用等号或者assign:
deque& operator=(const deque &deq);
//重载等号操作符assign(beg, end);
//将[beg, end)区间中的数据拷贝赋值给本身。assign(n, elem);
//将n个elem拷贝赋值给本身。
- 返回大小或调整大小(注意没有容量的概念):
deque.empty();
//判断容器是否为空deque.size();
//返回容器中元素的个数deque.resize(int num);
//重新指定容器的长度为num,若容器变长,则以0填充新位置;如果容器变短,则末尾超出容器长度的元素被删除。
- 插入与删除:
push_back(elem);
//在容器尾部添加一个数据push_front(elem);
//在容器头部插入一个数据pop_back();
//删除容器最后一个数据pop_front();
//删除容器第一个数据
insert(pos,elem);
//在pos位置插入一个elem元素的拷贝,返回新数据的位置。insert(pos,n,elem);
//在pos位置插入n个elem数据,无返回值。insert(pos,beg,end);
//在pos位置插入[beg,end)区间的数据,无返回值。clear();
//清空容器的所有数据erase(beg,end);
//删除[beg,end)区间的数据,返回下一个数据的位置。erase(pos);
//删除pos位置的数据,返回下一个数据的位置。
- 存取:
at(int idx);
//返回索引idx所指的数据operator[];
//返回索引idx所指的数据front();
//返回容器中第一个数据元素back();
//返回容器中最后一个数据元素
- 排序(删除最低分与最高分):
sort(iterator beg, iterator end)
//对beg和end区间内元素进行排序
deque在py3中也存在,即: from collections import deque,非常好用,
经常在 BFS(广度优先遍历算法)中出现,对于打分这件事情而言,真好用!
4. stack容器
单端的数据结构,在数组单调存储中用处挺大,在股票类似的题目中出现频繁,对于栈(stack)的先进后出的理解可以直接把其想象成为子弹上膛,非常形象。简要总结可以使用的成员方法:
- 构造函数:
stack<T> stk;
//stack采用模板类实现, stack对象的默认构造形式stack(const stack &stk);
//拷贝构造函数
- 赋值一般使用等号(append()仅在string容器中常用,其它类型容器则不可以。):
stack& operator=(const stack &stk);
//重载等号操作符
- 返回大小:
empty();
//判断堆栈是否为空size();
//返回栈的大小
- 数据存取:
push(elem);
//向栈顶添加元素pop();
//从栈顶移除第一个元素top();
//返回栈顶元素
stack在py3中一般使用list进行创建,即:之间令 stack = [] ,
同样是先进后出,但却使用append()函数追加元素,使用pop()函数返回栈顶元素吗,
而C++中append()函数主要用于字符串的操作,这里需要注意区分。
6. queue容器
队列,先进先出,跟学校排队打饭一样,简要总结可以使用的成员方法:
- 构造函数:
queue<T> que;
//queue采用模板类实现,queue对象的默认构造形式queue(const queue &que);
//拷贝构造函数
- 赋值一般使用等号:
queue& operator=(const queue &que);
//重载等号操作符
- 返回大小:
empty();
//判断堆栈是否为空size();
//返回栈的大小
- 数据存取(没了top(),但多了front()和back()):
push(elem);
/往队尾添加元素pop();
//从队头移除第一个元素back();
//返回最后一个元素front();
//返回第一个元素
在py3中常用list进行代替,要不说py3省力气那,人家都给我们考虑好了,
list数据类型既可以当stack使用,亦可以当queue使用,
不过全部封装在一起有时候还是需要拆开好好了解一下。
7. list容器*
链表,单个最小的存储单元出来记录本位的数据,同时记录下一个数据的地址,简要总结可以使用的成员方法:
- 构造函数:
list<T> lst;
//list采用采用模板类实现,对象的默认构造形式:list(beg,end);
//构造函数将[beg, end)区间中的元素拷贝给本身。list(n,elem);
//构造函数将n个elem拷贝给本身。list(const list &lst);
//拷贝构造函数。
- 赋值一般使用等号或者assign:
assign(beg, end);
//将[beg, end)区间中的数据拷贝赋值给本身。assign(n, elem);
//将n个elem拷贝赋值给本身。list& operator=(const list &lst);
//重载等号操作符
- 返回大小或调整大小(注意没有容量的概念):
list.empty();
//判断容器是否为空list.size();
//返回容器中元素的个数list.resize(int num);
//重新指定容器的长度为num,若容器变长,则以0填充新位置;如果容器变短,则末尾超出容器长度的元素被删除。
- 插入与删除(比较deque多了一个remove()函数):
push_back(elem);
//在容器尾部添加一个数据push_front(elem);
//在容器头部插入一个数据pop_back();
//删除容器最后一个数据pop_front();
//删除容器第一个数据
insert(pos,elem);
//在pos位置插入一个elem元素的拷贝,返回新数据的位置。insert(pos,n,elem);
//在pos位置插入n个elem数据,无返回值。insert(pos,beg,end);
//在pos位置插入[beg,end)区间的数据,无返回值。clear();
//清空容器的所有数据erase(beg,end);
//删除[beg,end)区间的数据,返回下一个数据的位置。erase(pos);
//删除pos位置的数据,返回下一个数据的位置。remove(elem);
//删除容器中所有与elem值匹配的元素。
- 存取:
front();
//返回第一个元素。back();
//返回最后一个元素。
- 交换:
swap(lst);
//将lst与本身的元素互换。
- 反转:
reverse();
//反转链表。
- 排序:
sort();
//链表排序。
C++中vector和list最为常用,py3中list类型也使用很频繁。
8. set/multiset容器(与py3的重要区别,C++有序,py3无序)
set容器中所有元素都会在插入时自动被排序,set/multiset属于关联式容器,底层结构是用二叉树实现。其中set不允许容器中有重复的元素,multiset允许容器中有重复的元素简。要总结可以使用的成员方法:
- 构造函数:
set<T> st;
//默认构造函数:set(const set &st);
//拷贝构造函数。
- 赋值一般使用等号:
set& operator=(const set &st);
//重载等号操作符
- 返回大小:
size();
//返回容器中元素的数目empty();
//判断容器是否为空
- 插入与删除:
insert(elem);
//在容器中插入元素。clear();
//清除所有元素erase(pos);
//删除pos迭代器所指的元素,返回下一个元素的迭代器。erase(beg, end);
//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。erase(elem);
//删除容器中值为elem的元素。
- 存取:
front();
//返回第一个元素。back();
//返回最后一个元素。
- 交换:
swap(st);
//交换两个集合容器
- 查找:
find(key);
//查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
- 计数:
count(key);
//统计key的元素个数
- 排序:
- 需要用伪函数进行数据对比
class MyCompare {
public:
bool operator()(int v1, int v2) {
return v1 > v2;
}
};
set<int,MyCompare> s;
// 之后此次插入数据
- 补充:pair队组创建方式:
pair<type, type> p ( value1, value2 );
pair<type, type> p = make_pair( value1, value2 );
py3的文档中:A set object is an unordered collection of distinct hashable objects.(集合对象是不同可散列对象的无序集合。)而在C++中set集合是有序的。
9. map/multimap容器
map中所有元素都是pair,pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
,所有元素都会根据元素的键值自动排序,map/multimap和set一样属于关联式容器,map不允许容器中有重复key值元素,而 multimap允许容器中有重复key值元素简要总结可以使用的成员方法(与set的成员函数大致相同):
- 构造函数:
map<T1, T2> mp;
//map默认构造函数:map(const map &mp);
//拷贝构造函数
- 赋值一般使用等号:
map& operator=(const map &mp);
//重载等号操作符
- 返回大小:
size();
//返回容器中元素的数目empty();
//判断容器是否为空
- 插入与删除:
insert(elem);
//在容器中插入元素。clear();
//清除所有元素erase(pos);
//删除pos迭代器所指的元素,返回下一个元素的迭代器。erase(beg, end);
//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。erase(elem);
//删除容器中值为elem的元素。
- 存取:
front();
//返回第一个元素。back();
//返回最后一个元素。
- 交换:
swap(st);
//交换两个集合容器
- 查找:
find(key);
//查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
- 计数:
count(key);
//统计key的元素个数
- 排序:
- 需要用伪函数进行数据对比
class MyCompare {
public:
bool operator()(int v1, int v2) {
return v1 > v2;
}
};
map<int,int,MyCompare> m;
// 之后此次插入数据
py3中使用collections中的defaultdict容器作为map使用,py3对于mao数据类型的处理方式较多。
结论
慢慢干货啊,现在心态也静下来了,开始认真地写blog,并且学习记忆了,昨天看到那些大佬,都说自己没天分,但非常勤奋,我很受鼓舞,我觉着自己也要勤奋点了,只有更勤奋,才能有机会正确到更多机会。