C/C++ STL容器的选择和适用,算法及其仿函数

转自http://blog.163.com/miky_sun/blog/static/3369405201022714145686/,作者:博客的简单


1.Vector,list,deque,map简介


vector数组容器:能自动扩充大小,每次增加原大小的一半 
deque双头队列: 能自动扩充大小,双头都可伸展;而Vector头是固定的 
list是链表容器:数据不是连续的,很适合于频繁的插入删除操作 
map是映射表:其key值存储是连续且有序的,所以find是很高效的。 
string字符串的使用 
strstream和sstream 字符串流一个是char*流、一个是string流

size_type 表示大小=size_t 

2. Vector的使用

 1: // Vector常见的用法和算法
 2: vector<int> vect_;
 3: int itemp = 2;
 4: vect_.assign(10, itemp);  //用10个itemp组成数组
 5: vect_.assign(deq.begin(), deq.end());
 6: vect_.resize(15); //将容量设置为15;这样size和capacity都是15
 7: vect_.push_back(10); //这时候size=16, 而capacity=22 
 8: 
 9: vect_.at(5);  //是第5个元素;对于所有容器都适用
 10: vect_.front(); //是第一个元素
 11: vect_.back(); //是最后一个元素
 12: it = vect_.erase(it); //it最后指向删除元素的下一个元素,且后面的成员copy和析构,所以连续容器不适合于频繁删除操作
 13: vect_.size() //是用for循环算出来的,所以不要频繁适用(所有容器) 
 14: 
 15: //常见的算法:单元素的容器都适用vect,list,deque都做过测试
 16: sort(vect_.begin(), vect_.end(), less<int>()); //greater<int>()
 17: copy(vect_.begin(), vect_.begin()+vect_.size(), vect_dest.begin()+vect_dest_old);
 18: if ((it = find(vect_.begin(), vect_.end(), ival)) != vect_.end()) {
 19: printf("vect pos=%d", it-vect_.begin()); // 打印出当前的位置
 20: }

 

3.双头队列deque,两头都可操作扩展

 1: //跟vector一样就多了头可以移动功能 
 2: deque<int> deq_; 
 3: deq_.pop_front(); 
 4: deq_.push_front(); 


4. 双头链表list

 1: //是一个双头链表;头尾都可操作 
 2: list<int> 
 3: list_; 
 4: list_.sort(less<int>()); //可排序,按照默认或自定义的方式 
 5: list_.unique(); // 设置为唯一模式,重复的元素将删除 


5.STD::map的使用

 1: //map映射表,key是连续且小序存储,value是映射的地址到key上面;适合大量存储且频繁查找和删除 
 2: map_.find(itemp);


6.string字符串操作

string并不是一个单独的容器,只是basic_string 模板类的一个typedef 而已,相对应的还有wstring, 你在string 头文件中你会发现下面的代码: 
typedef basic_string <char> string; 
typedef basic_string <wchar_t> wstring;

字符串的重载
//string重载了许多操作符:+, +=, <, =, , [], <<, >>等
string strinfo;
cout << strinfo << endl;
cin >> strinfo;
for(int i = 0; i < strtmp.size(); i++) {
printf("第%d个字符是: %c", i, strinfo[i]);
}
字符串的构造
string s1 = "hello";
string s2 = "world";
string s3 = s1 + "," + s2 +"!\n";
string s4("your name"); //使用const char生成
string s5(10, 'x'); //用10个x字符生成字符串;s5=xxxxxxxxxx
查找子串
size_t find(char*, pos, cnt); //类似函数有find_first_of,find_last_of
size_t find(string, pos, cnt); //size_t==string::npos表示没有找到

string str ("There are two needles in this haystack with needles.");
string str2 ("needle");
if ( string::npos == str.find(str2) )
cout << "not find" << endl;
ipos = str.find_first_of(str2); //ipos=15
ipos = str.find_last_of(str2); //ipos=40
插入子串
string& insert(size_t pos1, string& str); //例如: str1.insert(2, str2)
string& insert(size_t pos1, char* str); //例如: str1.insert(2, "ddd");
string& insert(size_t pos1, size_t cnt, char c);//例如: str1.insert(2, 10, 'x');
替换子串
string& replace(size_t pos1, size_t cnt, string& str, size_t pos2, size_t cnt2);
string& replace(size_t pos1, size_t cnt, char* str, size_t pos2, size_t cnt2);
string& replace(size_t pos1, size_t cnt, size_t n2, char c );
string& replace(起点, 个数, 要替换的子串, 子串的起点, 子串中字符的个数);
//子串的起点=0, 子串中字符的个数=length
//函数执行后当前串的长度会发生变化

string.replace(2, 3, "just all"); //将字符串从第2个起后3个字符替换为"just all"
stirng.replace(2, 3, 10, 'x'); //将字符串从第2个起后3个字符替换为10个'x'
string.replace(string.find("pstr"), strlen("pstr"), "just all"); //将pstr替换为"just all"
删除子串
string& erase(size_t pos, size_t cnt); //erase(起点, 个数);
string& erase(size_t pos); //erase(起点);从起点删除到结尾
str.erase(10, 8);
str.erase(10);
删除某个字符
//中删除前先remove_if办法,其实适用任何容器vector,list,map
string str(" hello, world. say bye ");
str.erase(remove_if(str.begin(), str.end(), bind2nd(equal_to<char>(), ' ')), str.end());
字符串比较
//可以使用==,!=,>=,<=或compare成员,或compare模板函数
if (str1 == str2);
str_.compare(5, 3, dest, 0, 3);

