C++ 刷题语法整理

本文目的:记录刷题时常用库函数,STL等,只涉及语法,不涉及具体的算法:
标题为遇到的时间顺序排列,并无先后之分

一、关联容器的语法

unordered_set,multiset,set插入元素:
如setrecord;
record.insert(1);
record.insert(3);
record.insert(2);
三个容器插入都用insert,区别在于遍历的时候:for(auto e:set)cout<<e<<endl;
由于multiset,set底层通过红黑树实现,会对里面元素进行排序(通过红黑树实现的不能修改其中键值,顺序会乱,只能删了再加),而unordered_set底层通过哈希表实现
因此unordered_set遍历时与插入顺序相反,为231(可能是插入的时候从指向begin迭代器往前插?)
而multiset,set会将其排序(升序),为123
而multiset与set的区别是如果再插入个1,遍历multiset时就会是1123,而set仍然是123,因为set有去重特性,而multiset允许重复

unordered_map,multimap,map与其的区别在于:
1.
multimap,map只能通过insert(),如:
multimap<int,int>record;
record.insert({3,2});
unordered_map,map插入时除了insert(),还通过[],如
map<int,int>record;
record[1]++;
或者map<int,char>record;
record[1]=‘a’;

2.在用auto遍历时,如:
for(auto e:record)得到的e为pair类型,不能直接cout,(重载<<之后可以),要通过e.first来访问key,e.second来访问value
3.map与multimap的升序排列是按照key来排列

    int test1[3];
    
    multiset<int>test2;
    test2.insert(1);
    test2.insert(3);
    test2.insert(2);
    
    multimap<int,int>test3;
    test3.insert({1,1});
    test3.insert({3,1});
    test3.insert({2,1});
    
    cout<<sizeof(test1)<<endl;//12
    cout<<sizeof(test2)<<endl;//unordered__set56,set48,multiset48
    cout<<sizeof(test3)<<endl;//unordered_map56,map48,multimap48

一个整型4个字节,所以cout<<sizeof(test1)<<endl;显示12
set48,一个e占16,

二、substr()与reverse()

substr()是C++语言函数,主要功能是复制子字符串,要求从指定位置开始,并具有指定的长度。如果没有指定长度_Count或_Count+_Off超出了源字符串的长度,则子字符串将延续到源字符串的结尾。——摘自百科词条

语法
substr(size_type _Off = 0,size_type _Count = npos)
一种构造string的方法
形式 : s.substr(pos, len)
返回值: string,包含s中从pos开始的len个字符的拷贝(pos的默认值是0,len的默认值是s.size() - pos,即不加参数会默认拷贝整个s)
异常 :若pos的值超过了string的大小,则substr函数会抛出一个out_of_range异常;若pos+n的值超过了string的大小,则substr会调整n的值,只拷贝到string的末尾

比如反转字符串二,用substr截取一段字符串
去进行反转,对原字符串不会产生影响,需要搭配引用才能对原字符串产生影响

如将"the sky is blue"去掉空格压在栈中/vector中使用word+=s[i];比用substr更简单,只用维护一个变量i,而substr需要维护两个变量start与end

for(int i=0;i<=s.size()-1;i++)
    {
   if(s[i]==' ')continue;//确保每个单词的开头不是空格
    if(i==s.size()-1||s[i+1]==' ')//当遍历到最后一个字符以及下一个字符是空格时需要收集单词
    {
        word+=s[i];//这样比用substr更简单,只用维护一个变量i,而substr需要维护两个变量start与end
        result1.push_back(word);
        word="";
        i=i+1;
        continue;
    }
    if(s[i]!=' ')
    word+=s[i];
    }

左旋转字符串
输入: s = “abcdefg”, k = 2
输出: “cdefgab”

string reverseLeftWords(string s, int n) {
    reverse(s.begin(),s.begin()+n);
    reverse(s.begin()+n,s.end());
    reverse(s.begin(),s.end());
    return s;
    }

reverse左开右闭合,即反转左参数到右参数前一个之间区间的容器

三,容器方法的名称对比

使用表格将各种STL的类似操作的用法和名称进行一个直观的对比:

返回头部元素返回尾部元素头部插入尾部插入x弹出
queue q1q1.front()q1.back()\(队尾)q1.push(x)q1.pop()
stack s1s1.top()\(栈顶)s1.push(x)\s1.pop()
vector v1v1.front()v1.back()\v1.push_back(x)只能尾插v1.pop_back()只能尾弹

四、栈的pop()

stacks1;
s1.push(1);
s1.pop();√
int result=s1.pop();×
C++中stack,其中有两个方法:

pop(), 返回void,

top(),返回栈顶的引用。

