【ONE·C++||vector(一)】-创新互联

总言

  学习笔记,慢慢补充。

成都创新互联主要从事成都网站制作、网站设计、外贸网站建设、网页设计、企业做网站、公司建网站等业务。立足成都服务平山,10年网站建设经验,价格优惠、服务专业,欢迎来电咨询建站服务:18980820575文章目录
  • 总言
  • 1、整体介绍:
  • 2、常用各种接口介绍
    • 2.1、vector的基本结构:构造、析构、赋值
      • 2.1.1、总体情况预览
      • 2.1.2、各项函数使用演示
    • 2.2、vector增删查改相关
      • 2.2.1、增删查改总览
      • 2.2.2、如何在vector中插入、删除、遍历数据
      • 2.2.3、front、back函数
    • 2.3、vector扩容相关
      • 2.3.1、容量问题总览
      • 2.3.2、resize、reserve函数介绍
    • 2.4、其它一些函数介绍
      • 2.4.1、find、insert函数介绍
      • 2.4.2、erase函数介绍
      • 2.4.3、vector排序问题:sort
    • 2.5、一些现象、问题说明
      • 2.5.1、一个问题讨论:vector存储char字符与string的比较
      • 2.5.2、vector与string结合使用:vector< string >
  • 3、相关练习题:
    • 3.1、只出现一次的数字
    • 3.2、杨辉三角:vector>嵌套使用
    • 3.3、删除有序数组中的重复项
    • 3.4、电话号码的字母组合

  
  

1、整体介绍:

   该文章参考网站是cplusplus.com。
在这里插入图片描述
  1、vector是类模板,其有两个模板参数class Tclass Alloc = allocator
  2、class Alloc = allocator:空间配置器(内存池)。默认配置了一个缺省参数,由库提供这个内存池。若自己有设计想法,也可自己显示实现。

  
  

2、常用各种接口介绍 2.1、vector的基本结构:构造、析构、赋值 2.1.1、总体情况预览

  1)、构造函数总览

在这里插入图片描述
在这里插入图片描述
  
  
  2)、析构函数总览
   vector的析构函数,出了作用域自动调用。
在这里插入图片描述

  
  
  3)、赋值运算符重载总览
   赋值运算符重载就涉及到后续深浅拷贝的问题。
在这里插入图片描述

  
  4)、小结
   上述几个函数中,
      ①对构造函数,使用最多的是无参构造、拷贝构造。
      ②对析构函数调用默认的即可,故不用太过理会。
      ③对赋值运算符重载,偶尔用到。
  
  
  
  

2.1.2、各项函数使用演示

  1)、演示构造函数:

  ①由下述代码可知,vector是一个类模板,因此需要显示实例化(详细学习请见模板初阶)。

template< class T, class Alloc = allocator>class vector;

  ②以下即为常见的vector的构造用法:

void test_vector01()
{vectorv1;//无参构造
	vectorv2(5, 10);//n个val
	vectorv3(v2);//拷贝构造
}

  ③通过调试观测如下:需要注意的是,对于vector的构造函数,后续我们在模拟实现时仍旧要解决深浅拷贝的问题。

在这里插入图片描述

  
  
  
  

2.2、vector增删查改相关 2.2.1、增删查改总览

在这里插入图片描述

  
  

2.2.2、如何在vector中插入、删除、遍历数据

  1)、对数据插入、删除:
   根据上述总览,目前我们知道可以使用push_backpop_backinserterase来达成数据的插入删除。

vectorv1;//构造一个vector,名为v1
		v1.push_back(1);//尾插
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);

  
  2)、对数据的遍历:

在这里插入图片描述方式一:下标+[ ]

   相关函数:
在这里插入图片描述
在这里插入图片描述
   代码演示:

//遍历演示
		for (size_t i = 0; i< v1.size(); ++i)//vector::size
		{	cout<< v1[i]<< " ";//vector::operator[]
		}
		cout<< endl;

		//下标访问,遍历自增
		for (size_t i = 0; i< v1.size(); ++i)
		{	v1[i]++;
		}

		//再次遍历
		for (size_t i = 0; i< v1.size(); ++i)//vector::size
		{	cout<< v1[i]<< " ";//vector::operator[]
		}
		cout<< endl;

在这里插入图片描述
  
  

在这里插入图片描述方式二:迭代器

   代码演示:

//使用迭代器遍历:需要注意的是这里迭代器对应的vector使用了模板参数
		vector::iterator it = v1.begin();
		while (it != v1.end())
		{	cout<< *it<< " ";
			++it;
		}
		cout<< endl;

在这里插入图片描述
   涉及函数:
在这里插入图片描述

   支持迭代器,就支持范围for:

//使用范围for
		for (auto e : v1)
		{	cout<< e<< " ";
		}
		cout<< endl;

在这里插入图片描述

  
  

2.2.3、front、back函数

  1)、简介:
   获取vector首元素和尾元素。 关于front和back二者的使用请见下述练习3.2。

在这里插入图片描述

  

2.3、vector扩容相关 2.3.1、容量问题总览

在这里插入图片描述

  
  

