【C++/STL】vector的OJ,深度剖析和模拟实现
vector在OJ中的使用
1.只出现一次的数字
class Solution {
public:int singleNumber(vector<int>& nums) {int value = 0;for(auto e : v) {value ^= e; }return value;}
};
2.杨辉三角
class Solution {
public:vector<vector<int>> generate(int numRows){vector<vector<int>> vv;vv.resize(numRows);for (size_t i = 0; i < vv.size(); i++){vv[i].resize(i + 1, 0);vv[i][i] = vv[i][0] = 1;}for (size_t i = 0; i < vv.size(); i++){for (size_t j = 0; j < vv[i].size(); j++){if (vv[i][j] == 0){vv[i][j] = vv[i - 1][j - 1] + vv[i - 1][j];}}}return vv;}
};
3.删除有序数组中的重复项
class Solution {
public:int removeDuplicates(vector<int>& nums) {int p=0,q=1;while(q<nums.size()){if(nums[p]==nums[q]){q++;}else{nums[++p]=nums[q];q++;}}return p+1;}
};
4.数组中出现次数超过一半的数字
class Solution {
public:int MoreThanHalfNum_Solution(vector<int>& numbers) {sort(numbers.begin(),numbers.end());int count=0;int middle=numbers[numbers.size()/2];for(int i=0;i<numbers.size();i++){if(numbers[i]==middle){count++;}}return (count>numbers.size()/2)?middle:0;// write code here}
};
5.
class Solution
{string strA[10] = { "","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz" };
public:void Combine(string digits, int level, string combineStr, vector<string>& v){if (level == digits.size()){v.push_back(combineStr);return;}int num = digits[level] - '0';string str = strA[num];for (size_t i = 0; i < str.size(); i++){Combine(digits, level + 1, combineStr + str[i], v);}}vector<string> letterCombinations(string digits){vector<string> v;if (digits.empty()){return v;}Combine(digits, 0,"", v);return v;}
};
使用memcpy拷贝问题
int main()
{mm::vector<mm::string> v;v.push_back("1111");v.push_back("2222");v.push_back("3333");return 0;
}
假设模拟实现的vector中的reserve接口中,使用memcpy进行的拷贝,则:
1.memcpy是内存的二进制格式拷贝,将一段内存空间中的内容原封不动的拷贝到另一端内存中。
2.如果拷贝的是内置类型的元素,memcpy既高效又不会出错,但如果拷贝的是自定义类型元素,并且自定义类型元素中涉及到资源管理时,就会出错,因为memcpy的拷贝实际是浅拷贝。
结论:如果对象中涉及到资源管理时,千万不能使用memcpy进行对象之间的拷贝,因为memcpy是
浅拷贝,否则可能会引起内存泄漏甚至程序崩溃。
注意:vector是深拷贝。但vector空间上存的对象是string的数组,使用memcpy导致string对象的浅拷贝。
for(size_t i=0;i<v.size();i++)
{_start[i]=v._start[i];
}
解决方案: T是string这样深拷贝的类,调用的是string赋值重载,实现string对象的深拷贝。
vector的模拟实现
#pragma once
#include <assert.h>
#include <iostream>
#include <algorithm>
namespace Q
{template<class T>class vector{public:typedef T* iterator;typedef const T* const_iterator;iterator begin(){return _start;}iterator end(){return _finish;}const_iterator begin() const{return _start;}const_iterator end() const{return _finish;}// vector<int> v(10, 1);// vector<int> v(10u, 1);// vector<string> v1(10, "1111");//选择问题vector(size_t n, const T& val = T()){resize(n, val);}vector(int n, const T& val = T()){resize(n, val);}template <class InputIterator>vector(InputIterator first, InputIterator last){while (first != last){push_back(*first);++first;}}vector(const vector<T>& v){_start = new T[v.capacity()];//memcpy(_start,v._start,sizeof(T)*v.size());for (size_t i = 0; i < v.size(); i++){_start[i] = v._start[i];}/*_finish = v._finish;_endofstorage = v._endofstorage;*/_finish = _start + v.size();_endofstorage = _start + v.capacity(); }/*vector(const vector<T>& v){reserve(v.capacity());for (auto e : v){push_back(e);}}*/void swap(vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_endofstorage, v._endofstorage);}vector<T>& operator=(vector<T> v){swap(v);return *this;}~vector(){if (_start){delete[] _start;_start = _finish = _endofstorage = nullptr;}}void reserve(size_t n){if (n > capacity()){size_t sz = size();T* tmp = new T[n];if (_start){for (size_t i = 0; i < sz; i++){tmp[i] = _start[i];}delete[] _start;}_start = tmp;_finish = _start + sz;_endofstorage = n;}}void resize(size_t n, const T& val = T()){if (n < size()){_finish = _start + n;}else{reserve(n);while (_finish != _start + n){*_finish = val;_finish++;}}}void push_back(const T& x){/*if (_finish == _endofstorage){size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;reserve(newcapacity);}*_finish = x;_finish++;*/insert(end(), x);}void pop_back(){erase(--end());}size_t capacity() const{return _endofstorage - _start;}size_t size() const{return _finish - _start;}T& operator[](size_t pos) {assert(pos < size());return _start[pos];}const T& operator[](size_t pos) const{assert(pos < size());return _start[pos];}iterator insert(iterator pos, const T& x){assert(pos >= _start && pos <=_finish);if (_finish == _endofstorage){size_t len = pos - _start;size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;reserve(newcapacity);pos = _start + len;}iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;end--;}*pos = x;_finish++;return pos;}iterator erase(iterator pos){assert(pos >= _start && pos < _finish);iterator it = pos + 1;while (it != _finish){*(it - 1) = *it;it++;}_finish--;return pos;}private:iterator _start = nullptr;iterator _finish = nullptr;iterator _endofstorage = nullptr;};void print(){for (auto e : v){cout << e << " ";}cout << endl;}
}