十年网站开发经验+多家企业客户+靠谱的建站团队
量身定制+运营维护+专业推广+无忧售后,网站问题一站解决
目录
1.vector的介绍及使用
1.1vector的介绍
1.2vector的使用
1.2.1vector的定义
1.2.2vectoriterator的使用
1.2.3vector空间增长问题
1.2.3vector增删查改
1.2.4vector迭代器失效问题。(重点)
1.2.5vector在OJ中的使用
2.vector深度剖析及模拟实现
使用memcpy拷贝问题
动态二维数组理解
模拟实现vector:
我们可以看到这里的iterator行为上就像指针一样,但又不一定是指针,而对于vector这里来说,这里的iterator就是一个原生指针,后面会讲到迭代器失效的问题。
这里的resize和reserve和之前的string的含义一样,这里就看看函数的使用方式即可:
这是vs下的扩容:
reserve的优势就在于如果我们知道要开多少空间,我们就可以一次性开好,就可以避免频繁的扩容,因为我们知道频繁扩容是要付出代价的,所以C++在这方面做的很好。
上述内容很简单,查网站就会使用,不过多讲解,下面主要讲解迭代器失效的问题;
#includeusingnamespacestd;#includeintmain(){ vectorv{1,2,3,4,5,6}; autoit=v.begin(); v.assign(100,3); //因为这里扩容过,所以迭代器肯定失效 while(it!=v.end()) { cout<<*it<<""; ++it; } cout<结果正如我们所料:
解决这个办法就是更新一下迭代器即可正常使用。
看看其他例子:
intmain(){ inta[]={1,2,3,4}; vectorv(a,a+sizeof(a)/sizeof(int)); //使用find查找3所在位置的iterator vector::iteratorpos=find(v.begin(),v.end(),3); //删除pos位置的数据,导致pos迭代器失效。 v.erase(pos); cout<<*pos 我们可以在不是偶数的时候再++,同时更新一下it,是偶数的就不用++ intmain(){ vectorv{1,2,3,4}; autoit=v.begin(); while(it!=v.end()) { if(*it%2==0) it=v.erase(it); else { ++it; } } for(auto&e:v) { cout< 但是在Linux底下g++编译器就没有检查的那么严格: 看看扩容这段代码: //1.扩容之后,迭代器已经失效了,程序虽然可以运行,但是运行结果已经不对了intmain(){ vectorv{1,2,3,4,5}; for(size_ti=0;i 可以看到Linux底下是没有报错的,因为空间还是原来的空间,后序元素往前搬移了,it的位置还是有效的,但是对于刚刚那个偶数那题Linux下也会报错: 4.与vector类似,string在插入+扩容操作+erase之后,迭代器也会失效 最后说说如何解决这类问题: 因为数组在实际的应用非常广泛,所以C++的vector的运用也是非常多,而且嵌套vector远远比C语言中的二维数组好用,下面我们就来看看vector在oj中的应用: classSolution{public:vector>generate(intnumRows){//先开辟空间vector>vv;vv.resize(numRows);for(size_ti=0;i2.力扣 这道题如果使用哈希表的话就超出了这个空间复杂度了,用暴力查找的方式又不符合题意,这里有一个思路非常巧妙: 我们可以利用位运算来解决,因为这个除了这个数字其他的数字都出现过3次,我们可以把数组中的每一个数字的二进制位加起来,然后让结果%3就可以得到我们所想要的二进制位了,(不论是0还是1,%3的结果都是我们想要的那个数的二进制位),最后我们用ret每次接受一下要的到二进制位,就可以得到答案。 代码实现: classSolution{public:intsingleNumber(vector&nums){//我们可以把所有的二进制位全部加起来,然后%3就可以得到所求的数字的二进制位了intret=0;//我们要求的数字for(inti=0;i<32;++i){intsum=0;for(autoe:nums){sum+=((e>>i)&1);}//把要求的数字的二进制位找出来if(sum%3){ret|=(1<3.数组中出现次数超过一半的数字_牛客题霸_牛客网 思路:因为所出现的元素的个数超过了一般半,我们就可以通过计数的方式记录它,如果是这个元素就++,不是就--,最后得到的那个数一定是我们想要的数,另外,我们还可以拓展一下:如果这个数不一定存在那要怎么处理? 我们可以对这个记录一下这个数,然后再遍历一次数组,通过计数的方式去确认是否存在。 classSolution{public:intMoreThanHalfNum_Solution(vectornumbers){//因为所出现的元素的个数超过了一般半,我们就可以通过计数的方式记录它,如果是这个元素就++,不是就--//这样的话就可以在最后的时候找到这个元素inttmp=numbers[0];//记录我们要求的数据inttimes=1;for(inti=1;i4.力扣 这一题的难度比较大,运用到了回溯算法 思路: 我们可以通过一个数组来记录数字与字母之间的映射关系,然后利用回溯算法(递归)就解决像这种组合问题,下面通过这题来大概讲解一下回溯: 这个很像二叉树的遍历,但又复杂一点,这个可以看成多叉树的遍历方式。我们可以通过每一层的递归来达到一个组合的效果。 classSolution{//映射数组stringnumstr[10]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};public://递归子函数voidcombine(string&digits,inti,vector&vcombine,stringretstr){if(i==digits.size()){vcombine.push_back(retstr);return;}//找到对应的字母intnum=digits[i]-'0';stringstr=numstr[num];//遍历串中的所有字符,然后进入下一层for(autoch:str){combine(digits,i+1,vcombine,retstr+ch);}}vectorletterCombinations(stringdigits){vectorvcombine;if(digits.empty()){returnvcombine;}inti=0;stringretstr;//用来每次加,然后最后加到vcombine中//递归combine(digits,i,vcombine,retstr);returnvcombine;}};下面通过画递归展开图再来看看其中的细节: 这个和之前讲拷贝构造的时候很像,都是浅拷贝导致的问题。可能会引起内存泄漏甚至程序崩溃。 在前面就已经看过了二维数组的题了,这里不过多介绍,还是介绍一下memcpy也会使内存崩溃的结果: 要解决这个问题,我们还是要进行深拷贝,这是下面的reserve的模拟实现代码来解决这个问题: 我们可以通过这个一个对象赋值的方式来进行深拷贝 扩容是防止浅拷贝,所有把利用赋值来实现深拷贝。insert以及erase要注意更新迭代器,防止迭代器失效。 你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