常用的部分函数
begin | 得到指向字符串开头的Iterator |
end |
得到指向字符串结尾的Iterator |
rbegin |
得到指向反向字符串开头的Iterator |
rend |
得到指向反向字符串结尾的Iterator |
size |
得到字符串的大小 |
length | 和size函数功能相同 |
max_size | 字符串可能的最大大小 |
empty | 判断是否为空 |
operator[] | 取第几个元素,相当于数组 |
c_str | 取得C风格的const char* 字符串 |
data | 取得字符串内容地址 |
operator= | 赋值操作符 |
reserve | 预留空间 |
swap | 交换函数 |
insert | 插入字符 |
append | 追加字符 |
push_back | 追加字符 |
operator+= += | 操作符 |
erase | 删除字符串 |
clear |
清空字符容器中所有内容 |
resize | 重新分配空间 |
assign | 和赋值操作符一样 |
replace | 替代 |
copy | 字符串到空间 |
find |
查找 |
rfind | 反向查找 |
find_first_of | 查找包含子串中的任何字符,返回第一个位置 |
find_first_not_of | 查找不包含子串中的任何字符,返回第一个位置 |
find_last_of | 查找包含子串中的任何字符,返回最后一个位置 |
find_last_not_of | 查找不包含子串中的任何字符,返回最后一个位置 |
substr | 得到字串 |
compare | 比较字符串 |
operator+ | 字符串链接 |
operator== | 判断是否相等 |
operator!= | 判断是否不等于 |
operator< | 判断是否小于 |
operator>> | 从输入流中读入字符串 |
operator<< | 字符串写入输出流 |
getline | 从输入流中读入一行 |
录入:
想要包括空格一起录进来
getline(cin,s);
如果在录入字符串之前有录进去‘\n’ 那就得小心了
回车换行会存在 缓存区内导致只录进去了一个回车换行
cin.get();
getline(cin,s);
这样回车换行就不会被读入了
插入:
#include
#include
using namespace std;
int main()
{
string s;
s="qq1048375125";
s.insert(s.find("1"),"haha");
cout<
运行结果:qqhaha1048375125
插入是在position的前面插入
删除:
#include
#include
using namespace std;
int main()
{
string s;
s="qq1048375125";
s.erase(0,3);
cout<
运行结果:1048375125
s.erase(int begin,int len);
删除这段区间[begin,len);
包括begin,长度len;
如果没写end参数
查找:
s.find(str);
从前面往后找
返回第一个匹配的的下标
s.rfind(str);
从后往前找
如果查找不成功返回 string::string::npos 也就是 -1
一般情况下写成if(s.find(str)!=-1) 也行;
1.string类重载运算符operator>>用于输入,同样重载运算符operator<<用于输出操作
string str1;
cin >> str1;//当用cin>>进行字符串的输入的时候,遇到空格的地方就停止字符串的读取输入
cout << str1 << endl;
cin.get();//这个的作用就是读取cin>>输入的结束符,不用对getline的输入产生影响!
getline(cin, str1);//字符串的行输入
cout << str1 << endl;
2.string类的构造函数
string str2 = "aaaaa";//最简单的字符串初始化
cout << str2 << endl;
char *s = "bbbbb";
string str3(s);//用c类型字符串s初始化
cout << str3 << endl;
char ch = 'c';
string str4(5, ch);//用n个字符ch初始化
cout << str4 << endl;
3.string类的字符操作
string str5 = "abcde";
ch = str5[3];//operator[]返回当前字符串中第n个字符的位置
cout << ch << endl;
string str6 = "abcde";
ch = str6.at(4);//at()返回当前字符串中第n个字符的位置,并且提供范围检查,当越界时会抛出异常!
cout << ch << endl;
//4.string的特性描述
string str7 = "abcdefgh";
int size;
size = str7.capacity();//返回当前容量
cout << size << endl;
size = str7.max_size();//返回string对象中可存放的最大字符串的长度
cout << size << endl;
size = str7.size();//返回当前字符串的大小
cout << size << endl;
size = str7.length();//返回当前字符串的长度
cout << size << endl;
bool flag;
flag = str7.empty();//判断当前字符串是否为空
cout << flag << endl;
int len = 10;
str7.resize(len, ch);//把字符串当前大小置为len,并用字符ch填充不足的部分
cout << str7 << endl;
//5.string的赋值
string str8;
str8 = str7;//把字符串str7赋给当前字符串
cout << str8 << endl;
str8.assign(str7);//把字符串str7赋给当前字符串
cout << str8 << endl;
str8.assign(s);//用c类型字符串s赋值
cout << str8 << endl;
str8.assign(s, 2);//用c类型字符串s开始的n个字符赋值
cout << str8 << endl;
str8.assign(len, ch);//用len个字符ch赋值给当前字符串
cout << str8 << endl;
str8.assign(str7, 0, 3);//把字符串str7中从0开始的3个字符赋给当前字符串
cout << str8 << endl;
string str9 = "0123456789";
str8.assign(str9.begin(), str9.end());//把迭代器之间的字符赋给字符串
cout << str8 << endl;
//6.string的连接
string str10;
str10 += str9;//把字符串str9连接到当前字符串的结尾
cout << str10 << endl;
str10.append(s);//把c类型字符串s连接到当前字符串的结尾
cout << str10 << endl;
str10.append(s, 2);//把c类型字符串s的前2个字符连接到当前字符串的结尾
cout << str10 << endl;
str10.append(str9.begin(), str9.end());//把迭代器之间的一段字符连接到当前字符串的结尾
cout << str10 << endl;
str10.push_back('k');//把一个字符连接到当前字符串的结尾
cout << str10 << endl;
//7.string的比较
flag = (str9 == str10);//判断两个字符串是否相等
cout << flag << endl;
flag = (str9 != str10);//判断两个字符串是否不相等
cout << flag << endl;
flag = (str9 > str10);//判断两个字符串是否大于关系
cout << flag << endl;
flag = (str9 < str10);//判断两个字符串是否为小于关系
cout << flag << endl;
flag = (str9 >= str10);//判断两个字符串是否为大于等于关系
cout << flag << endl;
flag = (str9 <= str10);//判断两个字符串否为小于等于关系
cout << flag << endl;
//以下的3个函数同样适用于c类型的字符串,在compare函数中>时返回1,<时返回-1,=时返回0
flag = str10.compare(str9);//比较两个字符串的大小,通过ASCII的相减得出!
cout << flag << endl;
flag = str10.compare(6, 12, str9);//比较str10字符串从6开始的12个字符组成的字符串与str9的大小
cout << flag << endl;
flag = str10.compare(6, 12, str9, 3, 5);//比较str10字符串从6开始的12个字符组成的字符串与str9字符串从3开始的5个字符组成的字符串的大小
cout << flag << endl;
//8.string的子串
string str11;
str11 = str10.substr(10, 15);//返回从下标10开始的15个字符组成的字符串
cout << str11 << endl;
//9.string的交换
str11.swap(str10);//交换str11与str10的值
cout << str11 << endl;
//10.string的查找,查找成功时返回所在位置,失败时返回string::npos的值,即是-1
string str12 = "abcdefghijklmnopqrstuvwxyz";
int pos;
pos = str12.find('i', 0);//从位置0开始查找字符i在当前字符串的位置
cout << pos << endl;
pos = str12.find("ghijk", 0);//从位置0开始查找字符串“ghijk”在当前字符串的位置
cout << pos << endl;
pos = str12.find("opqrstuvw", 0, 4);//从位置0开始查找字符串“opqrstuvw”前4个字符组成的字符串在当前字符串中的位置
cout << pos << endl;
pos = str12.rfind('s', string::npos);//从字符串str12反向开始查找字符s在字符串中的位置
cout << pos << endl;
pos = str12.rfind("klmn", string::npos);//从字符串str12反向开始查找字符串“klmn”在字符串中的位置
cout << pos << endl;
pos = str12.rfind("opqrstuvw", string::npos, 3);//从string::pos开始从后向前查找字符串s中前n个字符组成的字符串在当前串中的位置
cout << pos << endl;
string str13 = "aaaabbbbccccdddeeefffggghhhiiijjjkkllmmmandjfaklsdfpopdtwptioczx";
pos = str13.find_first_of('d', 0);//从位置0开始查找字符d在当前字符串第一次出现的位置
cout << pos << endl;
pos = str13.find_first_of("eefff", 0);//从位置0开始查找字符串“eeefff“在当前字符串中第一次出现的位置
cout << pos << endl;
pos = str13.find_first_of("efff", 0, 3);//从位置0开始查找当前串中第一个在字符串”efff“的前3个字符组成的数组里的字符的位置
cout << pos << endl;
pos = str13.find_first_not_of('b', 0);//从当前串中查找第一个不在串s中的字符出现的位置
cout << pos << endl;
pos = str13.find_first_not_of("abcdefghij", 0);//从当前串中查找第一个不在串s中的字符出现的位置
cout << pos << endl;
pos = str13.find_first_not_of("abcdefghij", 0, 3);//从当前串中查找第一个不在由字符串”abcdefghij”的前3个字符所组成的字符串中的字符出现的位置
cout << pos << endl;
//下面的last的格式和first的一致,只是它从后面检索!
pos = str13.find_last_of('b', string::npos);
cout << pos << endl;
pos = str13.find_last_of("abcdef", string::npos);
cout << pos << endl;
pos = str13.find_last_of("abcdef", string::npos, 2);
cout << pos << endl;
pos = str13.find_last_not_of('a', string::npos);
cout << pos << endl;
pos = str13.find_last_not_of("abcdef", string::npos);
cout << pos << endl;
pos = str13.find_last_not_of("abcdef", string::npos, 3);
cout << pos << endl;
//11.string的替换
string str14 = "abcdefghijklmn";
str14.replace(0, 3, "qqqq");//删除从0开始的3个字符,然后在0处插入字符串“qqqq”
cout << str14 << endl;
str14.replace(0, 3, "vvvv", 2);//删除从0开始的3个字符,然后在0处插入字符串“vvvv”的前2个字符
cout << str14 << endl;
str14.replace(0, 3, "opqrstuvw", 2, 4);//删除从0开始的3个字符,然后在0处插入字符串“opqrstuvw”从位置2开始的4个字符
cout << str14 << endl;
str14.replace(0, 3, 8, 'c');//删除从0开始的3个字符,然后在0处插入8个字符 c
cout << str14 << endl;
//上面的位置可以换为迭代器的位置,操作是一样的,在这里就不再重复了!
//12.string的插入,下面的位置处亦可以用迭代器的指针表示,操作是一样的
string str15 = "abcdefg";
str15.insert(0, "mnop");//在字符串的0位置开始处,插入字符串“mnop”
cout << str15 << endl;
str15.insert(0, 2, 'm');//在字符串的0位置开始处,插入2个字符m
cout << str15 << endl;
str15.insert(0, "uvwxy", 3);//在字符串的0位置开始处,插入字符串“uvwxy”中的前3个字符
cout << str15 << endl;
str15.insert(0, "uvwxy", 1, 2);//在字符串的0位置开始处,插入从字符串“uvwxy”的1位置开始的2个字符
cout << str15 << endl;
//13.string的删除
string str16 = "gfedcba";
string::iterator it;
it = str16.begin();
it++;
str16.erase(it);//删除it指向的字符,返回删除后迭代器的位置
cout << str16 << endl;
str16.erase(it, it+3);//删除it和it+3之间的所有字符,返回删除后迭代器的位置
cout << str16 << endl;
str16.erase(2);//删除从字符串位置3以后的所有字符,返回位置3前面的字符
cout << str16 << endl;
//14.字符串的流处理
string str17("hello,this is a test");
istringstream is(str17);
string s1,s2,s3,s4;
is>>s1>>s2>>s3>>s4;//s1="hello,this",s2="is",s3="a",s4="test"
ostringstream os;
os<
std:: 表示命名空间 可用using namespace std;代替
std::set
1,set的含义是集合,它是一个有序的容器,里面的元素都是排序好的,支持插入,删除,查找等操作,就 像一个集合一样。所有的操作的都是严格在logn时间之内完成,效率非常高。 set和multiset的区别是:set插入的元素不能相同,但是multiset可以相同。
创建 multiset
删除:如果删除元素a,那么在定义的比较关系下和a相等的所有元素都会被删除
base.count( a ):set能返回0或者1,multiset是有多少个返回多少个.
Set和multiset都是引用
2,Set中的元素可以是任意类型的,但是由于需要排序,所以元素必须有一个序,即大小的比较关系,比如 整数可以用<比较.
3,自定义比较函数;
include
typedef struct
{ 定义类型 }
ss(类型名);
struct cmp
{
bool operator()( const int &a, const int &b ) const
{ 定义比较关系<}
};
(运算符重载,重载<)
set base; ( 创建一个元素类型是ss,名字是base的set )
注:定义了<,==和>以及>=,<=就都确定了,STL的比较关系都是用<来确定的,所以必须通 过定义< --“严格弱小于”来确定比较关
4,set的基本操作:
begin() | 返回指向第一个元素的迭代器 |
clear() | 清除所有元素 |
count() | 返回某个值元素的个数 |
empty() | 如果集合为空,返回true |
end() | 返回指向最后一个元素的迭代器 |
equal_range() | 返回集合中与给定值相等的上下限的两个迭代器 |
erase() | 删除集合中的元素 |
find() | 返回一个指向被查找到元素的迭代器 |
get_allocator() | 返回集合的分配器 |
insert() | 在集合中插入元素 |
lower_bound() | 返回指向大于(或等于)某值的第一个元素的迭代器 |
key_comp() | 返回一个用于元素间值比较的函数 |
max_size() | 返回集合能容纳的元素的最大限值 |
rbegin() | 返回指向集合中最后一个元素的反向迭代器 |
rend() | 返回指向集合中第一个元素的反向迭代器 |
size() | 集合中元素的数目 |
swap() | 交换两个集合变量 |
upper_bound() | 返回大于某个值元素的迭代器 |
value_comp() | 返回一个用于比较元素间的值的函数 |
1:set元素的插入:
#include
#include
#include
using namespace std;
void printSet(set s)
{
set::iterator i;
for(i=s.begin(); i!=s.end(); i++)
printf("%d ",*i);
cout< s1;
for (int i = 0; i <5 ; i++)
s1.insert(i*10);
printSet(s1);
cout<<"s1.insert(20).second = "<::iterator, bool> p;
p = s1.insert(60);
if (p.second)
{cout<<"Insert OK!"<
2: set 的 empty erase 删除特定元素
#include
#include
using namespace std;
int main ()
{
set myset;
myset.insert(20);
myset.insert(30);
myset.insert(10);
while (!myset.empty())
{
cout <<" "<< *myset.begin();
myset.erase(myset.begin());
}
cout << endl;
return 0;
}
3:set 的 find 查找
//set::find
#include
#include
using namespace std;
int main ()
{
set myset;
set::iterator it;
for (int i=1; i<=5; i++) myset.insert(i*10); // set: 10 20 30 40 50
it=myset.find(20);
myset.erase (it);
myset.erase (myset.find(40));
myset.erase (30);
cout << "myset contains:";
for (it=myset.begin(); it!=myset.end(); it++)
cout << " " << *it;
cout << endl;
return 0;
}
4. set 的 二分 set::lower_bound/upper_bound
lower_bound()返回一个 iterator 它指向在[first,last)标记的有序序列中可以插入value,而不会破坏容器顺序的第一个位置,而这个位置标记了一个大于等于value 的值。 (即返回指向大于(或等于)某值的第一个元素的迭代器)
例如,有如下序列:
a[]={12,15,17,19,20,22,23,26,29,35,40,51}; 用值21调用lower_bound(),返回一个指向22的iterator。用值22调用lower_bound(),也返回一个指向22的iterator。
同理 upper_bound():返回第一个大于v的迭代器指针。
// 6.set::lower_bound/upper_bound
#include
#include
using namespace std;
int main ()
{
set myset;
set::iterator it,itlow,itup;
for (int i=1; i<10; i++) myset.insert(i*10); // 10 20 30 40 50 60 70 80 90
itlow=myset.lower_bound (30); // >=
itup=myset.upper_bound (60); // >
printf("%d %d",*itlow,*itup); // 30 70
return 0;
}
5.set 的 set::equal_elements
// 7.set::equal_elements 返回集合中与给定值相等的上下限的两个迭代器
#include
#include
using namespace std;
int main ()
{
set myset;
pair::iterator,set::iterator> ret;
for (int i=1; i<=5; i++) myset.insert(i*10); // set: 10 20 30 40 50
ret = myset.equal_range(30);
cout << "lower bound points to: " << *ret.first << endl;
cout << "upper bound points to: " << *ret.second << endl;
return 0;
}
//lower bound points to: 30
//upper bound points to: 40
6. set结构体的应用
#include
#include
using namespace std;
struct haha
{
int a,b;
char s;
friend bool operator<(struct haha a,struct haha b)
{
return a.selement;
int main()
{
struct haha a,b,c,d,t;
a.a=1; a.s='b';
b.a=2; b.s='c';
c.a=4; c.s='d';
d.a=3; d.s='a';
element.insert(d);
element.insert(b);
element.insert(c);
element.insert(a);
set::iterator it;
for(it=element.begin(); it!=element.end();it++)
cout<<(*it).a<<" ";
cout<
multiset
定义正向迭代器与正向遍历:
multiset::iterator it;
for(it=s.begin();it!=s.end();it++)
{
printf("%d\n",(*it));
}
或者
multisetit;
for(auto i : it)
{
printf("%d\n",i);
}
定义反向迭代器与反向遍历:
multiset::reverse_iterator rit;
for(rit=s.rbegin();rit!=s.rend();rit++)
{
printf("%d\n",-(*rit));
}
插入一个数x:
s.insert(x)
几种删除:
s.erase(v):删除值为v的所有元素。
s.erase(it):删除迭代器it处的元素。
也就是说可以用s.erase(s.find(v))来删除值为v的一个元素。
multiset::iterator it = a.find(x);
if (it != a.end())
{
a.erase(it); //这里是删除其中的一个x; 删除的是一个位置 而arase是删除所有位置
}
查找相关:
s.lower_bound(v):返回第一个大于等于v的迭代器指针。
s.upper_bound(v):返回第一个大于v的迭代器指针。
s.find(v):返回一个等于v的迭代器指针。如果不存在值等于v的元素,则返回s.end()
s.equal_range(v):返回值等于v的第一个迭代器和最后一个迭代器,左闭右开,如果不存在则返回两个s.end()
s.count(v):返回值等于v的元素个数,数据类型为unsigned longlong int,如果不存在返回0,时间复杂度未知,如果重复的个数过多可能会慢。
pair 默认对first升序,当first相同时对second升序;
类模板:template
参数:T1是第一个值的数据类型,T2是第二个值的数据类型。
功能:pair将一对值组合成一个值,这一对值可以具有不同的数据类型(T1和T2),两个值可以分别用pair的两个公有函数first和second访问。
1.定义(构造):
pair p1; //使用默认构造函数
pair p2(1, 2.4); //用给定值初始化
pair p3(p2); //拷贝构造函数
2.访问两个元素(通过first和second):
pair p1; //使用默认构造函数
p1.first = 1;
p1.second = 2.5;
cout << p1.first << ' ' << p1.second << endl;
输出结果:1 2.5
3.赋值operator = :
(1)利用make_pair:
pair p1;
p1 = make_pair(1, 1.2);
可以用cmp数组改;
代码:
#include
#include
#include
#include
#include
#define mem(x,y) memset(x,y,sizeof(x))
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
pairpa[100];
int cmp(paira,pairb){
if(a.first!=b.first)return a.first>b.first;
else return a.second
最近在写一个算法的时候,把一些数据存在了pair中,并且需要根据pair中first或者second的值对这些数据进行排序。
比如:输入数据(1,2)、(4,2)、(3,3)、(2,1)
根据first的值大小进行升序排序,输出(1,2)、(2,1)、(3,3)、(4,2)。
经过思索之后得到的实现方法如下:
首先将这些数据存在vector数组中,vector
然后使用sort函数对数组进行排序,这里就涉及到了sort函数的使用了。
下面是sort函数使用方法
函数声明:
template
void stable_sort ( RandomAccessIterator first, RandomAccessIterator last );
template
void stable_sort ( RandomAccessIterator first, RandomAccessIterator last,
Compare comp );
参数解释:
(1)第一个是要排序的数组的起始地址。
(2)第二个是结束的地址(最后一位要排序的地址的下一地址)。
(3)第三个参数是排序的方法,可以是从大到小也可是从小到大,还可以不写第三个参数,此时默认的排序方法是从小到大排序。
我们可以根据自己的需求自定义第三个参数cmp函数,比如若要对整型数组降序排序,则可以这样来写cmp函数:
bool cmp(int a, int b)
{
return a>b;//升序则为a
这个cmp参数使用起来非常方便,因为它正好能解决我们的pair排序问题。
我们只要根据数组中的元素类型定义cmp函数的参数,并且根据需求定义函数体
bool cmp(paira, pairb)
{
return a.first
然后调用sort函数sort(vec.begin(),vec.end(),cmp)。
便可以根据pair中first的值进行升序排序。
下面是具体代码实现
#include "stdafx.h"
#include
#include
#include
using namespace std;
//根据first的值升序排序
bool cmp1(paira,pairb)
{
return a.first < b.first;
}
//根据second的值升序排序
bool cmp2(paira, pairb)
{
return a.second < b.second;
}
int main()
{
vector>vec;
vec.push_back({ 1,2 });
vec.push_back({ 4,2 });
vec.push_back({ 3,3 });
vec.push_back({ 2,1 });
sort(vec.begin(), vec.end(), cmp1);
cout << "根据first的值升序排序:" << endl;
for (auto it = vec.begin();it != vec.end();it++)
{
cout << "(" << it->first << "," << it->second << ")" << endl;
}
sort(vec.begin(), vec.end(), cmp2);
cout << "根据second的值升序排序:" << endl;
for (auto it = vec.begin();it != vec.end();it++)
{
cout << "(" << it->first << "," << it->second << ")" << endl;
}
}
因为pair默认排序是first从小到大排,若first相同则second默认从小到大排
所以若first想要从小到大进行排序直接用默认sort即可
若
#include
#include
#include
using namespace std;
const int nmax=200000+10;
paira[nmax];
int main(int argc, char** argv) {
int t;
while(cin>>t){
int n;//任务数
int m;//人数
while(t--){
cin>>n>>m;
for(int i=0;i>a[i].first>>a[i].second;
}
sort(a,a+n);//按照first左边排序
for(int i=0;i
若想要从大到小,只要把second和first输入顺序交换一下即可
#include
#include
#include
using namespace std;
const int nmax=200000+10;
paira[nmax];
int main(int argc, char** argv) {
int t;
while(cin>>t){
int n;//任务数
int m;//人数
while(t--){
cin>>n>>m;
for(int i=0;i>a[i].second>>a[i].first;
}
sort(a,a+n);//按照firs右排序
for(int i=0;i