C++ vector

国庆放假第二天,奥利给,继续干。

看一下vector的构造函数:

C++ vector_第1张图片

 (1)默认构造函数:

vector  s1();

(2)复制初始化构造:

	vector  s2(10, 3);

(3)范围区间构造:

甚至可以用string的begin,end:

	string v1("hello");
	vector  s3(v1.begin(), v1.end());

遍历

operator[ ]

利用下标实现遍历:

	
	string v1("hello");


    for (size_t i = 0; i < v1.size(); i++)
	{
		
		cout << v1[i] << " ";

		
	}
	cout << endl;

迭代器



	string v1("hello");
	vector  s3(v1.begin(), v1.end());


	vector::iterator it = s3.begin(); 
	while (it != s3.end()) {
		cout << *it << " ";
		it++;
	}
	cout << endl;

 因为是,所以输出的是“hello”的ASCII码值:

如果把vector的模版类型改为char的话输出的就是“hello”:

范围for


	string v1("hello");
	vector  s3(v1.begin(), v1.end());

	for (auto h1 : s3)
	{
		cout << h1 << " ";
	}
	cout << endl;

 课习题(1)

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

解析:

C++ vector_第2张图片

vector扩容

扩容要用的函数参考:

C++ vector_第3张图片

如下代码:

	vector s1;
	auto sz = s1.capacity();
	for (size_t i = 0; i < 100; i++)
	{
		s1.push_back(i);
		
		if (sz != s1.capacity())
		{
			sz = s1.capacity();
		cout << "扩容:" << s1.capacity() << endl;
		}
	}

C++ vector_第4张图片

if (sz != s1.capacity())
        {
            sz = s1.capacity();
    
        }    

这个if语句的作用是什么呢?

如果删掉if语句运行:

C++ vector_第5张图片

 它会没执行一次循环就扩容一次,最后扩容一百次,if语句的作用就是限制了扩容,让它只有在空间不够的条件下菜扩容。

观察扩容的数字规律:发现它是一次扩容1.5的(受内存对齐影响看起来不完全是1.5倍扩容)。

我们看g++下的扩容规律:C++ vector_第6张图片

我们发现它是二倍扩容的关系。

reserve和resize

