包括string类,顺序容器,容器适配器,关联容器
创建与初始化
string a="adwdad";
string a[4] = {"twenty", "thirty", "forty", "fifty"};
//下面两行的写法是错的!!!
string b[4] = {'twenty', 'thirty', 'sdfse', 'dawd'};
string a='adwdad';
char s='a';
char s="a"; //这种写法是错的
char s[]="abcd"; //这个是字符串,以'\0'结束的,用strlen(s)是4,'\0'不计,但是它是有五个字符的
char s1[]={'a','b','c','d'}; //这个是字符数组,没有'\0',用strlen(s1)是不确定的,它有四个字符
char s='a';
操作
//获取字符串长度
int L =str.length();
int S =str.size(); //L=S 基本一样
//str去除元素
str.erase(pos,len); //str.erase(0,1); //删除pos开始的lin个字符
str.erase(a,b); //删除迭代器a和b标记范围内所有的元素,返回一个迭代器,指向被删除元素段后面的第一个元素
//string翻转
reverse(str.begin(),str.end());
//string插入元素
str.insert(pos,s2); //在下标为pos的元素之前插入string对象s2的副本
str.insert(pos,n,c); //在下标为pos的元素之前插入n个字符c
//子串
str.substr(pos,n); //返回一个string类型的字符串,它包含s中从下标pos开始的n个字符
str.substr(pos); //返回一个string类型的字符串,它包含从下标pos开始到s末为的所有字符
//查找
str.find(args); //在s中查找args的第一次出现
str.find(char c='a'); //在s中查找字符的第一次出现
str.find(string substr='abdb'); //在s中查找子字符串的第一次出现
str.rfind(args); //在s中查找args的最后一次出现
str.find_first_of(args); //在s中查args的任意字符的第一次出现
str.find_last_of(args); //在s中查找args的任意字符的最后一次出现
str.find_first_not_of(args); //在s中查找第一个不属于args的字符
str.find_last_not_of(args); //在s中查找最后一个不属于args的字符
//arg的各种情况:
c,pos //在s中,从下标pos标记的位置开始,查找字符c、pos的默认值是0
s2,pos //在s中,从下标pos标记的位置开始,查找string对象s2,pos的默认值为0
cp,pos //在s中从下标pos标记的位置开始,查找cp所指向的c风格的以空格结束的字符串。pos默认值为0
cp,pos,n //在s中,从下标pos标记的位置开始,查找指针cp所指向数组的前n个字符,pos和n都没有默认值
//返回的是元素下标:eg
size_t nLoc = str.find(args);
if (nLoc != string::npos) //未找到返回-1
cout << "nLoc is: " << nLoc << endl;
//比较compare
s.compare(s2); //比较s和s2
s.compare(pos1,n1,s2); //让s中从pos下标位置开始的n1个字符与s2做比较
s.compare(pos1,n1,s2,pos2,n2); //让s中从pos1下标位置开始的n1个字符与s2中从pos2下标位置开始的n2个字符做比较
s.compare(cp); //比较s和cp所指向的以空字符结束的字符串
s.compare(pos1,n1,cp); //让s从pos1下标位置开始的n1个字符与cp所指向的字符串做比较
s.compare(pos1,n1,cp,n2); //让s中从pos1下标位置开始的n1个字符与cp所指向字符串的前n2个字符做比较
//结果:
s1.compare(args);
//a.正数,此时s1大于args所代表的string对象
//b.负数,此时s1小于args所代表的string对象
//c.0,此时s1恰好等于args所代表的string对象
//追加append
s1 += s2;
s1.append(s2);
s1.append(s2, 5, 5); //取s2的第5个开始的5个字符追加给s1
s1.append(3, '!'); //s1尾部叠加3个!
常用代码块
//int转string
int a;
string str = to_string(static_cast(a));
//string转int
a=atoi(str.c_str());
//遍历string可以这样写,balabala
for(char c in s){
if(c=='a'){}
}
//字符范围判断相关代码块
for (size_t i = 0; i < str.size(); i++)
{
if( str[i]>='a' && str[i]<='z' ) //a to z
if( str[i]>='A' && str[i]<='Z' )
if( (str[i]>='a' && str[i]<='z') || (str[i]>='A' && str[i]<='Z') )
if( str[i]>='0' && str[i]<='9' )
}
//不等式
'a'<=str[i]<='z'//这样写是错的
str[i]>='a' && str[i]<='z' //这样才是正确语法
//等式
if(str[i]=' ') //这个写法错误
if(str[i]==' ') //这样才是正确语法
特性
头文件
#include
定义与初始化
vector Excel;
vector Excel = {1,2,3,4};
vector> Excel = {{1,2},{1,2,3,4}};
vector v(7,3); //指定值初始化,v被初始化为包含7个值为3的int
vector v(5);
itoa(v.begin(), v.end, 2) //v初始化为{2,3,4,5,6}
操作
方法 | 说明 |
---|---|
T front() | 返回首元素的引用 |
back | 返回尾元素的引用 |
begin | 返回指向首元素的随机存取迭代器 |
end | 返回指向尾元素的下一个位置的随机存取迭代器 |
push_back | 表尾巴添加元素 |
emplace_back | 表尾巴添加元素(传入构造函数的参数) |
pop_back | 删除尾元素 |
insert | 插入 |
erase | 删除 |
size() | 元素个数 |
clear | 清空 |
empty | 判空 |
resize | |
swap | |
assign | |
//添加元素
Excel.push_back(nums);
vector> v;
v.emplace_back(3, "abc");
//去除元素
int nPosition = i;//元素脚标
Excel.erase(Excel.begin()+nPosition);
Excel.erase(Excel.end()-1); //注意::最后一个元素是Deriction.end()-1!
常用代码块
//--查找find
//查找的重载
class error
{
public:
string file_name;
int line;
int count;
/////vector 的find函数,当vector中为自定义类型时,需要重载==操作,如下语句
bool operator == (const error & obj) const //重载 “==” 操作符,函数最后的 const 别忘了,否则会报错。(详见:http://www.cnblogs.com/SZxiaochun/p/7731900.html)
{
return file_name == obj.file_name && line == obj.line; //具体匹配条件,自己设定
}
};
//迭代器查找
error error_in;
vector errorlist;
//注意!!!!vector的find函数的使用方法不是v.find()!!!!
vector::iterator result = find( errorlist.begin( ), errorlist.end( ), error_in );
if ( result == errorlist.end( ) ) //没找到
errorlist.push_back(error_in);
else //查找到
{
int nPosition = distance(errorlist.begin(), result);
errorlist[nPosition].count++;
}
//--排序sort
//排序
sort(Excel.begin(),Excel.end());
//自定义类型的排序重载
//方式1
class Words
{
public:
string strwords;
int letter[26]={ 0 };
///自定义类型时,需要重载<操作,如下语句
bool operator < (const Words & obj) const //重载 “<” 操作符,函数最后的 const 别忘了,否则会报错。(详见:http://www.cnblogs.com/SZxiaochun/p/7731900.html)
{
return strwords < obj.strwords; //具体匹配条件,自己设定
}
};
sort(Excel.begin(),Excel.end());
//方式2
//或者自定义函数
bool cmp(Words a,Words b)
{
if(a.zfca::iterator max_e = max_element(candies.begin(), candies.end());
int max_num = *max_e;
特性
头文件
#include
创建
stack stk;
//初始化
stack stk = ;
操作
方法 | 说明 |
---|---|
bool empty()const | 判空 |
size_type size()const | 元素个数 |
T& top() | 返回栈顶元素的引用 |
void push(const T& x) | 栈顶插入元素 |
void pop() | 删除栈顶元素 |
stk.push(7); //入栈
stk.pop(); //出栈
stk.top(); //访问栈顶元素
stk.empty(); //判空
stk.size(); //元素个数
头文件
#include
创建
queue q;
//初始化
queue q =;
操作
q.push(7); //入队
q.pop(); //出队列
q.front(); //访问队首元素
q.back(); //访问队尾元素
q.empty(); //判空
q.size(); //返回队中元素个数
特性
特性
头文件
#include
创建
queue q;
操作
方法 | 说明 |
---|---|
bool empty()const | 判空 |
size_type size()const | 元素个数 |
T& front() | 返回队首元素的引用 |
T& back() | 返回队尾元素的引用 |
void push(const T& x) | 队尾插入元素 |
void pop() | 删除队首元素 |
特性
头文件
#include
创建
priority_queue pq1;
priority_queue pq1(greater); //自定义比较大小的函数greater()
特性
头文件
#include
创建
list c0; //空链表
//初始化
list c0{1,2,3,4,5};
list c1(3); //建一个含三个默认值是0的元素的链表
list c2(5,2); //建一个含五个元素的链表,值都是2
list c4(c2); //建一个c2的copy链表
list c5(c1.begin(),c1.end()); ////c5含c1一个区域的元素[_First, _Last)。
操作
c.begin(); //返回指向链表第一个元素的迭代器
c.end(); //返回指向链表最后一个元素之后的迭代器
1 list a1{1,2,3,4,5};
2 list::iterator it;
3 it = a1.begin();
4 cout << *it << endl;
c.rbegin() //返回逆向链表的第一个元素,即c链表的最后一个数据。
c.rend() //返回逆向链表的最后一个元素的下一个位置,即c链表的第一个数据再往前的位置。
c.front() //返回链表c的第一个元素。
c.back() //返回链表c的最后一个元素。
c.empty() //判断链表是否为空。
c.size() //返回链表c中实际元素的个数。
c.insert(pos,num) //在pos位置插入元素num。
c.insert(pos,n,num) //在pos位置插入n个元素num。
c.insert(pos,beg,end) //在pos位置插入区间为[beg,end)的元素。
c.erase(pos) //删除pos位置的元素。
c.push_back(num) //在末尾增加一个元素。
c.pop_back() //删除末尾的元素。
c.push_front(num) //在开始位置增加一个元素。
c.pop_front(); //删除第一个元素。
c.reverse(); //反转链表
c.unique(); //删除相邻的元素
c.sort() 将链表排序,默认升序
c.sort(comp) 自定义回调函数实现自定义排序
1 list a1{1,3,2,5,4};
2 a1.sort();
3 list::iterator it;
4 cout << "sort():";
5 for(it = a1.begin();it!=a1.end();it++){
6 cout << *it << " ";
7 }
8 cout << endl;
9
10 a1.sort([](int n1,int n2){return n1>n2;});
11 cout << "sort(function point):";
12 for(it = a1.begin();it!=a1.end();it++){
13 cout << *it << " ";
14 }
15 cout << endl;
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
void deleteNode(ListNode* node) {
node->val = (node->next)->val;
node->next = node->next->next;
}
};
特性
头文件
#include
创建
map mp;
map mp;
操作
//访问元素
map mp;
mp["apple"] = 15;
mp["bnanana"] = 16;
//方式一:直接访问
cout<first 来访问键, itr->second 来访问值。
for(map::iterator itr = mp.begin(); itr != mp.end(); itr++)
cout<< itr -> first
<< itr -> second<::iterator itr = mp.find("bnanana");
cout<< itr->first << itr->second<::iterator itr = mp.find("bnanana");
mp.erase(itr); //删除该迭代器所指元素
mp.erase(mp.begin(), itr); //删除最开始到itr所指元素前的所有元素,前闭后开
mp.erase(itr, mp.end()); //删除it之后的所有元素
mp.erase(mp.begin()); //删除最开始的元素
mp.erase(--mp.end()); //删除最后面的元素
//清空
mp.clear();
//大小
mp.size();
头文件
#include
特性
map: map内部实现了一个红黑树(红黑树是非严格平衡二叉搜索树,而AVL是严格平衡二叉搜索树),红黑树具有自动排序的功能,因此map内部的所有元素都是有序的,红黑树的每一个节点都代表着map的一个元素。因此,对于map进行的查找,删除,添加等一系列的操作都相当于是对红黑树进行的操作。map中的元素是按照二叉搜索树(又名二叉查找树、二叉排序树,特点就是左子树上所有节点的键值都小于根节点的键值,右子树所有节点的键值都大于根节点的键值)存储的,使用中序遍历可将键值按照从小到大遍历出来。
unordered_map: unordered_map内部实现了一个哈希表(也叫散列表,通过把关键码值映射到Hash表中一个位置来访问记录,查找的时间复杂度可达到O(1),其在海量数据处理中有着广泛应用)。因此,其元素的排列顺序是无序的。
map:
优点:
有序性,这是map结构最大的优点,其元素的有序性在很多应用中都会简化很多的操作
红黑树,内部实现一个红黑书使得map的很多操作在lgn的时间复杂度下就可以实现,因此效率非常的高
缺点: 空间占用率高,因为map内部实现了红黑树,虽然提高了运行效率,但是因为每一个节点都需要额外保存父节点、孩子节点和红/黑性质,使得每一个节点都占用大量的空间
适用处:对于那些有顺序要求的问题,用map会更高效一些
unordered_map:
优点: 因为内部实现了哈希表,因此其查找速度非常的快
缺点: 哈希表的建立比较耗费时间
适用处:对于查找问题,unordered_map会更加高效一些,因此遇到查找问题,常会考虑一下用unordered_map
总结:
内存占有率的问题就转化成红黑树 VS hash表 , 还是unorder_map占用的内存要高。
但是unordered_map执行效率要比map高很多
对于unordered_map或unordered_set容器,其遍历顺序与创建该容器时输入的顺序不一定相同,因为遍历是按照哈希表从前往后依次遍历的
头文件
#include
函数
去重
unique()
unique(A.begin(),A.end())
//unique将相邻的重复元素移动到末尾,并不是直接删除,
//注意"相邻的",所以要先进行排序,保证重复元素相邻
//unique() 的返回值就是被后置元素的“首地址”(迭代器)
operator==
operator!=
operator<
operator<=
operator>
operator>=
/*
递归问题
3个瓶子换1瓶水+1个空瓶子,两个瓶子换1瓶水+0个空瓶子,1个瓶子换0瓶水。
f(1) = 0
f(2) = 1
f(3) = 1
f(4) = f(2)+1 //4个瓶子,其中3个可以换1瓶水+1个空瓶,所以是f(2)+1
f(5) = f(3)+1 //3个瓶子换1瓶水+1个空瓶,所以是f(3)+1
...
f(n) = f(n-2)+1 */
int f(int n)
{
if(n==1) return 0;
if(n==2) return 1;
return f(n-2)+1;
}
int main()
{
int n;
while(cin >> n)
{
if(n==0)
break;
cout<