vector简单模拟

发布于:2024-10-16 ⋅ 阅读:(6) ⋅ 点赞:(0)

1.二维vector

下图可以看到vector<int>指向的是几个int型的,而vector<vector<int>>则指向的是几个vector<int>型的内容,而它们又指向几个int型的内容,三维就重复就可以理解。

 例题:

可以得到的规律中间(假设索引为2)的等于上面索引为2和1的相加,而且第一行和第二行不用动都是1,且每一行的头尾也不动是1。

先构建二维vector,然后以i+1(列的增加)来递增,然后用俩重循环来给中间赋值。

 

class Solution {
public:
    vector<vector<int>> generate(int numRows) {
        vector<vector<int>> v(numRows);
        for(size_t i=0;i<numRows;i++)
        {
            v[i].resize(i+1,1);
        }

        for(int i=0;i<v.size();i++)
        {
            for(int j=1;j<v[i].size()-1;++j)
            {
                v[i][j]=v[i-1][j]+v[i-1][j-1];
            }
        }
        return v;
    }
};

2.代码解析

 1.迭代器实现

用typedef重命名T*为iterator,成员变量是_start,_finish,_end_of_storage,所以begin()获取_start指向的位置,end()获取_finish指向的位置,后面俩个在函数后面+const的是指里面的内容都是只读不可以修改。

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


private:
		iterator _start = nullptr;
		iterator _finish = nullptr;
		iterator _end_of_storage = nullptr;

2. vector的大小容量以及判断空

vector的size可以通过首尾指针相减得到的距离值获取,容量则就使用原本容量空间-首的位置,判断是否为空看_start和_finish是否相等。


		size_t size()
		{
			return _finish - _start;
		}

		size_t capacity() const
		{
			return _end_of_storage - _start;
		}

		bool empty()
		{
			return _start == _finish;
		}

3. 容量设置

比较n和capacity的大小,因为我们是只打不小,所以只有大了才指向扩容,要保留原的size,如果不保留原来的size则在_finish=tmp+old_size这里就有问题,因为size就是_finish-_start,而不保留则用的是原来vector的size那么_finish=_finish(前一个的_finish),那么_start指向的是新的vector,而_finish还是指向旧的,所以就不行(迭代器失效问题)。

void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t old_size = size();
				T* tmp = new T[n];
				memcpy(tmp, _start, sizeof(T) * size());
				delete[] _start;

				_start = tmp;
				_finish = tmp + old_size;
				_end_of_storage = tmp + n;
			}
		}

 4.尾插和尾删

在尾插时要判断容量是否足够,不够就扩容,够就在_finish处插入值,然后再把_finish指向插入处的下一个位置,尾删要想判断是否为空,有才能删除,直接把_finish-1就删除了一个数据。

void push_back(const T& x)
		{
			if (_finish == _end_of_storage)
			{
				reserve(capacity() == 0 ? 4 : capacity() * 2);
			}
			*_finish = x;
			++_finish;
		}

		void pop_back()
		{
			assert(!empty());
			--_finish;
		}

 5.在指定位置插入

这里len保存pos-_start是因为下面有reserve函数会改变vector,_start和_finish会去新的vector而pos还在旧的vector,接下来就是挪动数据把pos位置空出来填要插入的数据。

iterator insert(iterator pos, const T& x)
		{
			if (_finish == _end_of_storage)
			{
				size_t len = pos - _start;//怕迭代器失效

				reserve(capacity() == 0 ? 4 : 2 * capacity());
				pos = _start + len;
			}

			iterator end = _finish - 1;//因为有一个数据finish+1 但是索引0处才有数据,而finish=1处没有所以访问要-1
			while (end >= pos)
			{
				*(end + 1) = *end;
				--end;
			}
			*pos = x;
			++_finish;

			return pos;
		}

6.重载函数

 _start[i]=*(_start+i),获取对应位置的解引用值,下面则是返回常量引用且是只读。

T& operator[](size_t i)
		{
			assert(i < size());

			return _start[i];
		}

		const T& operator[](size_t i) const
		{
			assert(i < size());

			return _start[i];
		}

7.测试函数

先尾插五个数据,然后在位置2插入20,这里用auto p接收pos而不用pos是因为插入后vector跟没插入之前是不一样了,所以pos失效了,可以通过函数返回值来得到位置,进而得到想要结果,输入在insert中有修正,但是pos是在insert函数的形参,而p是在测试函数的形参,这俩是没有关系的,除非实参修正才有用。(如果insert用的是引用也不可以,因为表达式的返回是临时变量具有常性,所以要有const &才行,但是加了const就不能修改pos了,所以不可以)

