string容器
一些基础的就不说了
string();
创建一个长度为0的string对象(默认构造函数)。sring(const char *s);
将string对象初始化为s指向的 NBTS(转换函数)。string(const string &str);
将string对象初始化为str(拷贝构造函数)。string(const void *s,size_t n);
将string对象初始化为s指向的地址后n字节的内容。string(const string &str,size_t pos=0,size_t n=npos);
将sring对象初始开始到结尾的字符,或从位置pos 开始的n个字符。template<class T> string(T begin,T end);
将string对象初始化为区间[begin,end]内的字符,其中 begin和end的行为就像指针,用于指定位置,范围包括begin在内,但不包括end。
#define _CRT_SECUER_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main() {
struct st_girl {//超女结构体
int bh;
char name[30];
bool yz;
double weight;
string memo;
}girl;
cout << "超女结构体的大小" << sizeof(struct st_girl) << endl;
string buffer;//创建一个空的string容器buffer
///生成10名超女的信息,存入buffer中
for (int ii = 1;ii <= 10;ii++) {
//对超女结构体成员赋值
memset(&girl, 0, sizeof(struct st_girl));
girl.bh = ii;
sprintf(girl.name, "西施%02d", ii);
girl.yz = true;
girl.weight = 48.5 + ii;
girl.memo = "中国历史第一美女.";
//把超女类追加到buffer中
buffer.append((char*)&girl, sizeof(struct st_girl));
cout << (void*)&girl << endl;
}
cout << "buffer.capacity()=" << buffer.capacity() << endl;//显示容量
cout << "buffer.size()=" << buffer.size() << endl;//显示实际大小
//用一个循环,把buffer容器中全部的数据取出
for (int ii = 0;ii < buffer.size() / sizeof(struct st_girl);ii++) {
memset(&girl, 0, sizeof(struct st_girl));//初始化超女结构体
//把容器中的数据复制到超女结构体
memcpy(&girl, buffer.data() + ii * sizeof(struct st_girl), sizeof(struct st_girl));
//buffer.copy((char*)&girl,sizeof(struct st_girl),ii*sizeof(struct st_girl));
//显示超女结构体成员的值
cout << "bh=" << girl.bh << ",name=" << girl.name << ",yz=" << girl.yz << ",weigh="
<< girl.weight << ",memo=" << girl.memo << endl;
}
}
vector容器
创建一个空的vector
vector<int> v;
创建一个大小为n的数组
vector<int>v(n);
想容器v中尾部追加一个元素a
v.push_back(a);
迭代器
迭代器是访问容器中元素的通用方法。
如果使用迭代器,不同的容器,访问元素的方法是相同的。
迭代器支持的基本操作:赋值(=)、解引用(*)、比较(==和!=)、从左向右遍历(++)
一般情况下,迭代器是指针和移动指针的方法。
迭代器有五种:
- 正向迭代器
只能使用++
运算符来遍历容器,每次沿容器向右移动一个元素。
相关函数:容器名<元素类型>:.iterator 迭代器名;//正向迭代器。 容器名<元素类型>::const_iterator迭代器名;//常正向迭代器。
例如:iterator begin(); const_iterator begin(); const_iterator cbegin();//配合auto使用。 iterator end(); const_iterator end(); const_iterator cend();
#define _CRT_SECUER_NO_WARNINGS #include<iostream> #include<algorithm> #include<cstring> #include<vector> using namespace std; int main() { vector<int>vv = { 1,2,3,4,5 }; vector<int>::iterator it1 = vv.begin(); *it1 = 8;//将修改容器中第0个元素 it1++;//迭代器后移一个元素 *it1 = 7;//将修改容器中第一个元素 for (auto it2 = vv.cbegin();it2 != vv.end();it2++) { cout << *it2 << endl; } cout << endl; for (auto x : vv) { cout << x << endl; } }
- 双向迭代器
具备正向迭代器的功能,还可以反向(从右到左)遍历容器(也是用++
),不管是正向还是反向遍历,都可以用--
让迭代器后退一个元素。容器名<元素类型>::reverse_iterator 迭代器名;//反向迭代器。 容器名<元素类型>::const_reverse_iterator 迭代器名;//常反向迭代器。
- 随机访问迭代器
具备双向迭代器的功能,还支持以下操作:- 用于比较两个迭代器相对位置的关系运算(<、<=、>、>=)。
- 迭代器和一个整数值的加减法运算(+、+=、-、-=)。
- 支持下标运算(iter[n])。
数组的指针是纯天然的随机访问迭代器.
我们来看vector中那些操作需要迭代器:
- 构造函数
#define _CRT_SECUER_NO_WARNINGS #include<iostream> #include<algorithm> #include<cstring> #include<vector> using namespace std; int main() { vector<int> v1 = { 1,2,3,4,5,6,7,8,9,10 }; vector<int> v2(v1.cbegin() + 2, v1.cend() - 3); for (auto x : v2) { cout << x << endl; } }
- 插入函数v.insert(iterator pos,const T& value);
#define _CRT_SECUER_NO_WARNINGS #include<iostream> #include<algorithm> #include<cstring> #include<vector> using namespace std; int main() { vector<int> v = { 1,2,3,4,5,6,7,8,9,10 }; auto iter = v.insert(v.begin() + 5, 13); cout << "新插入的元素是:" << *iter << endl; for (auto x : v) { cout << x << endl; } }
基于范围的for
循环
对于一个有范围的集合来说,在程序代码中指定循环的范围有时候是多余的,还可能犯错误。C++11中引入了基于范围的for循环。
语法:
for(迭代的变量: 迭代的范围)
{
//循环体
}
#define _CRT_SECUER_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
int main() {
vector<int> vv = { 1,2,3,4,5,6,7,8,9,10 };
for (auto it = vv.begin();it != vv.end();it++) {
cout << *it << " ";
}
cout << endl;
for (int x : vv) {
cout << x << " " ;
}
cout << endl;
}
注意:
- 迭代的范围可以是数组名、容器名、初始化列表或者可迭代的对象(支持begin()、 end()、++、==) 。
- 数组名传入函数后,已退化成指针,不能作为容器名。
- 如果容器中的元素是结构体和类,迭代器变量应该申明为引用,加const约束表示只读。
- 注意迭代器失效的问题。
#define _CRT_SECUER_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
class AA {
public:
string m_name;
AA() { cout << "默认构造函数AA()\n"; }
AA(const string& name) : m_name(name) { cout << "构造函数,name=" << m_name << "。\n" ;}
AA(const AA& a) : m_name(a.m_name) { cout<<"拷贝构造函数,name = " <<m_name << "。\n ";}
AA& operator=(const AA& a) {m_name = a.m_name; cout << "赋值函数,n_name=" << m_name << ".\n";}
~AA() { cout << "析构函数,name=" << m_name << "。\n";}
};
int main() {
vector<AA>v;
v.emplace_back("西施");
v.emplace_back("冰冰");
v.emplace_back("幂幂");
for (const auto &a : v) {
cout << a.m_name << endl;
}
cout << endl;
}
list容器
list容器封装了双链表。
包含头文件: #include<list>
list类模板的声明:
template<class T, class Alloc = allocator<T> >
class list{
private:
iterator head;
iterator tail;
.....
}
list的构造函数有很多:
list();
//创建一个空的list容器。list(initializer_list<T> il)
;//使用统一初始化列表。list(const list<T>& v);
//拷贝构造函数。list(Iterator first, Iterator last);
//用迭代器创建list容器。list(list<T>&& v);
//移动构造函数(C++11标准)。
#define _CRT_SECUER_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<list>
using namespace std;
int main() {
//1)list()//创建一个空的list容器
list<int>l1;
cout << "li.size()=" << l1.size() << endl;
// 2)list(initializer_list<T> il);//使用统一初始化列表。
list<int> l2({1,2,3,4,5,6,7,8,9,10 });
//list<int> 12={1,2,3,4,5,6,7,8,9,10 };
//list<int> l2{ 1,2,3,4,5,6,7,8,9,10 };
for (int value : l2)//用基于范围的for循环遍历容器。
cout << value << " ";
cout << endl;
//3)list(const list<T>& v);//拷贝构造函数。
//list<int> l3(12);
list<int> l3 = l2;
for (int value : l3)
cout << value << " ";
cout << endl;
//4)list(Iterator first, Iterator last);//用迭代器创建list容器。
list<int> l4(l2.begin() , l2.end() );//用list容器的迭代器。
for (int value : l4)
cout << value << " ";
cout << endl;
vector < int> v1 = { 1,2,3,4,5,6,7,8,9,10 };//创建vector容器。
list<int> l5(v1.begin() + 2, v1.end() - 3); //用vector容器的迭代器创建list容器。
for (int value : l5)
cout << value << " ";
cout << endl;
int a1[] = {1,2,3,4,5,6,7,8,9,10};//创建数组。
list<int> l6(a1 + 2, a1 + 10 - 3); // 用数组的指针作为迭代器创建list容器。
for(int value : l6)
cout << value << " ";
cout << endl;
}
list的元素操作
T &front();//第一个元素。
const T &front);// 第一个元素,只读。
const T &back();//最后一个元素,只读。
T &back();//最后一个元素。
list的交换,反转,排序,归并
void swap(list<T> &l);//把当前的容器于I交换,交换的是链表节点的地址
void reverse();//反转链表
void sort();//升序排序
void sort(_Pr2_Pred);//排序方法由Pred决定
void merge(list<T> &l)//合并两个已排序的list,
#define _CRT_SECUER_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<list>
using namespace std;
int main() {
list<int> la = { 8,2,6,4,5 };
for (auto& val : la) {
cout << val << " ";
}
cout << endl;
la.reverse();//反转
for (auto& val : la) {
cout << val << " ";
}
cout << endl;
la.sort();//排序
list<int>lb = { 3,7,9,10,1 };
lb.sort();
la.merge(lb);
for (auto& val : la) {
cout << val << " ";
}
cout << endl;
}
插入和删除操作
void push_back(const T& value);
//在链表的尾部追加一个元素。void emplace_back(...);
//在链表的尾部追加一个元素,…用于构造元素。iterator insert(iterator pos, const T& value);
//在指定位置插入一个元素,返回指向插入元素的迭代器。iterator emplace (iterator pos,....);
//在指定位置插入一个元素,…用于构造元素,返回指向插入元素的迭代器。iterator insert(iterator pos, iterator first, iterator last);
//在指定位置插入一个区间的元素,返回指向第一个插入元素的迭代器。void pop_back();
//从链表尾部删除一个元素。iterator erase(iterator pos);
//删除指定位置的元素,返回下一个有效的迭代器。iterator erase(iterator first, iterator last);
//删除指定区间的元素,返回下一个有效的迭代器。push_front(const T& value);
//在链表的头部插入一个元素。emplace_front(...);
//在链表的头部插入一个元素,.….用于构造元素。splice(iterator pos,const vector<T> &l);
//把另一个链表连接到当前链表。splice(iterator pos, const vector<T>&l, iterator first, iterator last);
//把另一个链表指定的区间连接到当前链表。splice(iterator pos, const vector<T> & l, iterator first);
//把另一个链表从first开始的结点连接到当前链表。void remove(value);
//删除链表中所有等于value的元素。void remove_if(_Pr1 _Pred);
//删除链表中满足条件的元素,参数_Pred是一元函数。void unique();
//删除链表中相邻的重复元素,只保留一个。
pair键值对
pair是类模板,一般用于表示 key/value
数据,其实现是结构体。pair结构模板的定义如下:
template <class T1, class T2>
struct pair
{
T1 first;//第一个成员,一般表示 key。
T2 second;//第二个成员,一般表value。
pair();//默认构造函数。
pair(const T1 &val1,const T2 &val2);//有两个参数的构造函数。
pair(const pair<T1,T2> &p);//拷贝构造函数。
void swap(pair<T1,T2> &p);//交换两个pair。
}
#define _CRT_SECUER_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<list>
using namespace std;
int main() {
pair<int, string>p0;
cout << "p0 first=" << p0.first << ",second=" << p0.second << endl;
pair<int, string>p1(1,"西施");
cout << "p1 first=" << p1.first << ",second=" << p1.second << endl;
struct st_girl {
string name;
int age;
double height;
};
pair<int, st_girl>p = { 3,{"西施",23,48.6} };
cout << "p first=" << p.first << endl;
cout << "p second.name=" << p.second.name << endl;cout << "p second.age=" << p.second.age << endl;
cout << "p second.height=" << p.second.height << endl;
}
make_pair
函数模板的定义如下:
map容器
map容器封装了红黑树(平衡二叉排序树),用于查找。
包含头文件: #include<map>
map容器的元素是pair 键值对。
map类模板的声明:
template <class K, class V, class P = less<K>, class _Alloc = allocator<pair<const K,V >>>
class map : public _Tree<_Tmap_traits<K, V,P,_Alloc, false> >
{
....
}
第一个模板参数K: key的数据类型(pair.first)。
第二个模板参数V: value的数据类型(pair.second)。
第三个模板参数Р:排序方法,缺省按key升序。
第四个模板参数_Alloc:分配器,缺省用new和delete。
map提供了双向迭代器。
二叉链表:
struct BTNode
{
pair<K,V> p;//键值对。
BTNode *parent;//父节点。
BTNode *Ichirld;//左子树。
BTNode *rchild;//右子树。
};
- 构造函数
注意对map容器正向遍历一定会得到一个有序的数列.因为红黑树是二叉排序树.map(); //创建一个空的map容器。 map(initializer_list<pair<K,V> > il); //使用统一初始化列表。 map(const map<K,V>& m);//拷贝构造函数。 map(Iterator first, Iterator last);//用迭代器创建map容器。 map(map<K,V>&& m);!/移动构造函数(C++11标准)。
#define _CRT_SECUER_NO_WARNINGS #include<iostream> #include<algorithm> #include<cstring> #include<vector> #include<list> #include<map> using namespace std; int main() { //1)map();//创建一个空的map map<int, string>m1; // 2) map(initializer_list<pair<K, V>> il);//使用统一初始化列表。 map<int, string> m2({ {8,"冰冰"},{ 3,"西施"},{1,"幂幂"},{7,"金莲"},{5, "西瓜"} }); //map<int, string> m2 = { {8,"冰冰"},{ 3,"西施" },{ 1,"幂幂" },{7, "金莲" },{5,"西瓜"} }; //map<int, string> m2{ {8,"冰冰" },{ 3,"西施" },{1,"幂幂" },{7, "金莲" },{5,"西瓜" } }; for (auto& val : m2) { cout << val.first << "," << val.second << " "; } cout << endl; // 3) map(const map<K, V>&m);//拷贝构造函数。 map<int, string> m3 = m2; for (auto& val : m3) cout << val.first << "," << val.second << " "; cout << endl; //4) map(Iterator first, Iterator last);//用迭代器创建map容器。 auto first = m3.begin(); first++; auto last = m3.end(); last--; map<int, string> m4(first, last); for (auto& val : m4) cout << val.first << "," << val.second << " "; cout << endl; }
- 插入操作
#define _CRT_SECUER_NO_WARNINGS #include<iostream> #include<algorithm> #include<cstring> #include<vector> #include<list> #include<map> using namespace std; int main() { map<int, string>m; m.insert({ {8,"冰冰"}, {3,"西施"} }); m.insert({ pair<int,string>(1,"幂幂"),make_pair<int,string>(7,"金莲"),{5,"西瓜"} }); m.insert({ {18,"冰冰"},{3,"西施"} }); for (auto& val : m) cout << val.first << "," << val.second << " "; cout << endl; }
哈希表
unordered_map容器
queue
queue容器的逻辑结构是队列,物理结构可以是数组或链表,主要用于多线程之间的数据共享。
包含头文件: #include<queue>
queue类模板的声明:
template <class T, class _Container = deque<T>> class queue{
....
}
第一个模板参数T:元素的数据类型。
第二个模板参数_Container:底层容器,缺省是std::deque。
queue容器不支持迭代器。