同样一段代码,用reserve和resize的运行结果区别:

	vector s1;
	auto sz = s1.capacity();
	//s1.reserve(100);
	//s1.resize(100);
	cout << "开空间:" << s1.capacity() << endl;
	for (size_t i = 0; i < 100; i++)
	{
        s1[i]=i;
		
		if (sz != s1.capacity())
		{
			sz = s1.capacity();
cout << "扩容:" << s1.capacity() << endl;
		}		

 reserve:

resize:

 因为reserve只是提前开空间,开的空间够用了就不再扩容了,它不会往里面写值。

但是resize是size和capacity都扩到了100,并且会实际往里面写入值,写100个int需要400个字节,所以还需要接着扩容。

用reserve开辟100个空间,然后遍历一下,打印出来:




	vector s1;
	auto sz = s1.capacity();
	s1.reserve(100);
	//s1.resize(100);
	cout << "开空间:" << s1.capacity() << endl;
	for (size_t i = 0; i 

 这是因为reserve只把capacity开辟了100个空间,但是size还是0:

那么强行写入呢?既然空间已经开出来了,那直接往里面写入会怎么样:



	vector s1;
	auto sz = s1.capacity();
	s1.reserve(100);
	//s1.resize(100);
	cout << "开空间:" << s1.capacity() << endl;
	for (size_t i = 0; i <100; i++)
	{
		s1[i]=i;
	}
	for (auto ch : s1)
	{
		cout << ch << endl;
   }

 会报异常:

C++ vector_第7张图片

这是因为方括号里面有断言:C++ vector_第8张图片

 如果就是想访问呢,解决办法:

(1)用resize,把size也开成100,这样就不会越界了:

	vector s1;
	auto sz = s1.capacity();
	//s1.reserve(100);
	s1.resize(100);
	cout << "开空间:" << s1.capacity() << endl;
	for (size_t i = 0; i <100; i++)
	{
		s1[i]=i;
	}
	for (auto ch : s1)
	{
		cout << ch << " ";
   }
	cout << endl;

(2)不用下标访问就不会越界,用push_back:


	vector s1;
	auto sz = s1.capacity();
	s1.reserve(100);
	//s1.resize(100);
	cout << "开空间:" << s1.capacity() << endl;
	for (size_t i = 0; i <100; i++)
	{
		s1.push_back(i);
	}
	for (auto ch : s1)
	{
		cout << ch << " ";
   }

插入

vector不支持流插入,流提取,也就是我们直接把值打印出来:C++ vector_第9张图片

这是因为vector是一个顺序表,如果直接把值打印出来编译器不明白是什么意思,假如你插入1,2,3,4

直接打印出来就是:

1234

 那编译器会认为这是整数1234还是12 ,34还是123,4还是1,2,34……

那么为什么string可以直接输出呢?

C++ vector_第10张图片

 string有直接流提取流输出的需求,列如输入"hello world",直接输出"hello world",就是我们想要的效果了,编译器不存在看不懂的情况。

解决方法,先遍历一遍,把我们需要分别的地方分别好再输出(列如数字之间的空格):


	vector s1;

	s1.push_back(1);
	s1.push_back(2);
	s1.push_back(3);
	s1.push_back(4);

	for (auto ch : s1)
	{
		cout << ch << " ";
	}
	cout << endl;

要用到的函数参考:C++ vector_第11张图片

(1)在头部头插一个0:

可以用insert:

pos我们可以用迭代器里的begin就可以找到头部了:

	vector s1;

	s1.push_back(1);
	s1.push_back(2);
	s1.push_back(3);
	s1.push_back(4);

	for (auto ch : s1)
	{
		cout << ch << " ";
	}
	cout << endl;
	s1.insert(s1.begin(), 0);
	for (auto ch : s1)
	{
		cout << ch << " ";
	}
	cout << endl;

(2)在指定数值前插入一个值

vector没有写find,但是在算法里面有find,这个find在标准库里,是一个模版,大家都可以用,如下:

C++ vector_第12张图片

 我们可以通过find找到值为3的数字,再通过inser()在3前插入一个30:


auto it=find(s1.begin(),s1.end(),3);
 
 if (it != s1.end())
 {
	 s1.insert(it, 30);
 }

 for (auto ch : s1)
 {
	 cout << ch << " ";
 }
 cout << endl;

删除一个指定的数:

先通过find找到这个数,然后再通过eraser删除这个数:C++ vector_第13张图片

 auto it1 = find(s1.begin(), s1.end(), 30);

 if (it1 != s1.end())
 {
	 s1.erase(it1);
 }

 for (auto ch : s1)
 {
	 cout << ch << " ";
 }
 cout << endl;

清理

可以用clean来释放size,但是clean只能释放size不能释放空间(capacity):

s1.clean();

要想手动释放空间不能通过调用析构函数来释放,因为析构函数不能被显示调用。 

 我们通过shrink_to_fit来释放空间:C++ vector_第14张图片

 也就是先把size释放为0,然后再用hrink_to_fit会把capacity缩到和size一样大小:

 s1.shrink_to_fit();

课习题2

136. 只出现一次的数字 - 力扣(LeetCode)

思路:

异或:C++ vector_第15张图片

 也就是异或是符合结合律的,让这个数组内部自己慢慢异或,最后的结果一定就是那个数组中唯一的值,因为其他出现两次或三次的数都被异或为0了。

代码:

写一个循环,把这个数组遍历一下,然后让数组内部异或,把最后得出的值返回即可:

class Solution {
public:
    int singleNumber(vector& nums) {
     
    size_t val=0;

     for(size_t i=0;i

但是这个代码是通过不了的,因为vector是一个顺序表,遍历它需要先存值,而存值需要开空间,所以我们需要reverse或者resize一个空间。

reverse只开辟capacity不开辟size大小无法遍历,所以我们用reszie。

案列能通过多少取决于你开多少空间和size:

C++ vector_第16张图片

 : 

 因为我们并不知道需要开多大空间,只能自己慢慢试,最后还开多了。因此我们可以用范围for,范围for会自动开辟空间,自己设置条件,自己++:

class Solution {
public:
    int singleNumber(vector& nums) {
     
    size_t val=0;
//手动开空间,手动遍历:
    //  nums.resize(100000);
    //  for(size_t i=0;i

课习题(3)118. 杨辉三角 - 力扣(LeetCode)

 思路:首先要知道  vector>啥意思。

vector的意思就是一个类型为Int的顺序表。

那么  vector>就好理解了,无非就是多个int顺序表。

用图表示的话就是这个样子:C++ vector_第17张图片

那么我们应该怎么去做一个杨辉三角的树呢

其实就是二维数组。

思路:

我们可以把一个顺序表看做一行,我们访问哪个vector就是访问那一行,

然后我们把一行变成0,把这一行的开头和结尾变成1:C++ vector_第18张图片

然后我们就可以把变成0的那个位置进行操作:

让这个位置的值=上一行同一个下标列左边的值+上一行下标列-1的值。C++ vector_第19张图片

vector的模拟实现

这个部分要结合vector的与源码来看的。

第一个版本:112git1 · 孙鹏宇/孙鹏宇的第一个仓库 - 码云 - 开源中国 (gitee.com)

你可能感兴趣的:(c++,开发语言)