2.3.2、resize、reserve函数介绍

  1)、扩容机制的验证

//扩容机制验证
	void TestVectorExpand()
	{size_t sz;
		vectorv;
		sz = v.capacity();

		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';
			}
		}
	}

  此处是以VS2019为例的运行结果:
在这里插入图片描述

  
  2)、reserve、rsize介绍
   在已知要插入的数据量的情况下,我们可以提前扩容:

void TestVectorExpand()
	{size_t sz;
		vectorv;
		//v.resize(100);//resize在开空间的同时还会进行初始化,影响size。
		v.reserve(100);//reserve只负责开辟空间,可缓解vector增容的代价缺陷问题。
		sz = v.capacity();

		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';
			}
		}
	}

   在上述场景中不能使用resize,因为resize在开辟空间的同时进行初始化数据。假如上述场景中使用了resize,相当于我已经在resize的帮助下拥有了100个数据,后续的for循环又为我提供了100个数据。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  
  

2.4、其它一些函数介绍 2.4.1、find、insert函数介绍

  1)、对algorithm
   在vector中,可以看到并没有单独的find函数,是因为我们完全可以用[ ]来做到,另者,如果有需要,algorithm库中提供了find函数。

在这里插入图片描述
  同理,vector也不像string一样提供流插入、流提取。因为我们对vector的一般是遍历访问,而string有整体打印字符串的需求。
  
  
  2)、对vector::insert
   vector中insert的用法说明:注意iterator position,其使用的是迭代器。

iterator is a member type, defined as a random access iterator type that points to elements.

在这里插入图片描述
  
  3)、使用演示

vectorv1;//构造一个vector,名为v1
		v1.push_back(1);//尾插
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);

		//使用find在v1中查找值:范围[v1.begin(),v1.end()),val=3
		vector::iterator pos = find(v1.begin(), v1.end(), 3);
		if (pos != v1.end())//检查是否找到相关值。此处find的last=v1.end()
		{	v1.insert(pos,30);
		}
		//遍历:用于检测是否成功插入数据
		for (auto e : v1)
		{	cout<< e<< " ";
		}
		cout<< endl;

在这里插入图片描述
  
  
  4)、一个边界说明
   如下图,分析现象并说明原因:

在这里插入图片描述

   原因:在v1中寻找300,find返回结果为v1.end()下标,相当于尾插。
   说明:虽然此处没有明确报错现象,但使用find找到值后最好还是检查一下。
  
  

2.4.2、erase函数介绍

  1)、对erase
在这里插入图片描述

  2)、使用演示:

vectorv1;//构造一个vector,名为v1
		v1.push_back(1);//尾插
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);

		//使用find在v1中查找值:范围[v1.begin(),v1.end()),val=3
		vector::iterator pos = find(v1.begin(), v1.end(), 3);
		if (pos != v1.end())//检查是否找到相关值。此处find的last=v1.end()
		{	v1.erase(pos);//删除单个元素
		}
		
		//遍历:用于检测是否成功插入数据
		for (auto e : v1)
		{	cout<< e<< " ";
		}
		cout<< endl;

在这里插入图片描述

  3)、不检查find返回值情况验证:
   如下图所示:报错。

在这里插入图片描述
  
  
  

2.4.3、vector排序问题:sort

  1)、基本介绍
   ①sort也是一个函数模板,其底层使用的原理是快排,默认排的是升序。
在这里插入图片描述
  
  2)、sort排升序

//乱序
		vectorv1;
		v1.push_back(11);
		v1.push_back(23);
		v1.push_back(6);
		v1.push_back(1);
		v1.push_back(9);
		v1.push_back(7);
		v1.push_back(3);
		v1.push_back(15);
		//排升序
		sort(v1.begin(), v1.end());
		//遍历查看
		vector::iterator it = v1.begin();
		while (it != v1.end())
		{	cout<< *it<< " ";
			it++;
		}
		cout<< endl;

在这里插入图片描述
  
  3)、sort排降序
   sort排降序涉及到Compare comp仿函数,此处我们只需要学习使用方法:
   两个函数介绍:less、greater

介绍:
		less也是一个类模板,int为此处需要的数据类型
		greater同上,但使用greater需要包含头文件。
		less不需要包含的这个头文件的原因是,sort默认升序。
		

		#includelessls;
		greatergt;
		
		//sort(v1.begin(), v1.end(), ls);
		sort(v1.begin(), v1.end(), gt);

在这里插入图片描述
  当然,上述只是一种写法介绍,也可以按照下述写法进行:

sort(v1.begin(), v1.end(), greater());

  此处相当于匿名对象的使用。

在这里插入图片描述

  
  
  4)、sort在string中的使用演示

string s("hello string 1144579");
		sort(s.begin(), s.end());
		cout<< s<< endl;

   sort在string中是按照ASCII码排序的:

在这里插入图片描述

   也可以排降序:

string s("hello string 1144579");
		sort(s.begin(), s.end(), greater());
		cout<< s<< endl;

在这里插入图片描述

  
  
  

2.5、一些现象、问题说明 2.5.1、一个问题讨论:vector存储char字符与string的比较

   问题描述:

vectorv;
		string s;

   上述二者有什么差异?能否用前者代替后者?
   回答:
   ①string中s后面默认追加\0;
   ②相比于vector,string中的相关函数比较多,实现功能也更全,比如+=(一个字符/字符串),流插入流提取,find(查字符串),比较大小、to_string等。
  
  
  

2.5.2、vector与string结合使用:vector< string >
//void push_back (const value_type& val);
		//void push_back (const T& val);

		vectorstrV;

		string str1("张龙");
		strV.push_back(str1);//深拷贝:push_back中val为什么要加&的原因

		strV.push_back(string("赵虎"));//匿名对象:push_back中val为什么要加const的原因

		strV.push_back("王朝");//日常使用习惯:隐式类型转换
//for (auto str : strV)
		//{//	cout<< str<< endl;
		//}
		
		//1、这里也涉及一个深浅拷贝的问题,所以需要十分谨慎处理
		//2、如果不涉及改变内容,可以加上const
		for (const auto& str : strV)
		{	cout<< str<< endl;
		}

在这里插入图片描述

  
  
  

3、相关练习题: 3.1、只出现一次的数字

   题源
在这里插入图片描述
   代码如下:

class Solution {public:
    int singleNumber(vector& nums) {int value=0;
        for(auto e:nums)
        {value^=e;//异或
        }
        return value;
    }
};

   要满足时间复杂度O(n),空间复杂度O(1),最简单的方式就是使用异或。
   其余不满足上述条件下,也可以使用排序遍历、直接遍历等方法。
  
  
  

3.2、杨辉三角:vector>嵌套使用

   题源

在这里插入图片描述
  
   关键点: 理解vector>的含义。
在这里插入图片描述

   代码如下:

class Solution {public:
    vector>generate(int numRows) {vector>vv;//定义一个vector>类型的数据
        vv.resize(numRows);//第一次开辟空间:numRows,表示总行数(整体大小)
        for(size_t i=0;ivv[i].resize(i+1,0);//第二次开辟空间,表示初始化杨辉三角的每行大小
            vv[i].front()=vv[i].back()=1;//杨辉三vv.size()角每行首尾数据为1

            //vv[i].resize(i+1,1);//上述代码也可以合并为一行实现
        }

        for(size_t i=2;ifor(size_t j=1;jvv[i][j]=vv[i-1][j-1]+vv[i-1][j];
            }
        }

        return vv;
    }
};

vv[i][j]的理解如下:双层嵌套
在这里插入图片描述

  
  
  

3.3、删除有序数组中的重复项

   题源
在这里插入图片描述

  1)、写法说明
   此题我们曾用C语言写过:

int removeDuplicates(int* nums, int numsSize){int src,det;
det=0;src=1;
while(srcif(nums[src]!=nums[det])
    {nums[++det]=nums[src];
    }
    src++;
}
return det+1;
}

   如果用C++写呢?
  使用vector下,本质区别还是不变。

class Solution {public:
    int removeDuplicates(vector& nums) {int src,det;
    det=0;src=1;
    while(srcif(nums[src]!=nums[det])
        {nums[++det]=nums[src];
        }
        src++;
    }
    return det+1;
    }
};

  2)、一点扩展
   在上述用C++写的代码中,我们只是做了挪动数据的处理,假如我们要求挪动数据后,并把之后那些无效数据都删除,该如何操作呢?
   此处就可以借助vector中的resize函数:当我们输入的n小于原先vector的size时,会保留n个数据空间,并把n之后的容量空间删除。

nums.riseze(det+1);//此处det+1是因为我们输入的n是数据个数,而det标记的是下标。

  
  
  

3.4、电话号码的字母组合

   题源
在这里插入图片描述

   此题的整体思路是循环控制递归。
  

class Solution {//numToStr:主要是用于映射2-9数字对应的字母
    char* numToStr[10]={" "," ","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
    //string numToStr[10]={"","","abc","def","ghi"."jkl","mno","pqrs","tuv","wxyz"};

public:

    //digits:系统输入的数字字符串
    //di:这些字符串对应的顺序:第一个、第二个
    //retV:用于存储获取的排列组合,总数目
    //combineStr:用于存储单次递归获取的组合
    void Combine(string digits,int di,vector& retV,string combineStr)
    {if(di==digits.size())
        {retV.push_back(combineStr);
            return;
        }
        
        int num=digits[di]-'0';//将输入的数字字符转换为数字
        string str=numToStr[num];//当前数字对应的字母
        for(auto ch :str)
        {Combine(digits,di+1,retV,combineStr+ch);
        }
    }



    vectorletterCombinations(string digits) {vectorv;
        if(digits.empty())//如果输入的字符串为空时
        {return v;
        }
        string str;
        Combine(digits,0,v,str);
         return v;
    }
};

  
  
  
  
  

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧

本文题目:【ONE·C++||vector(一)】-创新互联
文章位置:https://www.cdcxhl.com/article40/codjho.html

成都网站建设公司_创新互联,为您提供云服务器营销型网站建设网站内链搜索引擎优化微信小程序电子商务

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

绵阳服务器托管