强大的STL(二)

本文介绍了C++标准模板库(STL)中string、set、map等容器的基本操作及常用算法,如查找、插入、删除元素,以及如何使用string streams进行字符串处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


********************************************************************************************************************************

string

********************************************************************************************************************************

方法

    string s = "hello"; 

    string 

        s1 = s.substr(0, 3), // "hel" 

        s2 = s.substr(1, 3), // "ell" 

        s3 = s.substr(0, s.length()-1),// "hell"

        s4 = s.substr(1); // "ello" 



********************************************************************************************************************************

set

********************************************************************************************************************************



set提供的功能:可以添删元素,不允许相同元素存在,可以查元素总数,以及某个元素是否已存在

方法

--------------------

构造

int data[5] = { 5, 1, 4, 2, 3 }; 

set<int> s(data, data+5); 

--------------------

 set<int> s; 

 for(int i = 1; i <= 100; i++) {

      s.insert(i); // Insert 100 elements, [1..100] 

 }

 s.insert(42); // does nothing, 42 already exists in set 

 for(int i = 2; i <= 100; i += 2) { 

      s.erase(i); // Erase even values 

 } 

 int n = int(s.size()); // n will be 50 

--------------------

 set 没有push_back方法,

--------------------

 循环遍历

 int r = 0; 

 for(set<int>::const_iterator it = S.begin(); it != S.end(); it++) { 

      r += *it; 

 } 

--------------------

查找,可以使用STL提供的find方法(复杂度为O(n)),而set::find()复杂度为 O(log(n))

 set<int> s; 

 // ... 

 if(s.find(42) != s.end()) { 

      // 42 presents in set 

 } 

 else { 

      // 42 not presents in set 

 } 

 或

 if(s.count(42) != 0) { 

      // … 

 }  

 或

 if(s.count(42)) { 

      // … 

 } 

--------------------

 区间擦除

 set<int>::iterator it1, it2; 

 it1 = s.find(10); 

 it2 = s.find(100); 

 s.erase(it1, it2);

--------------------

非常简单但是有用的方法:去除vector中重复的项,并排好序(升序)  

  vector<int> v; 

 // … 

 set<int> s(v.begin(), v.end()); 

 vector<int> v2(s.begin(), s.end()); //vc无法编译通过,用下代替



    for (set<int>::const_iterator it = s.begin(); it != s.end(); it++)

        v2.push_back(*it);



********************************************************************************************************************************

map

********************************************************************************************************************************

map与set很相似,但是map存放的是pairs <key, value>而不是值,

map确保对应一个明确的key最多只存在一个pair(即key不重复,同set的value),并且map可以使用操作符[]。



不要通过iterator来改变map的key,因为这会破坏map的内部数据结构。



 map<string, int> M; 

 M["Top"] = 1; 

 M["Coder"] = 2; 

 M["SRM"] = 10; 



 int x = M["Top"] + M["Coder"]; 



 if(M.find("SRM") != M.end()) { 

      M.erase(M.find("SRM")); // or even M.erase("SRM") 

 } 





map::find() 和 map::operator []. 有一个很重要的不同就是,map::find()不会改变map的内容,operator []如果不存在的话会创建一个新的元素,

有时这可能会非常便利,但是最好不要在一个循环中多次使用operator [],如果你不想创建新元素的话。

这也就是当引用一个map作为一个函数的const型参数的时候不能使用operator []的原因。





********************************************************************************************************************************

STL algorithm

********************************************************************************************************************************

#include <algorithm>



min(a,b), max(a,b), swap(a,b)

find(begin, end, element) 返回iterator第一次出现的地方,没找到返回end

count(begin, end, element) 返回element出现的次数

set 和 map 都有成员方法 find() 和 count(),时间复杂度为O(log N), 而std::find() 和 std::count() 为 O(N). 



介绍两个有用的算法,可以用在排列组合等等问题

next_permutation(begin, end) 把第一项做为最高位依次递减,从当前序列值开始增值到最大,最后设回最小值的一个排列

prev_permutation(begin, end) 类似next_permutation,不过是递减,而不是递增,最后设为最大值

示例:

// int data[3] = { 1, 2, 3}; vector<int> v(data,data+3);

*  1 *  2 *  3     

// do {} while(next_permutation(v.begin(), v.end())); 

1 2 3              

1 3 2

2 1 3

2 3 1

3 1 2

3 2 1

*  1 *  2 *  3 // 重设v为{1, 2, 3},无视v的初始值

// reverse(v.begin(),v.end()); 重设v为 3 2 1,以执行prev_permutation

// do {} while(prev_permutation(v.begin(), v.end()));

3 2 1

3 1 2

2 3 1

2 1 3

1 3 2

1 2 3

*  3 *  2 *  1 





********************************************************************************************************************************

String Streams

********************************************************************************************************************************

#include <sstream>



编程中经常要对字符串进行处理/输入/输出

C++提供了两个有意思的类 'istringstream' 和 'ostringstream'。

istringstream对象允许你象从标准输入(stdin)一样读取一个字符串,示例代码:

vector<int> f(const string& s) 

{

    // Construct an object to parse strings 

    istringstream is(s); 

    

    // Vector to store data 

    vector<int> v; 

    

    // Read integer while possible and add it to the vector 

    int tmp; 

    while(is >> tmp) { 

        v.push_back(tmp); 

    } 

    return v;

} 

ostringstream对象用来格式化输出,示例代码:

string U(const vector<int>& v) 

{ 

    // Constucvt an object to do formatted output 

    ostringstream os; 

    

    // Copy all elements from vector<int> to string stream as text 

    for (vector<int>::const_iterator it = v.begin(); it != v.end(); it++)

    { 

        os << ' ' << *it; 

    } 



    // Get string from string stream 

    string s = os.str(); 

    

    // Remove first space character 

    if(!s.empty()) { // Beware of empty string here 

        s = s.substr(1); 

    } 

    

    return s; 

} 



********************************************************************************************************************************

总结 summary

********************************************************************************************************************************

这些宏是有作用的,可参考

typedef vector<int> vi; 

typedef vector<vi> vvi; 

typedef pair<int,int> ii; 

#define sz(a) int((a).size()) 

#define pb push_back 

#define all(c) (c).begin(),(c).end() 

// 这个宏vc下不可用,typeof是glibc下定义的

#define tr(c,i) for(typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)

#define present(c,x) ((c).find(x) != (c).end()) 

#define cpresent(c,x) (find(all(c),x) != (c).end()) 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值