吴江做网站,深圳网站建设送域名,网站加视频,文山知名网站建设报价1.vector的介绍及使用
1.1 vector的介绍
vector的文档介绍 vector是表示可变大小数组的序列容器。 就像数组一样#xff0c;vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问#xff0c;和数组一样高效。但是又不像数组#xff0c…1.vector的介绍及使用
1.1 vector的介绍
vector的文档介绍 vector是表示可变大小数组的序列容器。 就像数组一样vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问和数组一样高效。但是又不像数组它的大小是可以动态改变的而且它的大小会被容器自动处理。 本质讲vector使用动态分配数组来存储它的元素。当新元素插入时候这个数组需要被重新分配大小为了增加存储空间。其做法是分配一个新的数组然后将全部元素移到这个数组。就时间而言这是一个相对代价高的任务因为每当一个新的元素加入到容器的时候vector并不会每次都重新分配大小。 vector分配空间策略vector会分配一些额外的空间以适应可能的增长因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何重新分配都应该是对数增长的间隔大小以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。 因此vector占用了更多的存储空间为了获得管理存储空间的能力并且以一种有效的方式动态增长。 与其它动态序列容器相比deque, list and forward_list vector在访问元素的时候更加高效在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作效率更低。比起list和forward_list统一的迭代器和引用更好。
1.2 vector的使用
push_back的用法
#include iostream
#include vector
using namespace std;void test_vector1()
{// 使用int实例化一个vector对象vectorint v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);for (size_t i 0; i v.size(); i){cout v[i] ;}cout endl;// 使用迭代器打印容器中的数据vectorint::iterator it v.begin();while (it ! v.end()){cout *it ;it;}cout endl;// 使用for循环打印容器中的数据for (auto e : v){cout e ;}cout endl;// 打印容器的最大存储容量cout v.max_size() endl;//vectorchar vstr; // vector并不可以替代string//string str;
}reserve的用法
void test_vector2()
{vectorint v;// 向容器中尾插数据// void push_back (const value_type val);v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);cout v.capacity() endl; // 打印结果为6// 调整容器的大小v.reserve(10);cout v.capacity() endl; // 打印结果为10// 比当前容量小时不缩容v.reserve(4);cout v.capacity() endl; // 打印结果为10// 调整容器size的大小v.resize(8);v.resize(15, 1);v.resize(3);
}// vector的扩容机制
void TestVectorExpand()
{size_t sz;vectorint v;// 提前预留空间在已知将要插入多少数据量v.reserve(100);sz v.capacity();cout sz endl;cout making v grow:\n;for (int i 0; i 100; i){v.push_back(i);if (sz ! v.capacity()){sz v.capacity();cout capacity changed: sz \n;}}
}size和[]重载
// size只有一个接口为const接口size只需要提供读的功能
// size_type size() const;// operator[]提供了两个接口operator[]要有读和写的功能
// reference operator[] (size_type n);
// const_reference operator[] (size_type n) const;
void Func(const vectorint v)
{v.size();v[0];// 错误演示, v被const修饰因此调用的接口为const_reference operator[] (size_type n) const;// 因此v[0]是不可以被修改的// v[0]; // Returns a reference to the element at position n in the vector.// 返回vector中n下标位置的元素的引用// reference 就是类型 value_type// reference at (size_type n);// const_reference at (size_type n) const;v.at(0);
}
// 总结
// 1.只读接口函数。const 如size()
// 2.只写接口函数。非const 如push_back()
// 3.可读可写的接口函数。const非const; 如operator[]void test_vector3()
{vectorint v;v.push_back(1);v.push_back(2);v.push_back(3);v.size();v[0];v[0];v.at(0);Func(v);
}operator[]和at()越界的区别
// operator[]和at()越界的区别就是一个是assert一个是抛异常
void test_vector4()
{vectorint v;//v.reserve(10);v.resize(10);for (size_t i 0; i 10; i){v[i] i; // assert // v.at(i) i; // 抛异常// v.push_back(i);}
}assign的用法
// assign()
// template class InputIterator
// void assign (InputIterator first, InputIterator last);
// 新内容是由范围内的每个元素构建的元素顺序相同从第一个元素到最后一个元素。// void assign (size_type n, const value_type val);
// 这个版本的 assign() 函数接受一个整数参数 count 和一个值 value它会用 count 个 value 值来替换容器中的元素
void test_vector5()
{vectorint v;v.push_back(1);v.push_back(2);v.push_back(3);for (auto e : v){cout e ;}cout endl;// 对应 void assign (size_type n, const value_type val);v.assign(10, 1); for (auto e : v){cout e ;}cout endl;vectorint v1; v1.push_back(10);v1.push_back(20);v1.push_back(30);// 对应template class InputIterator // void assign (InputIterator first, InputIterator last);// 将v容器中的元素替换为v1容器中begin指针到end指针之间的元素v.assign(v1.begin(), v1.end());for (auto e : v){cout e ;}cout endl;string str(hello world);v.assign(str.begin(), str.end()); //有迭代器就可以使用for (auto e : v){cout e ;}cout endl;v.assign(str.begin(), --str.end());for (auto e : v){cout e ;}cout endl;
}find、insert、swap的用法
// std::find的源码
/*template class InputIterator, class TInputIterator find (InputIterator first, InputIterator last, const T val);The behavior of this function template is equivalent to:
templateclass InputIterator, class T
InputIterator find (InputIterator first, InputIterator last, const T val)
{while (first!last) {if (*firstval) return first;first;}return last;
}
*/void test_vector6()
{vectorint v;v.push_back(1);v.push_back(2);v.push_back(3);v.insert(v.begin(), 4);v.insert(v.begin()2, 4);//vectorint::iterator it v.find(3);vectorint::iterator it find(v.begin(), v.end(), 3);if (it ! v.end()){v.insert(it, 30);}for (auto e : v){cout e ;}cout endl;vectorint v1;v1.push_back(10);v1.push_back(20);v1.push_back(30);// 专门为vector写的非成员函数就是为了防止调用算法库中的swap(),哪个需要将交换的对象实例化代价太大
// std::swap (vector) // 使用这个swap就相当于调用 v1.swap(v);// template class T, class Alloc
// void swap (vectorT,Alloc x, vectorT,Alloc y);v1.swap(v); swap(v1, v); // std::swap (vector)对swap的重载
}void test_vector7()
{vectorint v;v.reserve(10);v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);cout v.size() endl;cout v.capacity() endl;// 设计理念不动空间不去缩容 空间换时间v.reserve(5);cout v.size() endl;cout v.capacity() endl;v.resize(3);cout v.size() endl;cout v.capacity() endl;v.clear();cout v.size() endl;cout v.capacity() endl;// 设计理念时间换空间一般缩容都是异地代价不小一般不要轻易使用v.push_back(1);v.push_back(2);v.push_back(3);// 这个函数的功能就是v.shrink_to_fit();cout v.size() endl;cout v.capacity() endl;
}int main()
{try{test_vector4();}catch (const exception e){cout e.what() endl;}//TestVectorExpand();return 0;
}// 增push_back 不直接头插需要挪动数据效率低建议少用 偶尔头插,使用insert(v.begin(),val)
// 删pop_back 不直接头删需要挪动数据效率低建议少用 偶尔头删,使用erase(v.begin())
// 查算法库的find
// 改迭代器 []习题
只出现一次的数字 分析
// (按位与) 都为1则按位与为1有0则按位与为0// 按位与
//00000000000000000000000000000011 - 3的补码正数的原码补码反码相同
// //10000000000000000000000000000101 - -5的原码
// //11111111111111111111111111111010 - -5的反码符号位不变其他位按位取反
//
// //11111111111111111111111111111011 - -5的补码
// //00000000000000000000000000000011 - 3的补码
// //00000000000000000000000000000011 - 后的补码(放到内存中的都是补码);// |按位或 有1则按位或为1都为0则按位或为0
// 00000000000000000000000000000011 - 3的补码正数的原码补码反码相同
// 10000000000000000000000000000101 - -5的原码
// 11111111111111111111111111111010 - -5的反码符号位不变其他位按位取反
//
// 11111111111111111111111111111011 - -5的补码
// 00000000000000000000000000000011 - 3的补码
// 11111111111111111111111111111011 - |按位或 后的补码(放到内存中的都是补码)// ^按位异或 相同则按位异或为0相反则按位异或为1
// 00000000000000000000000000000011 - 3的补码正数的原码补码反码相同
// 10000000000000000000000000000101 - -5的原码
// 11111111111111111111111111111010 - -5的反码符号位不变其他位按位取反
//
// 11111111111111111111111111111011 - -5的补码
// 00000000000000000000000000000011 - 3的补码
// 11111111111111111111111111111000 - ^按位异或后的补码(放到内存中的都是补码)// 任何数按位异或0都等于它本身 如 a^0 a
// 任何数按位异或其本身都等于0 如 a^a 0
// 3^3^5 5
// 3^5^3 5
//由以上可得异或操作符支持交换律class Solution {
public:int singleNumber(vectorint nums) {int ret 0;// 范围forfor(auto e : nums){// 数组中只有一个数据是单个其余数据都是两两一组且相等// 又因为a^0 a// a^a 0// a^b^c a^c^b 按位异或 的复合交换律ret ^ e;}return ret;}
};杨辉三角 class Solution {
public:vectorvectorint generate(int numRows){// 先创建一个二维数组的vector对象存放的数据为intvectorvectorint vv;// 确定vector的大小;// 使用resize可以对其初始化如果不传参会使用缺省参数vv.resize(numRows);// 像遍历二维数组一样将相应的数值进行存储// vv.size()代表的就是二维数组的行数// 因为在vv中一个元素的大小就是vectorint的大小for(size_t i 0; i vv.size(); i){// 确定vectorint的大小并初始化// void resize (size_type n, value_type val value_type());// 调整容器的大小使其包含 n 个元素。 // 如果新的大小大于当前大小则容器将增加到 n 个元素并用可选的第二个参数 value 的值进行填充。vv[i].resize(i1,0);// 边界的数值填充// 左边界就是vv[i][0] 右边界是vv[i][vv[i].size() - 1]vv[i][0] vv[i][vv[i].size() - 1] 1;}// 杨辉三角一共有vv.size()行每一行有vv[i].size()列for(size_t i 0; i vv.size(); i){for(size_t j 0; j vv[i].size(); j){// 如果值为1为边界的值不用处理// 如果值为0这个值的大小等于左上方的值加上右上方的值if(vv[i][j] 0){vv[i][j] vv[i-1][j] vv[i-1][j-1];}}}return vv;}
};电话号码的字母组合 // 解题思路
class Solution {// 2~9所有数字对应的字符string _numStr[10] {, , abc, def, ghi, jkl, mno, pqrs, tuv, wxyz};public:void Combine(const string digits, int i, vectorstring vCombine, string combinestr) {// 当i等于digits.size()时迭代完成// 将已经组合好的字符串combinestr尾插到vCombine中if(i digits.size()) {vCombine.push_back(combinestr);return;}// 第一次迭代// digits[i]是字符的ASCLL值因此需要减去字符0才可以拿到相应的数// num就是电话号码的第一个数字int num digits[i] - 0; // 将电话号码第一个数字对应的字符串存储到str中string str _numStr[num]; // 遍历strfor(auto ch : str) {// 开始迭代// 经过for循环会将str存储的所有字符串都执行一次 Combine层层递归直到i digits.size()为真结束Combine(digits, i1, vCombine, combinestr ch); } } // 题目给出的接口vectorstring letterCombinations(string digits){// 用来存储组合好的字符串vectorstring vCombine;// 如果没有输入字符则返回一个空的vectorstring; // 特殊的,作单独处理if(digits.empty()){return vCombine;}// i为string digits的下标size_t i 0;// str是用来存储组合起来的字符串的// 对应这个构造函数string(); 这个构造的对象为空串string str; // digit是题目给我们的数字这些数字存放在字符串当中// i是字符串中字符对应的下标Combine(digits, i, vCombine, str);return vCombine;}
};2.vector深度剖析及模拟实现 vector的私有成员变量
iterator _start; // 指向数组的起始位置
iterator _finish; // _finish _start size(); 指向数组的末尾指向末尾元素的下一个元素
iterator _endofstorage; // _endofstorage _start capacity(); 数组的容量指向数组容量的末尾末尾的下一个元素迭代器
typedef T* iterator;
typedef const T* const_iterator; // 普通迭代器
iterator begin()
{return _start;
}iterator end()
{return _finish;
}// const迭代器
const_iterator begin() const
{return _start;
}const_iterator end() const
{return _finish;
}operator[]重载
// 普通重载operator[]
T operator[](size_t pos)
{assert(pos size());return _start[pos];
}// const重载operator[]
const T operator[](size_t pos) const
{assert(pos size());return _start[pos];
}默认构造函数
// 默认构造函数
vector()
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{}// n可以为负数这种方法不建议
// vectorint v1(10, 1); // 10为int类型1为int类型
// vectorint v1(10, 1) 匹配 vector(int n, const T val T())// size_t 不会有负数建议使用这种构造方法
// vectorchar v1(10, A); // 10为int类型A为char类型
// vectorchar v1(10, A) 匹配 vector(size_t n, const T val T())
// int会发生整型提升提升为size_t类型
// 用n个val值来填充容器vector(int n, const T val T())
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{reserve(n);for (int i 0; i n; i){push_back(val);}
}vector(size_t n, const T val T())
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{reserve(n);for (size_t i 0; i n; i){push_back(val);}
}拷贝构造函数
// 传统的拷贝构造的写法
// v2(v1)
/*
vector(const vectorT v)
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{reserve(v.capacity());for (const auto e : v){push_back(e);}
}*/// 现代写法的拷贝构造
// v1(v2)
template class InputIterator
vector(InputIterator first, InputIterator last)
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{// 用迭代器的方法将v2的数据一个一个插入到v1中while (first ! last){push_back(*first);first;}
}// v1(v2)
vector(const vectorT v)
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{// 使用上述的现代写法的拷贝构造函数将v2的数据拷贝给tmpvectorT tmp(v.begin(), v.end()); // 将v的数据拷贝到tmp// 交换tmp和v1的成员变量swap(tmp);
}void swap(vectorT v)
{std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_endofstorage, v._endofstorage);
}operator
// v1 v2
// 这里的vectorT v 是v2的拷贝
vectorT operator(vectorT v)
{// v出了作用域就会被销毁// 交换v和v1swap(v);return *this;
}reserve, 扩容
// 扩容
void reserve(size_t n)
{// 如果将要扩容的容量n大于原有的容量capacity()那么就要进行扩容但是如果将要扩容的容量n小于原有的容量capacity()那么不进行处理不会进行缩容if (n capacity()){// 此处必须将size()的返回值进行存储// 如果_start被改变则size()的返回值也会被改变size()的返回值就是_start与_finsh两个指针之间元素的个数size_t oldSize size();// tmp是扩容后新空间的地址T* tmp new T[n];if (_start){// 将旧空间的数据按字节拷贝到新空间memcpy(tmp, _start, sizeof(T)*oldSize); // 将原空间的数据拷贝到新空间delete[] _start; // 将原空间释放}// 更新成员变量_start tmp; _finish tmp oldSize; // 指针整型 指针 指针1 就会跳过 T* 个字节的地址_endofstorage _start n;}
}resize()调整数组的大小
// 设置数据个数的大小并对扩容空间进行初始化初始化使用val进行初始化
void resize(size_t n, T val T())
{// 如果n capacity()则需要先进行扩容if (n capacity()) {reserve(n);}if (n size()){// size()位置到n位置的数据进行初始化也就是对n-size()个数据初始化// 即n-(_finish - _start) 0while (_finish _start n) {*_finish val;_finish;}}else{// 当n size()时令 n size()即可也就是 n _finish - _start_finish _start n;}
}尾插尾删
void push_back(const T x)
{// 如果数组的大小与数组的容量相等那么要插入就需要进行扩容if (_finish _endofstorage){size_t newCapacity capacity() 0 ? 4 : capacity() * 2;reserve(newCapacity);}*_finish x;_finish;
}void pop_back()
{assert(!empty());--_finish;
}insert任意位置插入
// 迭代器失效 : 扩容引起野指针问题
iterator insert(iterator pos, const T val)
{// pos只是形参 this-_start; this-_finishassert(pos _start);assert(pos _finish);// 扩容容量满了需要进行扩容if (_finish _endofstorage){// 记录起始位置和pos位置之间的长度size_t len pos - _start;size_t newCapacity capacity() 0 ? 4 : capacity() * 2;reserve(newCapacity);// 这里如果不更新pos就会导致野指针// 扩容之后编译器可能会重新分配新的空间pos还指向原来的空间也就是野指针// 扩容会导致pos迭代器失效需要更新处理一下pos _start len;}// 挪动数据将pos以及pos位置后的数据向后挪动一个位置// _finish 指向数组最后一个元素的下一个位置// _finish - 1 指向数组的最后一个元素iterator end _finish - 1;while (end pos) {*(end 1) *end;--end;}*pos val;_finish;// 返回更新之后的pos指针这里的pos指针是主函数的形参必须返回更新主函数的pos实参return pos;
}erase任意位置删除
iterator erase(iterator pos)
{assert(pos _start);assert(pos _finish);// 将pos位置后的所有数据向前挪动iterator begin pos1;while (begin _finish){*(begin-1) *(begin);begin;}--_finish;// 返回更新之后的pos指针这里的pos指针是主函数的形参必须返回更新主函数的pos实参return pos;
}3.vector的完整实现
// vector.h
#pragma once
namespace qwy
{templateclass Tclass vector{public:typedef T* iterator; typedef const T* const_iterator; // 普通迭代器iterator begin(){return _start;}iterator end(){return _finish;}// const迭代器const_iterator begin() const{return _start;}const_iterator end() const{return _finish;}// 普通重载operator[]T operator[](size_t pos){assert(pos size());return _start[pos];}// const重载operator[]const T operator[](size_t pos) const{assert(pos size());return _start[pos];}// 默认构造函数vector():_start(nullptr), _finish(nullptr), _endofstorage(nullptr){}// n可以为负数这种方法不建议// vectorint v1(10, 1); // 10为int类型1为int类型// vectorint v1(10, 1) 匹配 vector(int n, const T val T())// size_t 不会有负数建议使用这种构造方法// vectorchar v1(10, A); // 10为int类型A为char类型// vectorchar v1(10, A) 匹配 vector(size_t n, const T val T())// int会发生整型提升提升为size_t类型// 用n个val值来填充容器vector(int n, const T val T()):_start(nullptr), _finish(nullptr), _endofstorage(nullptr){reserve(n);for (int i 0; i n; i){push_back(val);}}vector(size_t n, const T val T()):_start(nullptr), _finish(nullptr), _endofstorage(nullptr){reserve(n);for (size_t i 0; i n; i){push_back(val);}}// 传统的拷贝构造的写法// v2(v1)/*vector(const vectorT v):_start(nullptr), _finish(nullptr), _endofstorage(nullptr){reserve(v.capacity());for (const auto e : v){push_back(e);}}*/// 现代写法的拷贝构造// v1(v2)template class InputIteratorvector(InputIterator first, InputIterator last):_start(nullptr), _finish(nullptr), _endofstorage(nullptr){// 用迭代器的方法将v2的数据一个一个插入到v1中while (first ! last){push_back(*first);first;}}vector(const vectorT v):_start(nullptr), _finish(nullptr), _endofstorage(nullptr){vectorT tmp(v.begin(), v.end()); // 将v的数据拷贝到tmpswap(tmp);}// v1 v2// v1 v1; // 极少数情况能保证正确性所以这里就这样写没什么问题vectorT operator(vectorT v){swap(v);return *this;}// 析构函数~vector(){delete[] _start;_start _finish _endofstorage nullptr;}// 扩容void reserve(size_t n){if (n capacity()){// 此处必须将size()的返回值进行存储// 如果_start被改变则size()的返回值也会被改变size()的返回值为_start与_finsh的差值size_t oldSize size();T* tmp new T[n];if (_start){memcpy(tmp, _start, sizeof(T)*oldSize); // 将原空间的数据拷贝到新空间delete[] _start; // 将原空间释放}_start tmp; _finish tmp oldSize;_endofstorage _start n;}}// 设置数据个数的大小并对其初始化void resize(size_t n, T val T()){if (n capacity()) // 如果n capacity()则需要先进行扩容{reserve(n);}if (n size()){// size()位置到n位置的数据进行初始化也就是对n-size()个数据初始化// 即n-(_finish - _start) 0while (_finish _start n) {*_finish val;_finish;}}else{// 当n size()时令 n size()即可也就是 n _finish - _start_finish _start n;}}bool empty() const{return _finish _start;}size_t size() const{return _finish - _start;}size_t capacity() const{// 指针-指针 两个指针之间元素的个数return _endofstorage - _start;}void push_back(const T x){if (_finish _endofstorage){size_t newCapacity capacity() 0 ? 4 : capacity() * 2;reserve(newCapacity);}*_finish x;_finish;}void pop_back(){assert(!empty());--_finish;}// 迭代器失效 : 扩容引起野指针问题iterator insert(iterator pos, const T val){// pos只是形参 this-_start; this-_finishassert(pos _start);assert(pos _finish);// 扩容if (_finish _endofstorage){size_t len pos - _start;size_t newCapacity capacity() 0 ? 4 : capacity() * 2;reserve(newCapacity);// 扩容之后编译器可能会重新分配新的空间pos还指向原来的空间也就是野指针// 扩容会导致pos迭代器失效需要更新处理一下pos _start len;}// 挪动数据iterator end _finish - 1;while (end pos) {*(end 1) *end;--end;}*pos val;_finish;return pos;}iterator erase(iterator pos){assert(pos _start);assert(pos _finish);iterator begin pos1;while (begin _finish){*(begin-1) *(begin);begin;}--_finish;return pos;}void swap(vectorT v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_endofstorage, v._endofstorage);}void clear(){_finish _start;}private:iterator _start; iterator _finish; // _finish _start size()iterator _endofstorage; // _endofstorage _start capacity()};void test_vector1(){vectorint v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);for (size_t i 0; i v.size(); i){cout v[i] ;}cout endl;vectorint::iterator it v.begin();while (it ! v.end()){cout *it ;it;}cout endl;for (auto e : v){cout e ;}cout endl;v.pop_back();v.pop_back();v.pop_back();v.pop_back();v.pop_back();for (auto e : v){cout e ;}cout endl;}void test_vector2(){vectorint v;v.resize(10, -1);for (auto e : v){cout e ;}cout endl;v.resize(5);for (auto e : v){cout e ;}cout endl;}void test_vector3(){vectorint v;//v.reserve(10);v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);for (size_t i 0; i v.size(); i){cout v[i] ;}cout endl;v.insert(v.begin(), 0);for (auto e : v){cout e ;}cout endl;// 算法库中的find// template class InputIterator, class T// InputIterator find (InputIterator first, InputIterator last, const T val);vectorint::iterator it find(v.begin(), v.end(), 3);if (it ! v.end()){v.insert(it, 30);}for (auto e : v){cout e ;}cout endl;}void test_vector4(){vectorint v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);// 算法库中的findvectorint::iterator it find(v.begin(), v.end(), 3);if (it ! v.end()){v.insert(it, 30);}// insert以后 it还能否继续使用 -- 不能可能迭代器失效野指针// insert以后实参it并不会发生改变但是形参pos会发生改变形参改变并不会影响实参// (*it);// *it * 100;for (auto e : v){cout e ;}cout endl;}// 算法库实现的测试-- 最后发现程序崩溃了// 这是由于v.erase(it)调用之后 it就失效了因此我们需要去更新it即it v.erase(it)void test_vector5(){std::vectorint v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);// it失效还是不失效(这里一定会失效具体原因详细看erase的模拟实现)std::vectorint::iterator it find(v.begin(), v.end(), 3);if (it ! v.end()){v.erase(it);}// 读 (在vs下会失效)cout *it endl;// 写 (在vs下会失效)(*it);for (auto e : v){cout e ;}cout endl;}// 算法库中实现的erase()的测试 //void test_vector6()//{// // 要求删除所有偶数// std::vectorint v;// v.push_back(1);// v.push_back(2);// v.push_back(2);// v.push_back(3);// v.push_back(4);// std::vectorint::iterator it v.begin();// while (it ! v.end())// {// if (*it % 2 0)// {// it v.erase(it);// }// else// {// it;// }// }// for (auto e : v)// {// cout e ;// }// cout endl;//}// 我们自己实现的erase()的测试void test_vector6(){// 要求删除所有偶数vectorint v;v.push_back(1);v.push_back(2);v.push_back(2);v.push_back(3);v.push_back(4);//v.push_back(5);vectorint::iterator it v.begin();while (it ! v.end()){if (*it % 2 0){// 这里更新it指针那么pos就不会失效// erase(iterator pos)it v.erase(it);}else{it;} }for (auto e : v){cout e ;}cout endl;}// 测试拷贝构造void test_vector7(){vectorint v;v.push_back(1);v.push_back(2);v.push_back(2);v.push_back(3);v.push_back(4);vectorint v1(v);for (auto e : v1){cout e ;}cout endl;vectorint v2;v2.push_back(10);v2.push_back(20);v1 v2;for (auto e : v1){cout e ;}cout endl;v1 v1;for (auto e : v1){cout e ;}cout endl;}void test_vector8(){std::string str(hello);vectorint v(str.begin(), str.end());for (auto e : v){cout e ;}cout endl;//vectorint v1(v.begin(), v.end());vectorint v1(10, 1);//vectorchar v1(10, A);for (auto e : v1){cout e ;}cout endl;}// 测试杨辉三角// 杨辉三角的实现程序class Solution {public:vectorvectorint generate(int numRows) {vectorvectorint vv;vv.resize(numRows);for (size_t i 0; i vv.size(); i){vv[i].resize(i 1, 0);vv[i][0] vv[i][vv[i].size() - 1] 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] vv[i - 1][j - 1];}}}return vv;}};// 需要注意的问题如void test_vector9()void test_vector10(){vectorstring v;v.push_back(1111111111111111111111111111);v.push_back(1111111111111111111111111111);v.push_back(1111111111111111111111111111);v.push_back(1111111111111111111111111111);v.push_back(1111111111111111111111111111);for (auto e : v){cout e ;}cout endl;}// 测试杨辉三角void test_vector9(){// 内部运行原理// vv的类型是vectorvectorint 给vv中插入5个vv的类型是vectorint// v中开辟5个空间每个空间初始化为1// 根据我们写的底层原理插入第5个数据的时候程序会进行扩容// 扩容时会调用reserve()函数如果reserve()函数中使用memcopy()来拷贝原空间的数据到扩容的新空间但是这个新空间是vv的新空间vv中的v指向的还是原来的空间并没有给v开辟新空间并将v的数据拷贝到新空间v的指针_start,_finish,_endofstorage是在vv中// 拷贝数据之后就会将v指向的原空间释放但是没有给v开辟新空间并将将数据拷贝// 解决方案// 将memcopy()函数拷贝替换为// for (size_t i 0; i oldSize; i)// {// tmp[i] _start[i]; // 对应 vectorT operator(vectorT v)// }// 这样就可以将v的数据拷贝到新空间原空间被释放并不会对现在的v指向的空间有影响vectorvectorint vv;vectorint v(5, 1);vv.push_back(v);vv.push_back(v);vv.push_back(v);vv.push_back(v);vv.push_back(v);for (size_t i 0; i vv.size(); i){for (size_t j 0; j vv[i].size(); j){cout vv[i][j] ;}cout endl;}cout endl;}
}// test.cpp
int main()
{try{bit::test_vector9();}catch (const exception e){cout e.what() endl;}return 0;
}测试杨辉三角(使用自己的vector)
// 测试杨辉三角下面的代码使用我自己的vector容器会报错具体原因如下改进方式如下void test_vector9(){// 内部运行原理// vv的类型是vectorvectorint 给vv中插入5个vv的类型是vectorint// v中开辟5个空间每个空间初始化为1// 根据我们写的底层原理插入第5个数据的时候程序会进行扩容// 扩容时会调用reserve()函数如果reserve()函数中使用memcopy()来拷贝原空间的数据到扩容的新空间但是这个新空间是vv的新空间vv中的v指向的还是原来的空间并没有给v开辟新空间并将v的数据拷贝到新空间v的指针_start,_finish,_endofstorage是在vv中// 拷贝数据之后就会将v指向的原空间释放但是没有给v开辟新空间并将将数据拷贝// 解决方案// 将memcopy()函数拷贝替换为// for (size_t i 0; i oldSize; i)// {// tmp[i] _start[i]; // 对应 vectorT operator(vectorT v)// }// 这样就可以将v的数据拷贝到新空间原空间被释放并不会对现在的v指向的空间有影响vectorvectorint vv;vectorint v(5, 1);vv.push_back(v);vv.push_back(v);vv.push_back(v);vv.push_back(v);vv.push_back(v);for (size_t i 0; i vv.size(); i){for (size_t j 0; j vv[i].size(); j){cout vv[i][j] ;}cout endl;}cout endl;}
文章转载自: http://www.morning.bnlkc.cn.gov.cn.bnlkc.cn http://www.morning.tkrpt.cn.gov.cn.tkrpt.cn http://www.morning.qbgff.cn.gov.cn.qbgff.cn http://www.morning.rlzxr.cn.gov.cn.rlzxr.cn http://www.morning.snzgg.cn.gov.cn.snzgg.cn http://www.morning.gpsrk.cn.gov.cn.gpsrk.cn http://www.morning.pswzc.cn.gov.cn.pswzc.cn http://www.morning.ryglh.cn.gov.cn.ryglh.cn http://www.morning.hpxxq.cn.gov.cn.hpxxq.cn http://www.morning.ygkk.cn.gov.cn.ygkk.cn http://www.morning.huayaosteel.cn.gov.cn.huayaosteel.cn http://www.morning.dmrjx.cn.gov.cn.dmrjx.cn http://www.morning.wnmdt.cn.gov.cn.wnmdt.cn http://www.morning.tpnxr.cn.gov.cn.tpnxr.cn http://www.morning.srckl.cn.gov.cn.srckl.cn http://www.morning.wxwall.com.gov.cn.wxwall.com http://www.morning.qtyfb.cn.gov.cn.qtyfb.cn http://www.morning.sfqtf.cn.gov.cn.sfqtf.cn http://www.morning.kaoshou.net.gov.cn.kaoshou.net http://www.morning.kkqgf.cn.gov.cn.kkqgf.cn http://www.morning.tcfhs.cn.gov.cn.tcfhs.cn http://www.morning.xrnh.cn.gov.cn.xrnh.cn http://www.morning.njfgl.cn.gov.cn.njfgl.cn http://www.morning.demoux.com.gov.cn.demoux.com http://www.morning.lbrwm.cn.gov.cn.lbrwm.cn http://www.morning.rnlx.cn.gov.cn.rnlx.cn http://www.morning.dqcpm.cn.gov.cn.dqcpm.cn http://www.morning.zpqbh.cn.gov.cn.zpqbh.cn http://www.morning.mqxzh.cn.gov.cn.mqxzh.cn http://www.morning.djlxz.cn.gov.cn.djlxz.cn http://www.morning.bhgnj.cn.gov.cn.bhgnj.cn http://www.morning.qrqg.cn.gov.cn.qrqg.cn http://www.morning.blqsr.cn.gov.cn.blqsr.cn http://www.morning.hwxxh.cn.gov.cn.hwxxh.cn http://www.morning.fzqfb.cn.gov.cn.fzqfb.cn http://www.morning.fgkrh.cn.gov.cn.fgkrh.cn http://www.morning.wyjhq.cn.gov.cn.wyjhq.cn http://www.morning.lktjj.cn.gov.cn.lktjj.cn http://www.morning.qzpw.cn.gov.cn.qzpw.cn http://www.morning.psxcr.cn.gov.cn.psxcr.cn http://www.morning.kdjtt.cn.gov.cn.kdjtt.cn http://www.morning.zqdzg.cn.gov.cn.zqdzg.cn http://www.morning.fdfdz.cn.gov.cn.fdfdz.cn http://www.morning.ldspj.cn.gov.cn.ldspj.cn http://www.morning.nyqxy.cn.gov.cn.nyqxy.cn http://www.morning.mbfkt.cn.gov.cn.mbfkt.cn http://www.morning.datadragon-auh.cn.gov.cn.datadragon-auh.cn http://www.morning.ptzf.cn.gov.cn.ptzf.cn http://www.morning.plhyc.cn.gov.cn.plhyc.cn http://www.morning.ptlwt.cn.gov.cn.ptlwt.cn http://www.morning.yhtnr.cn.gov.cn.yhtnr.cn http://www.morning.xckqs.cn.gov.cn.xckqs.cn http://www.morning.xjtnp.cn.gov.cn.xjtnp.cn http://www.morning.nxtgb.cn.gov.cn.nxtgb.cn http://www.morning.nkhdt.cn.gov.cn.nkhdt.cn http://www.morning.srrrz.cn.gov.cn.srrrz.cn http://www.morning.rczrq.cn.gov.cn.rczrq.cn http://www.morning.jygsq.cn.gov.cn.jygsq.cn http://www.morning.dgfpp.cn.gov.cn.dgfpp.cn http://www.morning.dbtdy.cn.gov.cn.dbtdy.cn http://www.morning.qbccg.cn.gov.cn.qbccg.cn http://www.morning.ftmp.cn.gov.cn.ftmp.cn http://www.morning.nkhdt.cn.gov.cn.nkhdt.cn http://www.morning.xnqwk.cn.gov.cn.xnqwk.cn http://www.morning.rknhd.cn.gov.cn.rknhd.cn http://www.morning.bctr.cn.gov.cn.bctr.cn http://www.morning.yltyr.cn.gov.cn.yltyr.cn http://www.morning.pntzg.cn.gov.cn.pntzg.cn http://www.morning.ydrml.cn.gov.cn.ydrml.cn http://www.morning.bbyqz.cn.gov.cn.bbyqz.cn http://www.morning.qwwcf.cn.gov.cn.qwwcf.cn http://www.morning.xhqr.cn.gov.cn.xhqr.cn http://www.morning.fplqh.cn.gov.cn.fplqh.cn http://www.morning.jgykx.cn.gov.cn.jgykx.cn http://www.morning.fksrg.cn.gov.cn.fksrg.cn http://www.morning.lhldx.cn.gov.cn.lhldx.cn http://www.morning.sqdjn.cn.gov.cn.sqdjn.cn http://www.morning.qgmbx.cn.gov.cn.qgmbx.cn http://www.morning.lynmt.cn.gov.cn.lynmt.cn http://www.morning.nyfyq.cn.gov.cn.nyfyq.cn