分割字符串
stringstream ss("big|dog|china|sonic|free");
string sub_str;
while( getline(ss,sub_str,'|')) //按照|分割为行,每次从流中读取一行数据到sub_str中
printf("%s\n", sub_str.c_str());

//strtok也可以做到: 只不过strtok修改了自身字符串;将字符串中的分隔符替换为"\0"
char* p = strtok(pbuf, delim); //第一次切割,将找出的指针压入vect中
if (p != NULL)
vect_.push_back(p);
while ((p = strtok(NULL, delim)))
vect_.push_back(p); //循环切割,且将找出的指针压入vect中
大小写切换
//transform(inIt, inIt, outIt, func); transform(起始点, 结束点, 输出点, 执行的彷函数)
transform(string.begin(), string.end(), string.begin(), toupper);
transform(string.begin(), string.end(), string.begin(), tolower);
数字转换
//转换为数字 atoi, atof, stringstream
atoi(s.c_str());
atof(s.c_str());
stringstream(s) >> ipos;
解析路径中的 
文件名
string sPath = "C:\\Program Files\\Kingsoft\\WPS Office Personal\\aeoc.dll";
size_t pos = sPath.rfind("\\ ");
string sFile = sPath.substr(pos == string::npos ? 0 : pos + 1);
printf("fileName=%s\n", sFile.c_str());
拷贝=strncpy 
将string拷贝到 
ansi字符串中
string str ("Test string...");
char buffer[20];
size_t len;
len = str.copy(buffer,6,5);//将数据copy到buffer中,等同于strncpy
buffer[len] = '\0'; //在最后设置为\0结束符
string 
操作汇总
string.length() //字符串的长度
string.size() //容器的大小
string.clear() //清理
string.empty() //判断是否为空
string.erase() //删除
operator[pos] //获得pos位置上的字符
at(pos)
c_str()
insert(); //insert(位置, 字符串)
replace(); //replace(位置, 个数, 替换的字符串)
find(); //find(字符串)
copy(); //copy(目标缓冲区, 位置, 个数)
substr() //substr(位置, 个数)
compare(); //compare(字符串)
 

7. c++有两种流,也成为数组I/O流:


一个是在sstream中定义的、基于string字符串的流stringStream;str()返回的是string 
一个是在strstream中定义、基于char*的字符串流strstream;str()返回的是char* 08cppios01  
1: //stringstream流以空格为分隔符
2: stringstream.str("str 8765");
3: stringstream >> s >> i; //s=str & i=8765
4: stringstream << s << i; //将s-i存入流中
5: stringstream.str(); //就是写入的数据
6: stringstream.clear(); //清理转换的类型,而不是数据
7: stringstream.str(""); //清理存储的数据
8:
9: //在字符数组上建立一个输出流;可以将流写入数组中
10: ostrstream ostr(char* buf, int buf_len, int mode=ios::out);
11:
12: //将字符数组作为流的来源;
13: istrstream istr(char*buf);
14:
15: //文件流i/ofstream;(<fstream>)
16: ifstream infile("input.txt");
17: infile.close(); //fstream每次只能和一个文件关联
18: infile.clear(); //


8. 常见的函数 <algorithm>


1: vector/list/deque vect,dest;
2: int oldsize=dest.size();
3: sort(vect.begin(), vect.end(), less<int>() );
4: copy(vect.begin(), vect.begin()+vect.size(), dest.begin()+oldsize);
5: find(vect.begin(), vect.end, value);
6: it = vect.erase(it); //返回的指针是指向删除元素后面的元素
7: for_each(), count(), count_if();


================================================================ 
常见的函数 <algorithm> 
仿函数 <function>

 

9.STL中的仿函数

#include <functional>   // 仿函数的头文件 
仿函数是模板,因此在定义的时候一定要定义其模板参数和类型

我们看一个查询的map的流程,其中使用仿函数

 1: /* 其实仿函数就是将来作为函数指针来使用的,只不过这个指针是个模板的方式来定义的。
 2:  * 定义一个仿函数,其声明的格式:
 3:  * struct xxxxx : binary_function< 模板参数, 模板参数, 模板返回值 >
 4:  * {
 5:  * bool operator()(模板参数定义的输入, 模板参数定义的输入) const //必须为const否则会出错
 6:  * {
 7:  * }
 8:  * }
 9:  *
 10:  * 对于第一个输入参数:可默认为容器的value_type
 11:  * vector,list,deque的value_type 是容器中的存储数据的类型
 12:  * map的value_type 是pair类型,而且不能是key_type! 这个一定要注意
 13:  */
 14: struct find_byid: binary_function<map<string,int>::value_type, const char*, bool>
 15: {
 16: bool operator()(map<string,int>::value_type &_pair, const char* username) const
 17: {
 18: if ( strncmp( _pair.first.c_str(), username, strlen(username)) == 0)
 19: return true;
 20: else
 21: return false;
 22: }
 23: };
 24: 
 25: int _tmain(int argc, _TCHAR* argv[])
 26: {
 27: map<string, int> test_map;
 28: test_map["123-test1"] = 12;
 29: test_map["133-test"] = 10;
 30: test_map["143-test"] = 10;
 31: test_map["153-test"] = 10;
 32: test_map["163-test"] = 10;
 33: test_map["123-test2"] = 12;
 34: 
 35: // 使用STL的find_if函数,将前面定义的仿函数作为参数输入进去
 36: map<string,int>::iterator it = find_if(test_map.begin(), test_map.end(), bind2nd(find_byid(), "123"));
 37: if (it != test_map.end())
 38: printf("key=%s, value=%d", it->first.c_str(), it->second);
 39: 
 40: 
 41: getchar();
 42: return 0;
 43: }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值