浅谈STL

string

常用的部分函数

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 s;那个s这个对象里面存贮的元素是从小到大排序的,(因为用std::less作为比较工具。)

1,set的含义是集合,它是一个有序的容器,里面的元素都是排序好的,支持插入,删除,查找等操作,就    像一个集合一样。所有的操作的都是严格在logn时间之内完成,效率非常高。 set和multiset的区别是:set插入的元素不能相同,但是multiset可以相同。

   创建 multiset base;

   删除:如果删除元素a,那么在定义的比较关系下和a相等的所有元素都会被删除

  base.count( a ):set能返回0或者1,multiset是有多少个返回多少个.

   Set和multiset都是引用头文件,复杂度都是logn

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

multisets;

定义正向迭代器与正向遍历:

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

 pair 默认对first升序,当first相同时对second升序;

类模板:template struct pair

参数:T1是第一个值的数据类型,T2是第二个值的数据类型。

功能:pair将一对值组合成一个值,这一对值可以具有不同的数据类型(T1和T2),两个值可以分别用pair的两个公有函数first和second访问。

1.定义(构造):

     pair p1;  //使用默认构造函数
     pair p2(1, 2.4);  //用给定值初始化
     pair p3(p2);  //拷贝构造函数

2.访问两个元素(通过firstsecond):

     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

C++对一组pair数据进行排序(sort函数的使用)

最近在写一个算法的时候,把一些数据存在了pair中,并且需要根据pair中first或者second的值对这些数据进行排序。

比如:输入数据(1,2)、(4,2)、(3,3)、(2,1)

根据first的值大小进行升序排序,输出(1,2)、(2,1)、(3,3)、(4,2)。
经过思索之后得到的实现方法如下:
首先将这些数据存在vector数组中,vector>vec;
然后使用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;
    }
}

浅谈STL_第1张图片

因为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

 

你可能感兴趣的:(STL,算法详解)