看起来非常pop函数非常的浪费,为什么不再pop是返回值呢。

主要有两个原因:

安全原因:

假设有这个stack类

class Stack
{
public:

T pop();    //let pop to change the stack's internal state and return the top element

};

这么使用

Stack stack;

stack.push(object);

Object obj=stack.pop() ;

当我们执行Object obj=stack.pop() 时,Object的构造函数被调用,而这里是可以反生异常的,

假设这时候发生异常,丢生的栈顶元素就回不去了。

效率原因:

当一个栈顶元素被弹出后,我们不得不返回这个元素的值(而不是引用),因此接收这个值的一方Object obj必然发生一次实例化。

而不同的是top函数不弹出元素,因此可以返回引用,也就不必发生实例化。

所以为了兼顾效率,pop不返回任何数据。
参考:https://blog.csdn.net/sxyizhiren/article/details/42506823

五、分割字符串

C++没有python那样方便的spilt()函数,遇到需要分割字符串时使用getline(istream && is,string&str,char delim),如
力扣71.简化路径

这个函数的作用将输入流的字符串按照分割符delim为界分割出来。

c++网站上的介绍是:

从流获取线到字符串:
1.从提取的字符是并将其存储到STR直到划界字符DELIM被发现(getline (istream&& is, string& str)默认分割符是“\ n”, )。
2.如果到达文件末尾,或者在输入操作过程中出现其他错误,则提取也会停止。
3.如果找到分隔符,则将其提取并丢弃(即不存储,下一个输入操作将在其后开始)。
4.请注意,调用之前的str中的任何内容都被新提取的序列替换。
5.每个提取的字符都附加到该字符串,和使用push_back()的效果一样。

六、string当栈用

比如题目要返回一个字符串,用栈接收之后再遍历栈给赋值到字符串上,比较浪费时间,更推荐使用一个string当做栈来使用

string result;
result.push_back("a");//入栈
string temp=result.back();//显示栈顶元素
result.pop_back();//出栈

七、通过map的value进行排序

在一中我们说到map默认是通过key进行排序,但有些时候想通过value进行排序,比如:
前K个高频元素
做法如下:
01,在类外定义数据类型(非必要):

typedef pair<int, int> pii;

02,想直接用sort排序是做不到的,sort只支持数组、vetctor等的排序,所以我们可以先把map装进pair里,然后再放入vector,自定义sort实现排序

static bool cmp(pii a,pii b)
    {
        return a.second > b.second;//按照pii的第二个元素从大到小排序
    }

cmp写在类内的话一定要加static,原因如下:
为什么cmp函数在作为类成员函数的时候一定需要static修饰呢?这是因为所有我们在类内定义的非static成员函数在经过编译后隐式的为他们添加了一个this指针参数!变为了:

bool cmp(Solution *this, int a, int b)

而标准库的sort()函数的第三个cmp函数指针参数中并没有这样this指针参数,因此会出现输入的cmp参数和sort()要求的参数不匹配,从而导致了:

error: reference to non-static member function must be called

而我们知道static静态类成员函数是不需要this指针的,因此改为静态成员函数即可通过!
参考:https://blog.csdn.net/weixin_40710708/article/details/111269356

   vector<pii>vc;//用于按照map的value进行排序

03.将哈希表record给塞入刚刚定义的vc中,再使用自定义的cmp进行排序

    for(auto e:record)
    vc.push_back(e);
    sort(vc.begin(),vc.end(),cmp);

八、访问multimap同一key的value

multimap与map的区别在于multimap的key可以重复,即一个key可以对应多个value,
电话号码中开始想用multimap来存储不同号码对应的value,可以这样写:

    multimap<int,char>record;;
    record.insert({2,'a'});
    record.insert({2,'b'});
    auto it=record.equal_range(2);
    for(auto pt=it.first;pt!=it.second;pt++)
    cout<<pt->second<<endl;//a endl b

直接用equal_range方法返回用pair封装的两个迭代器,it.first为第一个迭代器,it.second为第二个迭代器,这两个迭代器之间的范围是键为2的范围,在这个范围中遍历时访问其second即可以访问multimap同一key的value。

所以还是

 const string letterMap[10] = {
        "", // 0
        "", // 1
        "abc", // 2
        "def", // 3
        "ghi", // 4
        "jkl", // 5
        "mno", // 6
        "pqrs", // 7
        "tuv", // 8
        "wxyz", // 9
    };

更方便哈哈哈

九、vector的初始化

vector<vector<int>>result={{}};

打印出来:[[]]

vector<int>result={};

打印出来:[]

十、ACM模式的输入输出

输入是个字符串,如’ABCD’:

#include<string>
string name;
getline(cin, name);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值