void test_vector2()
	{
		vector<int> v;
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		v.push_back(5);
		
		print_vector(v);

		v.insert(v.begin() + 2, 30);
		print_vector(v);

		int x;
		cin >> x;

		auto p = find(v.begin(), v.end(), x);
		if (p != v.end())
		{
			// insert以后p就是失效,不要直接访问,要访问就要更新这个失效的迭代器的值
			//v.insert(p, 40);
			//(*p) *= 10;

			p = v.insert(p, 40);
			(*(p + 1)) *= 10;
		}
		print_vector(v);
	}

 find函数解释:

 

std::find 函数的原型定义在 C++ 标准库的 &lt;algorithm&gt; 头文件中。以下是其基本原型:
template&lt;class ForwardIt, class T&gt;
ForwardIt find(ForwardIt first, ForwardIt last, const T&amp; value);

参数说明

1.ForwardIt first:范围的开始迭代器,表示要搜索的序列的第一个元素的迭代器。
2.ForwardIt last:范围的结束迭代器,表示要搜索的序列的最后一个元素后面的迭代器(不包含该位置)。
3.const T&amp; value:要查找的值,可以是任何类型(例如基本数据类型、用户定义类型等)。

返回值

4.返回一个迭代器,指向找到的第一个匹配元素。如果在指定范围内没有找到该元素,则返回 last 迭代器。

使用示例
这里是一个简单的示例,展示如何使用 std::find 函数:
#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;algorithm&gt;

int main() {
    std::vector&lt;int&gt; v = {1, 2, 3, 4, 5}; // 创建一个整数类型的vector
    int x = 3; // 要查找的值

    // 使用 std::find 查找值 x
    auto p = std::find(v.begin(), v.end(), x);

    // 检查查找结果
    if (p != v.end()) {
        std::cout &lt;&lt; "Found " &lt;&lt; x &lt;&lt; " at index " &lt;&lt; std::distance(v.begin(), p) &lt;&lt; std::endl;
    } else {
        std::cout &lt;&lt; x &lt;&lt; " not found in the vector." &lt;&lt; std::endl;
    }

    return 0;
}

总结
std::find 是一种非常方便的查找算法,能够简化在容器中查找元素的操作,并且通过使用模板支持各种数据类型。

 

3.总代码 

vector.h

#pragma once
#include<iostream>
#include<assert.h>

namespace zym
{
	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;
		}
		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t old_size = size();
				T* tmp = new T[n];
				memcpy(tmp, _start, sizeof(T) * size());
				delete[] _start;

				_start = tmp;
				_finish = tmp + old_size;
				_end_of_storage = tmp + n;
			}
		}

		size_t size()
		{
			return _finish - _start;
		}

		size_t capacity() const
		{
			return _end_of_storage - _start;
		}

		bool empty()
		{
			return _start == _finish;
		}

		void push_back(const T& x)
		{
			if (_finish == _end_of_storage)
			{
				reserve(capacity() == 0 ? 4 : capacity() * 2);
			}
			*_finish = x;
			++_finish;
		}

		void pop_back()
		{
			assert(!empty());
			--_finish;
		}
		iterator insert(iterator pos, const T& x)
		{
			if (_finish == _end_of_storage)
			{
				size_t len = pos - _start;//怕迭代器失效

				reserve(capacity() == 0 ? 4 : 2 * capacity());
				pos = _start + len;
			}

			iterator end = _finish - 1;//因为有一个数据finish+1 但是索引0处才有数据,而finish=1处没有所以访问要-1
			while (end >= pos)
			{
				*(end + 1) = *end;
				--end;
			}
			*pos = x;
			++_finish;

			return pos;
		}
		T& operator[](size_t i)
		{
			assert(i < size());

			return _start[i];
		}

		const T& operator[](size_t i) const
		{
			assert(i < size());

			return _start[i];
		}

		


	private:
		iterator _start = nullptr;
		iterator _finish = nullptr;
		iterator _end_of_storage = nullptr;
	};

	template<class T>
	void print_vector(const vector<T>& v)
	{
		auto it = v.begin();
		while (it != v.end())
		{
			cout << *it << "";
			++it;
		}

		cout << endl;

		for (auto e : v)
		{
			cout << e << "";
		}
		cout << endl;
	}
	void test_vector2()
	{
		vector<int> v;
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		v.push_back(5);
		
		print_vector(v);

		v.insert(v.begin() + 2, 30);
		print_vector(v);

		int x;
		cin >> x;

		auto p = find(v.begin(), v.end(), x);
		if (p != v.end())
		{
			// insert以后p就是失效,不要直接访问,要访问就要更新这个失效的迭代器的值
			//v.insert(p, 40);
			//(*p) *= 10;

			p = v.insert(p, 40);
			(*(p + 1)) *= 10;
		}
		print_vector(v);
	}
}

 

test.cpp


#include<iostream>

using namespace std;
#include"vector.h"


int main()
{
	zym::test_vector2();
}