本质
string是C++风格的字符串,而string本质上是一个类
string与char* 的区别
char * 是一个指针
string是一个类,类内部封装了char*,管理这个字符串,是一个char*型的容器。
构造函数
string();
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//创建一个空的字符串 例如: string s;
string s1; //创建空字符串,调用无参构造函数
string(const char* s);
? ? ? ? ?//使用字符串s初始化
const char* str = "hello world";
string s2(str); //把c_string转换成了string
string(const string& str);
//使用一个string对象初始化另一个string对象
string s2 = "KKGG";
string s3(s2); //调用拷贝构造函数
string(int n, char c);
? ? ? ? //使用n个字符c初始化
string str(5, 'a'); //aaaaa
1、string字符串的赋值操作
string& operator=(const char* s);
//char*类型字符串 赋值给当前的字符串
string str1;
str1 = "kk";
string& operator=(const string &s);
//把字符串s赋给当前的字符串
string str1 = "gg";
string str2;
str2 = str1;
string& operator=(char c);
//字符赋值给当前的字符串
string str3;
str3 = 'KG';
string& assign(const char *s);
//把字符串s赋给当前的字符串
string str4;
str4.assign("hello, this is my world");
string& assign(const char *s, int n);
//把字符串s的前n个字符赋给当前的字符串
string str5;
str5.assign("hello c++",5); //str5 = "hello"
string& assign(const string &s);
//把字符串s赋给当前字符串
string str6;
str6.assign(str5);
string& assign(int n, char c);
//用n个字符c赋给当前字符串
string str7;
str7.assign(5, 'k'); //str7 = "kkkkk"
2、string字符串的拼接
string& operator+=(const char* str);
//重载+=操作符
string& operator+=(const string& str);
//重载+=操作符
string str1 = "我喜欢";
str1 += "写博客";
//str1 = "我喜欢写博客"
string& operator+=(const char c);
//重载+=操作符
string str1 = "我喜欢";
string str2 = "写博客";
str1 += str2;
//str1 = "我喜欢写博客"
string& append(const char *s);
//把字符串s连接到当前字符串结尾
string str = "I";
str.append(" love");
//str = "I love"
string& append(const char *s, int n);
//把字符串s的前n个字符连接到当前字符串结尾
string str = "I ";
str.append("love myself",4);
//str = "I love"
string& append(const string &s);
//同operator+=(const string& str)
string s1 = "kk";
string s2 = "gg";
s1.append(s2);
//s1 = "kkgg"
string& append(const string &s, int pos, int n);
//字符串s中从pos开始的n个字符连接到字符串结尾
string str1;
string str2 = "abcdefg";
str1.append(str2, 4, 3); //efg
//从下标4位置开始 ,截取3个字符,拼接到字符串末尾
3、string字符串的查找和替换
int find(const string& str, int pos);
//查找str第一次出现位置,从pos开始查找
int find(const char* s, int pos);
//查找s第一次出现位置,从pos开始查找
int find(const char* s, int pos, int n);
//从pos位置查找s的前n个字符第一次位置
int find(const char c, int pos);
//查找字符c第一次出现位置
void test(){
//查找
string str1 = "abcdefgde";
int pos = str1.find("de");
if (pos == -1){
cout << "未找到" << endl;
}
else{
cout << "pos = " << pos << endl;
}
}
int rfind(const string& str, int pos);
//查找str最后一次位置,从pos开始查找
int rfind(const char* s, int pos);
//查找s最后一次出现位置,从pos开始查找
int rfind(const char* s, int pos, int n);
//从pos查找s的前n个字符最后一次位置
int rfind(const char c, int pos);
//查找字符c最后一次出现位置
void test(){
//查找
string str1 = "abcdefgde";
int pos = str1.rfind("de");
cout << "pos = " << pos << endl;
//pos = 7
}
string& replace(int pos, int n, const string& str);
//替换从pos开始n个字符为字符串str
string& replace(int pos, int n,const char* s);
//替换从pos开始的n个字符为字符串s
void test(){
//替换
string str1 = "abcdefgde";
str1.replace(1, 3, "1111");
cout << "str1 = " << str1 << endl;
//str1 = "a1111efgde"
}
4、string字符串的比较
int compare(const string &s) const;
//与字符串s比较
int compare(const char *s) const;
//与字符串s比较
void test(){
string s1 = "hello";
string s2 = "aello";
int ret = s1.compare(s2); //字符串比较
if (ret == 0) {
cout << "s1 等于 s2" << endl;
}
else if (ret > 0){
cout << "s1 大于 s2" << endl;
}
else{
cout << "s1 小于 s2" << endl;
}
}
5、string字符串的存取
char& operator[](int n);
//通过[]方式取字符
char& at(int n);
//通过at方法获取字符
void test(){
string str = "hello world";
for (int i = 0; i < str.size(); i++){
cout << str[i] << " ";
}
cout << endl;
for (int i = 0; i < str.size(); i++){
cout << str.at(i) << " ";
}
cout << endl;
//字符修改
str[0] = 'x';
str.at(1) = 'x';
cout << str << endl;
}
6、string字符串的插入和删除
总结:插入和删除的起始下标都是从0开始
string& insert(int pos, const char* s);
//插入字符串string& insert(int pos, const string& str);
//插入字符串
string& insert(int pos, int n, char c);
//在指定位置插入n个字符c
//字符串插入
void test(){
string str = "hello";
str.insert(1, "***");
cout << str << endl;
//str = "h***ello"
}
string& erase(int pos, int n = npos);
//删除从Pos开始的n个字符
//字符串删除
void test(){
string str = "hello";
str.erase(1, 3);
//从1号位置开始3个字符
cout << str << endl;
//str = "ho"
}
7、string字符串的子串
string substr(int pos, int n);
//返回由pos开始的n个字符组成的字符串
//子串
void test(){
string str = "abcdefg";
string subStr = str.substr(1, 3);
cout << "subStr = " << subStr << endl;
//subStr = "bcd";
}
1、vector数据结构和数组非常相似,也称为单端数组
2、不同之处在于数组是静态空间,而vector可以动态扩展
构造函数
vector<T> v;
//采用模板实现类实现,默认构造函数
vector<int> v; //无参构造
vector(v.begin(), v.end());
//将v[begin(), end())区间中的元素拷贝给本身
void test(){
vector<int> v1;
for (int i = 0; i < 10; i++){
v1.push_back(i);
}
vector<int> v2(v1.begin(), v1.end());
}
vector(n, elem);
//构造函数将n个elem拷贝给本身
vector<int> v(10, 100);
vector(const vector &vec);
//拷贝构造函数
vector<int> v3(10, 100);
vector<int> v4(v3);
vector赋值操作
vector& operator=(const vector &vec);
//重载等号操作符
void test(){
vector<int> v1; //无参构造
for (int i = 0; i < 10; i++){
v1.push_back(i);
}
vector<int>v2;
v2 = v1;
}
assign(beg, end);
//将[beg, end)区间中的数据拷贝赋值给本身
assign(n, elem);
//将n个elem拷贝赋值给本身
vector<int>v3;
v3.assign(v1.begin(), v1.end());
vector<int>v4;
v4.assign(10, 100);
vector容量和大小
empty();
//判断容器是否为空
capacity();
//容器的容量
size();
//返回容器中元素的个数
void test(){
vector<int> v1;
for (int i = 0; i < 10; i++){
v1.push_back(i);
}
if (v1.empty()){
cout << "v1为空" << endl;
}
else{
cout << "v1不为空" << endl;
cout << "v1的容量 = " << v1.capacity() << endl;
cout << "v1的大小 = " << v1.size() << endl;
}
//v1不为空
//v1的容量 = 13
//v1的大小 = 10
}
resize(int num);
//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。????????????????????????????????//如果容器变短,则末尾超出容器长度的元素被删除。
resize(int n,elem);
//重新指定容器长度为n,若容器变长,则以elem值填充新位置。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??//如果容器变短,则末尾超出容器长度的元素被删除
vector插入和删除
push_back(ele);
//尾部插入元素ele
pop_back();
//删除最后一个元素
insert(const_iterator pos, ele);
//迭代器指向位置pos插入元素ele
insert(const_iterator pos, int count,ele);
//迭代器指向位置pos插入count个元素ele
erase(const_iterator pos);
//删除迭代器指向的元素
erase(const_iterator start, const_iterator end);
//删除迭代器从start到end之间的元素
clear();
//删除容器中所有元素
//插入和删除
void test(){
vector<int> v1;
//尾插
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
v1.push_back(40);
v1.push_back(50);
//尾删
v1.pop_back();
//插入
v1.insert(v1.begin(), 100);
v1.insert(v1.begin(), 2, 1000);
//删除
v1.erase(v1.begin());
//清空
v1.erase(v1.begin(), v1.end());
v1.clear();
}
vector数据存取
at(int idx);
//返回索引idx所指的数据
operator[];
//返回索引idx所指的数据
front();
//返回容器中第一个数据元素
back();
//返回容器中最后一个数据元素
void test(){
vector<int>v1;
for (int i = 0; i < 10; i++){
v1.push_back(i);
}
for (int i = 0; i < v1.size(); i++){
cout << v1[i] << " ";
}
cout << endl;
for (int i = 0; i < v1.size(); i++){
cout << v1.at(i) << " ";
}
cout << endl;
cout << "v1的第一个元素为: " << v1.front() << endl;
cout << "v1的最后一个元素为: " << v1.back() << endl;
}
vector互换容器
swap(vec);
// 将vec与本身的元素互换
v1.swap(v2);
vector预留空间
reserve(int len);
//容器预留len个元素长度,预留位置不初始化,元素不可访问
vector<int> v;
v.reserve(100000);//预留空间
双端数组,可以对头端进行插入删除操作。
deque与vector的区别
(1)vector对于头部的插入删除效率低,数据量越大,效率越低
(2)deque相对而言,对头部的插入删除速度回比vector快
(3)vector访问元素时的速度会比deque快,这和两者内部实现有关
构造函数
deque<T>
; //默认构造形式
deque(beg, end);
//构造函数将[beg, end)区间中的元素拷贝给本身
deque(n, elem);
//构造函数将n个elem拷贝给本身
deque(const deque &deq);
//拷贝构造函数
//deque构造
void test{
deque<int> d1; //无参构造函数
for (int i = 0; i < 10; i++){
d1.push_back(i);
}
deque<int> d2(d1.begin(),d1.end());
deque<int>d3(10,100);
deque<int>d4 = d3;
}
deque赋值操作
deque& operator=(const deque &deq);
//重载等号操作符
assign(beg, end);
//将[beg, end)区间中的数据拷贝赋值给本身
assign(n, elem);
//将n个elem拷贝赋值给本身
//赋值操作
void test(){
deque<int> d1;
for (int i = 0; i < 10; i++){
d1.push_back(i);
}
//d1 = 0 1 2 3 4 5 6 7 8 9
deque<int>d2;
d2 = d1;
//d2 = 0 1 2 3 4 5 6 7 8 9
deque<int>d3;
d3.assign(d1.begin(), d1.end());
//d3 = 0 1 2 3 4 5 6 7 8 9
deque<int>d4;
d4.assign(5, 100);
//d4 = 100 100 100 100 100
}
deque大小操作
deque.empty();
//判断容器是否为空
deque.size();
? ?//返回容器中元素的个数
deque.resize(num);
//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。???????????????????????????????????//如果容器变短,则末尾超出容器长度的元素被删除。
deque.resize(num, elem);
//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。???????????????????????????????????//如果容器变短,则末尾超出容器长度的元素被删除。
注意:deque没有容量的概念
void test(){
deque<int> d1;
for (int i = 0; i < 10; i++){
d1.push_back(i);
}
//判断容器是否为空
if (d1.empty()) {
cout << "d1为空!" << endl;
}
else {
cout << "d1不为空!" << endl;
//统计大小
cout << "d1的大小为:" << d1.size() << endl;
}
//重新指定大小
d1.resize(15, 1);//多余的部分用1填充
d1.resize(5);
}
deque插入和删除
两端插入操作:
push_back(elem);
//在容器尾部添加一个数据
push_front(elem);
//在容器头部插入一个数据
pop_back();
//删除容器最后一个数据
pop_front();
//删除容器第一个数据
void test(){
deque<int> d;
//尾插
d.push_back(10);
d.push_back(20); //10 20
//头插
d.push_front(100);
d.push_front(200); //200 100 10 20
//尾删
d.pop_back(); //200 100 10
//头删
d.pop_front();//100 10
}
?指定位置操作
insert(pos,elem);
//在pos位置插入一个elem元素的拷贝,返回新数据的位置
insert(pos,n,elem);
//在pos位置插入n个elem数据,无返回值
insert(pos,beg,end);
//在pos位置插入[beg,end)区间的数据,无返回值
void test(){
deque<int> d;
d.push_back(10);
d.push_back(20);
d.push_front(1);
d.push_front(2);
//2 1 10 20
d.insert(d.begin(), 100);
//100 2 1 10 20
d.insert(d.begin(), 2,1000);
//1000 1000 100 2 1 10 20
}
clear();
//清空容器的所有数据
erase(beg,end);
//删除[beg,end)区间的数据,返回下一个数据的位置
erase(pos);
//删除pos位置的数据,返回下一个数据的位置
//删除
void test03(){
deque<int> d;
d.push_back(10);
d.push_back(20);
d.push_front(1);
d.push_front(2);
//2 1 10 20
d.erase(d.begin());
//1 10 20
d.erase(d.begin(), d.end());
//
d.clear();
//
}
deque数据存取
at(int idx);
//返回索引idx所指的数据
operator[];
//返回索引idx所指的数据
front();
//返回容器中第一个数据元素
back();
//返回容器中最后一个数据元素
void test(){
deque<int> d;
d.push_back(10);
d.push_back(20);
d.push_front(1);
d.push_front(2);
for (int i = 0; i < d.size(); i++) {
cout << d[i] << " ";//2 1 10 20
}
cout << endl;
for (int i = 0; i < d.size(); i++) {
cout << d.at(i) << " ";//2 1 10 20
}
cout << endl;
cout << "front:" << d.front() << endl;
//2
cout << "back:" << d.back() << endl;
//20
}
deque排序
sort(iterator beg, iterator end)
//对beg和end区间内元素进行排序
void test{
deque<int> d;
d.push_back(10);
d.push_back(20);
d.push_front(1);
d.push_front(2);
sort(d.begin(), d.end());
//1 2 10 20
}
概念:stack是一种先进后出(或后进先出)的数据结构,它只有一个出口。
stack<T> stk;
//stack采用模板类实现, stack对象的默认构造形式
stack(const stack &stk);
//拷贝构造函数
赋值操作:
stack& operator=(const stack &stk);
//重载等号操作符数据存取:
push(elem);
//向栈顶添加元素
pop();
//从栈顶移除第一个元素
top();
//返回栈顶元素大小操作:
empty();
//判断堆栈是否为空
size();
//返回栈的大小
void test(){
//创建栈容器 栈容器必须符合先进后出
stack<int> s;
//向栈中添加元素,叫做 压栈 入栈
s.push(10);
s.push(20);
s.push(30);
while (!s.empty()) {
//输出栈顶元素
cout << s.top() << endl; //30
//弹出栈顶元素
s.pop();
}
cout << "栈的大小为:" << s.size() << endl;//2
}
概念:队列是一种先进先出的数据结构,它有两个出口。
队列容器允许从一端新增元素,从另一端移除元素。
队列中只有队头和队尾才可以被外界使用,因此队列不允许有遍历行。
queue<T> q;
//queue采用模板类实现,queue对象的默认构造形式
queue(const queue &que);
//拷贝构造函数
赋值操作:
queue& operator=(const queue &que);
//重载等号操作符数据存取:
push(elem);
//往队尾添加元素
pop();
//从队头移除第一个元素
back();
//返回最后一个元素
front();
//返回第一个元素大小操作:
empty();
//判断堆栈是否为空
size();
//返回栈的大小
链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的。
链表的组成:链表由一系列结点组成。
结点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
构造函数
list<T> li;
//list采用采用模板类实现,对象的默认构造形式
list(beg,end);
//构造函数将[beg, end)区间中的元素拷贝给本身
list(n,elem);
//构造函数将n个elem拷贝给本身
list(const list &li);
//拷贝构造函数
void test(){
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
list<int>L2(L1.begin(),L1.end());
list<int>L3(L2);
list<int>L4(10, 1000);
}
list赋值和交换
assign(beg, end);
//将[beg, end)区间中的数据拷贝赋值给本身
assign(n, elem);
//将n个elem拷贝赋值给本身
list& operator=(const list &lst);
//重载等号操作符
//赋值
void test(){
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
//赋值
list<int>L2;
L2 = L1;
list<int>L3;
L3.assign(L2.begin(), L2.end());
list<int>L4;
L4.assign(10, 100);
}
swap(lst);
//将lst与本身的元素互换
//交换
void test(){
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
list<int>L2;
L2.assign(4, 1);
//L1 =10 20 30 40
//L2 = 1 1 1 1
L1.swap(L2);
//L1 = 1 1 1 1
//L2 =10 20 30 40
}
list大小操作
size();
//返回容器中元素的个数
empty();
//判断容器是否为空
resize(num);
//重新指定容器的长度为num,若容器变长,则以默认值填充新位置????????????????????????//如果容器变短,则末尾超出容器长度的元素被删除
resize(num, elem);
//重新指定容器的长度为num,若容器变长,则以elem值填充新位置? ????????????????????????????????//如果容器变短,则末尾超出容器长度的元素被删除
//大小操作
void test(){
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
if (L1.empty()){
cout << "L1为空" << endl;
}
else{
cout << "L1不为空" << endl;
cout << "L1的大小为: " << L1.size() << endl;//4
}
//重新指定大小
L1.resize(10);
L1.resize(2);
}
list插入和删除
push_back(elem);//在容器尾部加入一个元素
pop_back();//删除容器中最后一个元素
push_front(elem);//在容器开头插入一个元素
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值匹配的元素。
void test(){
list<int> L;
//尾插
L.push_back(10);
L.push_back(20);
L.push_back(30);
//头插
L.push_front(100);
L.push_front(200);
L.push_front(300);
//尾删
L.pop_back();
//头删
L.pop_front();
//插入
list<int>::iterator it = L.begin();
L.insert(++it, 1000);
//删除
it = L.begin();
L.erase(++it);
//移除
L.push_back(10000);
L.push_back(10000);
L.push_back(10000);
L.remove(10000);
//清空
L.clear();
}
list数据存取
front();
//返回第一个元素
back();
//返回最后一个元素
//数据存取
void test(){
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
//cout << L1.at(0) << endl;//错误 不支持at访问数据
//cout << L1[0] << endl; //错误 不支持[]方式访问数据
cout << "第一个元素为: " << L1.front() << endl;
cout << "最后一个元素为: " << L1.back() << endl;
//list容器的迭代器是双向迭代器,不支持随机访问
list<int>::iterator it = L1.begin();
//it = it + 1;//错误,不可以跳跃访问,即使是+1
}
list反转和排序
reverse();
//反转链表
sort();
//链表排序
//反转和排序
void test(){
list<int> L;
L.push_back(90);
L.push_back(30);
L.push_back(20);
L.push_back(70);
//90 30 20 70
//反转容器的元素
L.reverse();
//70 20 30 90
//排序
L.sort(); //默认的排序规则 从小到大
//20 30 70 90
L.sort(greater<int>()); //指定规则,从大到小
//90 70 30 20
}
例题:创建一个链表,实现前n个数的旋转。
例如:1 2 3 4 5 6,实现前3个数的旋转变成4 5 6 1 2 3
int main(){
list<int> li;
li.push_back(10);
li.push_back(20);
li.push_back(30);
li.push_back(40);
li.push_back(50); //初始化5个数据
int n = 0;
cin >> n; //选择翻转几个数
list<int>::iterator it = li.begin();
for (int i = 0; i < n; i++){ //使用迭代器遍历到翻转的位置
it++;
}
reverse(li.begin(),it); //逆置前 n 个数
reverse(it, li.end()); //逆置后 li.size() - n 个数
reverse(li.begin(), li.end());//整体逆置
return 0;
}
所有元素都会在插入时自动被排序。
set/multiset属于关联式容器,底层结构是用二叉树实现。
set和multiset区别:
(1)set不允许容器中有重复的元素。
(2)multiset允许容器中有重复的元素。
构造函数
set<T> st;
//默认构造函数
set(const set &st);
//拷贝构造函数
//构造和赋值
void test(){
set<int> s1;
s1.insert(10);
s1.insert(30);
s1.insert(20);
s1.insert(40);
//拷贝构造
set<int>s2(s1);
//赋值
set<int>s3;
s3 = s2;
}
set大小和交换
size();
//返回容器中元素的数目
empty();
//判断容器是否为空
swap(st);
//交换两个集合容器
void test(){
set<int> s1;
s1.insert(10);
s1.insert(30);
s1.insert(20);
s1.insert(40);
if (s1.empty()){
cout << "s1为空" << endl;
}
else{
cout << "s1不为空" << endl;
cout << "s1的大小为: " << s1.size() << endl;//4
}
set<int> s2;
s2.insert(100);
s2.insert(300);
s2.insert(200);
s2.insert(400);
s1.swap(s2);
}
set插入和删除
insert(elem);
//在容器中插入元素。
clear();
//清除所有元素。
erase(pos);
//删除pos迭代器所指的元素,返回下一个元素的迭代器。
erase(beg, end);
//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
erase(elem);
//删除容器中值为elem的元素。
//插入和删除
void test(){
set<int> s1;
//插入
s1.insert(10);
s1.insert(30);
s1.insert(20);
s1.insert(40);
printSet(s1);
//删除
s1.erase(s1.begin());
s1.erase(30);
//清空
//s1.erase(s1.begin(), s1.end());
s1.clear();
}
set查找和统计
find(key);
//查找key是否存在,若存在,返回该键的元素的迭代器;??????????????????????????????????????????????????若不存在,返回set.end();
count(key);
//统计key的元素个数
//查找和统计
void test(){
set<int> s1;
//插入
s1.insert(10);
s1.insert(30);
s1.insert(20);
s1.insert(40);
//查找
set<int>::iterator pos = s1.find(30);
if (pos != s1.end()){
cout << "找到了元素 : " << *pos << endl;
}
else{
cout << "未找到元素" << endl;
}
//统计
int num = s1.count(30);
cout << "num = " << num << endl;
}
set和multiset的区别
set不可以插入重复数据,而multiset可以。
set插入数据的同时会返回插入结果,表示插入是否成功。
multiset不会检测数据,因此可以插入重复数据。
//set和multiset区别
void test(){
set<int> s;
pair<set<int>::iterator, bool> ret = s.insert(10);
if (ret.second) {
cout << "第一次插入成功!" << endl;
}
else {
cout << "第一次插入失败!" << endl;
}
ret = s.insert(10);
if (ret.second) {
cout << "第二次插入成功!" << endl;
}
else {
cout << "第二次插入失败!" << endl;
}
//multiset
multiset<int> ms;
ms.insert(10);
ms.insert(10);
for (multiset<int>::iterator it = ms.begin(); it != ms.end(); it++) {
cout << *it << " ";
}
}
set容器排序
主要技术点:利用仿函数,可以改变排序规则。
class MyCompare
{
public:
bool operator()(int v1, int v2) {
return v1 > v2;
}
};
void test(){
set<int> s1;
s1.insert(10);
s1.insert(40);
s1.insert(20);
s1.insert(30);
s1.insert(50);
//默认从小到大
for (set<int>::iterator it = s1.begin(); it != s1.end(); it++) {
cout << *it << " ";
}
cout << endl;
//指定排序规则
set<int,MyCompare> s2;
s2.insert(10);
s2.insert(40);
s2.insert(20);
s2.insert(30);
s2.insert(50);
for (set<int, MyCompare>::iterator it = s2.begin(); it != s2.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
pair队组创建
pair<type, type> p (value1, value2);
pair<type, type> p = make_pair(value1, value2);
//对组创建
void test(){
pair<string, int> p(string("Tom"), 20);
cout << "姓名: " << p.first << " 年龄: " << p.second << endl;
pair<string, int> p2 = make_pair("Jerry", 10);
cout << "姓名: " << p2.first << " 年龄: " << p2.second << endl;
}
map中所有元素都是pair。
pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)。
所有元素都会根据元素的键值自动排序。
本质:map/multimap属于关联式容器,底层结构是用二叉树实现。
map和multimap区别:
(1)map不允许容器中有重复key值元素
(2)multimap允许容器中有重复key值元素
map<T1, T2> mp;
//map默认构造函数
map(const map &mp);
//拷贝构造函数
map& operator=(const map &mp);
//重载等号操作符
void test(){
map<int,int>m; //默认构造
m.insert(pair<int, int>(1, 10));
m.insert(pair<int, int>(2, 20));
m.insert(pair<int, int>(3, 30));
map<int, int>m2(m); //拷贝构造
map<int, int>m3;
m3 = m2; //赋值
}
map大小和交换
size();
//返回容器中元素的数目
empty();
//判断容器是否为空
swap(st);
//交换两个集合容器
//交换
void test(){
map<int, int>m;
m.insert(pair<int, int>(1, 10));
m.insert(pair<int, int>(2, 20));
m.insert(pair<int, int>(3, 30));
map<int, int>m2;
m2.insert(pair<int, int>(4, 100));
m2.insert(pair<int, int>(5, 200));
m2.insert(pair<int, int>(6, 300));
m.swap(m2);
}
map插入和删除
insert(elem);
//在容器中插入元素
clear();
//清除所有元素
erase(pos);
//删除pos迭代器所指的元素,返回下一个元素的迭代器
erase(beg, end);
//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器
erase(key);
//删除容器中值为key的元素
void test(){
//插入
map<int, int> m;
//第一种插入方式
m.insert(pair<int, int>(1, 10));
//第二种插入方式
m.insert(make_pair(2, 20));
//第三种插入方式
m.insert(map<int, int>::value_type(3, 30));
//第四种插入方式
m[4] = 40;
//删除
m.erase(m.begin());
m.erase(3);//删除key为3
//清空
m.erase(m.begin(),m.end());
m.clear();
}
map查找和统计
find(key);
//查找key是否存在,若存在,返回该键的元素的迭代器? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 若不存在,返回set.end()
count(key);
//统计key的元素个数
//查找和统计
void test(){
map<int, int>m;
m.insert(pair<int, int>(1, 10));
m.insert(pair<int, int>(2, 20));
m.insert(pair<int, int>(3, 30));
//查找
map<int, int>::iterator pos = m.find(3);
if (pos != m.end()){
cout << "找到了元素 key = " << (*pos).first << " value = " << (*pos).second << endl;
}
else{
cout << "未找到元素" << endl;
}
//统计
int num = m.count(3);
cout << "num = " << num << endl;
}
map容器排序
利用仿函数可以指定map容器的排序规则。
对于自定义数据类型,map必须要指定排序规则,同set容器。
class MyCompare {
public:
bool operator()(int v1, int v2) {
return v1 > v2;
}
};
void test() {
//默认从小到大排序
//利用仿函数实现从大到小排序
map<int, int, MyCompare> m;
m.insert(make_pair(1, 10));
m.insert(make_pair(2, 20));
m.insert(make_pair(3, 30));
m.insert(make_pair(4, 40));
m.insert(make_pair(5, 50));
for (map<int, int, MyCompare>::iterator it = m.begin(); it != m.end(); it++) {
cout << "key:" << it->first << " value:" << it->second << endl;
}
}
?例题:随机输入n个数,找到所有出现重复的数。
例如:输入2,3,1,0,2,5,3? 输出2,3
int test(){
multimap<int,int> m;
int n = 0;
cin >> n;
for (int i = 0; i < n; i++){
int t = 0;
cin >> t;
m.insert(pair<int, int>(t, m.count(t) + 1));
}
for (multimap<int, int>::iterator it = m.begin(); it != m.end(); it++){
if (m.count(it->second) > 1){
cout << it->first << " ";
}
}
}
其他内容推荐: