【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(一)】-创新互联
网站地址:http://ybzwz.com/article/codjho.html