文章目录为什么要转CC语言基础C如何输入输出Cstring相关去除前导空格提取和拼接子串一些常用的C操作Csort(排序函数的用法)数组去重二分查找STL容器相关常见的STL容器使用常见队列栈map(键值对)set(集合)C进阶相关结语为什么要转C首先对于C语言它初见虽然简单但是深入后确实非常的难并且不方便的。例如C语言使用排序qsort必须要写排序函数但是用C的std::sort就很方便而且对于一些常见的数据结构C也有相对应的STL容器如:queuestackvector最重要的还是C在C11之前和C语言相差不大如果仅仅是打算法竞赛那么CC STL转起语言来几乎完全没有压力C语言基础对于初学者而言我们只需要记住如下代码#includebits/stdc.husingnamespacestd;intmain(void){return0;}初看这个和C语言极为相似除了using namespace std;和#include bits/stdc.h对于using namespace std;我们只需要记住不需要了解如果有人想了解的话可以去搜下C的命名空间然后对于#include bits/stdc.h是C的万能头(竞赛专用你下的gcc里面是没有这个的需要额外配置)后续内容中如果学习C只为了打算法竞赛那么后续所有头文件都不需要记忆C如何输入输出#includeiostream#includestringusingnamespacestd;intmain(void){intn;string s;cinn;cins;coutn\nsendl;}上述头文件的iostream就相当于C的stdio.h而string是C特有的字符串对象其中C输入为scanf而且还需要记住类似于%d,%s之类的格式化符号而C之间cin就可以了输出的话直接coutCstring相关对于C语言我们处理字符串很痛苦(虽然C也很痛苦)但C处理字符串却比C语言简单多了以下列举一些本人常用的字符串处理方法去除前导空格#includeiostream#includestringusingnamespacestd;intmain(void){string s;while(getline(cin,s)){intposs.find_first_not_of( );s.erase(0,pos);std::couts\n;}std::couthello , world;}提示C的cin会自动去除掉前导空格如果是去除前导0的话直接把 换成0就可以了提取和拼接子串#includeiostream#includestringusingnamespacestd;intmain(void){string shello , world;//从第0个位置开始截取长度为5的子串string s1s.substr(0,5);//从第6个位置开始截取后面的所有字符string s2s.substr(6);//将s1和s2拼接位一个字符串string s3s1s2;//运行下二者输出的结果相同couts1s2\n;couts3;}string截取子串的成员函数为substr相关解释已经在注释当中一些常用的C操作Csort(排序函数的用法)#includealgorithm#includeiostream#includestringusingnamespacestd;boolcomp(inta,intb){returnab;}intmain(void){inta[1000]{0,1,1,4,5,1,4};//这个sort第一个参数是这是你要排序的起始位置第二个参数是终止位置sort(a1,a16);for(inti1;i6;i)couta[i];//C排序默认的升序std::cout\n;//如果我们要用降序的话可以添加第三个参数也就是我们的自定义比较函数sort(a1,a16,comp);for(inti1;i6;i)couta[i];}C的sort排序的时间复杂度是O(nlogn)比大家常用的冒泡排序快速多了所有如果要有排序的话推荐一直用这个至于comp函数我这里使用了也就是引用这样可以避免复制数值但是大家在平时使用时不添加引用符也可以正常运行数组去重#includealgorithm#includeiostream#includestring#includevectorusingnamespacestd;intmain(void){//使用原始数组的方法//数组去重需要我们先排序inta[1000]{0,1,1,4,5,1,4};sort(a1,a16);//这里去重int*posunique(a1,a16);//这里计算去重后的数组个数intnew_countpos-(a1);for(inti1;inew_count;i)std::couta[i] ;}//如果不打算了解C进阶相关这下面部分可以不看#includealgorithm#includeiostream#includevectorintmain(void){//使用vector(动态数组的做法)std::vectorintarr{0,1,1,4,5,1,4};//这里至于为什么使用arr.begin()这里暂不讲解在进阶部分再讲解std::sort(arr.begin()1,arr.begin()16);//这里返回的是一个迭代器autoposunique(arr.begin()1,arr.begin()16);arr.erase(pos,arr.end());return0;}unique函数返回的是检查范围的数据如果有相同的则移到传入的末尾之后直接计算剩余元素数量后使用去重过后的数组就行了详细操作见上述代码二分查找#includealgorithm#includeiostream#includevector#includestack#includequeue#includemap#includesetusingnamespacestd;intmain(void){//这里为了演示我这边就直接用有序数组了inta[105];for(inti1;i100;i)a[i]i;//查找第一个小于等于25的元素int*lb1std::lower_bound(a1,a101,25);intindex1lb1-a;// 计算索引std::coutelem is*(lb1) index isindex1endl;//查找第一个大于25的元素int*lb2std::upper_bound(a1,a101,25);intindex2lb2-a;// 计算索引std::coutelem is*(lb2) index isindex2endl;int*resultstd::lower_bound(a1,a101,101);//二分超出范围的话if(resulta101){std::coutlower_bound(101) return a101\n;// 因为数组中没有不小于101的元素}return0;}STL容器相关常见的STL容器使用这部分设计数据结构例如:栈队列红黑树二叉搜索树常见队列#includealgorithm#includeiostream#includequeue#includevectorintmain(void){std::queueintq;//这里模拟插入数据for(inti0;i10;i)q.push(i);//一般我们是不知道队列里面的元素个数的所以我们一般用while语句来处理//这里的empty返回的是一个bool变量,如果不了可以理解为true 1(判断为真),false 0(判断为假)while(!q.empty()){//队列可以查看队头和队尾的元素//其中队头的元素是第一个被插入的元素std::coutq.front() q.back()\n;//这里默认弹出队头元素q.pop();}//双端队列和普通队列的区别就是可以弹出和插入元素到队头和队尾的任意一部分std::dequeintqu;for(inti0;i10;i){qu.push_back(i);//qu.push_front(i);}while(!qu.empty()){std::coutqu.front() qu.back()\n;//弹出队尾qu.pop_back();//弹出队首qu.pop_front();}}C的队列使用和声明极为简单,其中内部实现为一个数组是根据先进先出(FIFO)思想设计的所有上述操作时间复杂度都为O(1)如果使用了using namespace std;那么上述的的std::可以去掉栈#includealgorithm#includeiostream#includevector#includestack#includequeueusingnamespacestd;intmain(void){stackints;for(inti0;i10;i)s.push(i);while(!s.empty()){//默认弹出最后一个元素std::couts.top() ;s.pop();}}栈和队列的使用方式差不多最具有分辨力的区别是:栈是根据先进后出(FILO)的思想设计的map(键值对)键值对又称字典,是一个相互进行映射(一个键对应一个值)的STL容器内部实现为红黑树或(二叉搜索树)其插入的时间复杂度为O(logn)是一个在算法竞赛中很实用的STL容器#includealgorithm#includeiostream#includevector#includestack#includequeue#includemapusingnamespacestd;intmain(void){std::mapint,intmp;inttemp114514;for(inti0;i10;i){//插入数据(这两种方法都可以)if(i4)mp[i]temp*(10-i);elsemp.insert({i,temp*(10-i)});}//遍历mapfor(auto[key,value]:mp){//这里的key代表第一个也就是键第二个代表值这两个可以随意命名std::coutmp[key] value\n;//遍历是根据键的大小来输出的也可以自定义排序(属于进阶内容新手不必要掌握)}//查找操作其中时间复杂度为O(logn)if(mp.find(2)!mp.end())std::coutYes;if(mp.find(10)mp.end())std::coutNo;std::cout\n;intidx0;while(1){mp.erase(idx);idx;if(mp.empty()){std::cout已弹出所有元素;break;}}return0;}我们这里只讲map的插入删除和遍历以及查找这种基础内容还有一种map是unordered_map其结构和map很像这里不再介绍。unordered_map和map的区别是map是红黑树而它的实现为哈希表查找插入的速度为O(1)并且unordered_map是无序的set(集合)set和map极为相似你可以把set理解为只有一个value的的map(一般map有键和值)其中时间复杂度和map基本一致这里不再介绍#includealgorithm#includeiostream#includevector#includestack#includequeue#includemap#includesetusingnamespacestd;intmain(void){setints;for(inti0;i100;i)s.insert(0);s.insert(5);s.insert(3);s.insert(114514);//set里面是自动有序而且是会自动去重的for(autoi:s)couti ;cout\n;if(s.find(3)!s.end())coutYes ;if(s.find(6)s.end())coutNo ;cout\n;//查看集合的大小couts.size()\n;for(autoi:s)s.erase(i);couts.size()\n;return0;}C进阶相关标准输入输出加快ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);lambda表达式(无名函数)std::vectorintarr{1,1,4,5,1,4};std::sort(arr.begin(),arr.end(),[](inta,intb){returnab;});这里只不过是将函数换成了lambda表达式优先对列自定义排序structNode{intx,y;booloperator(Nodea)const{returnxa.x;};};intmain(void){std::priority_queueNodeq;}对于我们自定义的结构体它是无法直接比较大小的那么直接使用operator进行重载可以使它们在一个陌生的结构体有明确的大小顺序由于作者赖的写了这里简单的介绍下优先队列。优先队列就是我们所说的堆其中内部是二叉搜索树插入和弹出都是logn的复杂度堆顶元素默认是最大(最小)元素stringstream流#includevector#includestring#includesstream#includeiostreamusingnamespacestd;intmain(void){//将字符类型转化为整数std::string s1 2 3 4 5 6;std::vectorintarr;stringstreamstream(s);intnum;while(streamnum){arr.push_back(num);}for(autoi:arr)couti ;cout\n;//将数据为某个字符串分割string dataapple,banana,orange,grape;stringstreamss(data);string fruit;while(getline(ss,fruit,,))coutfruitendl;return0;}结语以上内容属于C基础内容如果以后有从事C相关行业的话属于基础中的基础相反则需要掌握一些C基础内容虽然文章中分为了基础和进阶但即便是只打算打一些简单的算法比赛以上编码技巧也只属于基础内容