其他分享
首页 > 其他分享> > 顺序容器——vector

顺序容器——vector

作者:互联网

#include <iostream>
#include <vector>
#include <iterator> //迭代器头文件
#include <algorithm> //泛型算法头文件

using namespace std;

int main()
{
	//使用库中的 vector 
	int arr[] = {1,24,62,63,3,34,85,32};
	int len = sizeof(arr) / sizeof(arr[0]);
	vector<int> vec(arr,arr + len);//用数组的区间、系统中的 vector 构造 vec 对象
	cout << vec.size() << endl;//容器当前大小
	cout << vec.max_size() << endl;//容器最大的可以存储的元素   这个数目与平台和实现相关,在我的机器上vector<int>的max_size为1073741823,而string的max_size为4294967294
	vec[0] = 222; //将第一个元素改为222 针对 vec 来说是容器对象,对象怎么能用下标来做,证明在库中实现了中括号运算符的重载函数

	vec.push_back(20);//尾插
	vec.insert(vec.begin(),30);//按开始位置插

	vector<int>::iterator index1 = find(vec.begin(),vec.end(),62);//按元素位置插
	vec.insert(index1,66);

	vec.pop_back();//尾删
	vec.erase(vec.begin());//按开始位置删

	vector<int>::iterator index2 = find(vec.begin(),vec.end(),85);//按元素位置删除
	vec.erase(index2);

迭代器:面向对象的指针

针对容器对象内部数据,迭代器将其屏蔽起来。外部使用时,不能用一个普通指针指向内部空间。遍历整个元素时,通过迭代器的方式,给出一种遍历容器的方法。迭代器是面向对象的指针,拿不到内部的东西,需要容器返回一个区间出来(返回起始位置的迭代器:begin() 末尾位置迭代器:end() )。通过容器接口 begin() 和 end() 确定容器区间,从 begin 到 end 遍历一遍,就把所以数据遍历了。迭代器区间是半开半闭的区间,对于普通正向迭代器,针对 begin() 返回的就是起始位置(闭区间)元素迭代器,指向第一个元素,而 end() 返回最后一个元素后继位置(开区间)

        //迭代器的打印
	vector<int>::iterator it = vec.begin();//定义一个迭代器的对象 it ,指向起始位置元素
	for(it;it != vec.end();it++)
	{
		cout << *it << "  ";//it 可以解引用,实现了解引用运算符的重载函数 指针都可以解引用,迭代器是面向对象的指针
	}
	cout << endl;
	return 0;
}
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
using namespace std;

template<typename T>
class MyVector
{
public:
	typedef T value_type;//把T类型定义为值类型
	//针对所有的容器,都有默认的构造函数,即不带参数的构造函数
	MyVector()
	{
		//cursize = totalsize = 0; 
		arr = new T[1];
		cursize = 0;
		totalsize = 1;
	}

~MyVector()
	{
		delete[] arr;//如果调用默认(无参数)构造函数,里面的 arr 没有任何处理,指向0XCCCC,delete导致程序奔溃
		             //为了统一资源释放,不用判断,在开始的时候,开辟一个字节
	}

	MyVector(int size)//可以用一个整型参数构造函数来构造容器对象 size代表元素的多少,比如传入20,就表示开辟20个大小的数组并初始化为0
	{
		if(size < 0)
			return;
		arr = new T[size]();
		cursize = size;
		totalsize = size;
	}

	MyVector(const MyVector<T>& rhs)//实现有指针拷贝构造函数,如果不写,使用系统提供的拷贝构造函数,是以一个浅拷贝,导致析构时同一块内存析构两次。所以要实现自己的深拷贝
	{
		arr = new T[rhs.totalsize]();//开辟空间
		memcpy(arr,rhs.arr,sizeof(T)*rhs.cursize);//内容拷贝函数
		cursize = rhs.cursize;
		totalsize = rhs.totalsize;
	}

	MyVector<T>& operator = (const MyVector<T>&rhs)//实现 赋值运算符的重载函数
	{
		if(this != &rhs)//判断自赋值
		{
			delete[] arr;//释放旧空间
			arr = new T[rhs.totalsize]();//开辟新空间
			memcpy(arr,rhs.arr,sizeof(T)*rhs.cursize);
			cursize = rhs.cursize;
			totalsize = rhs.totalsize;
		}
		return *this;//命中自赋值返回
	}

	typedef Iterator<MyVector<T>> iterator;//传的应是容器类型
	iterator begin()
	{
		return iterator(this,0);
	}
	iterator end()
	{
		return iterator(this,cursize);
	}

	T& operator[](int index)//在容器中实现 中括号运算符重载函数
	{
		return arr[index];
	}

	// vector 是矢量容器(一端增长),肯定要支持 push 操作,只有尾部插入 即 push_back
	void push_back(T val)//相当于底层调用 Insert ,迭代器是尾部迭代器
	{
		Insert(end(),val);
	}

	void Insert(iterator _where,T val)//按当前迭代器的位置插入元素  Iterator _where:迭代器位置  T* val:元素
	//怎么做可以在当前迭代器的位置插入元素? 按位置插入,肯定有数组的移动。
	//怎么移动数组,从后面把元素依次挪一下,挪到一定位置时,刚好到迭代器位置 
	//问题:在迭代器里面取不到pos  不能将迭代器类型转为内置类型,能否将内置类型转为迭代器类型?
	//可以
	{
		//插入时先判满,满的话扩容
		if(IsFull())
		{
			resize();
		}
		iterator last = end();//定义一个迭代器 last 指向末尾
		int pos = cursize;
		while(last != _where)
		{
			arr[pos] = arr[pos - 1];
			last--;
			pos--;
		}
		arr[pos] = val;
		cursize++;
	}

	// vector 删除
	void pop_back1()// vector 尾删
	{
		Delete(end());//直接调用 Delete
	}
	void pop_back2()// vector 尾删
	{
		if(IsEmpty())
		{
			throw exception("vector is null");//为空抛出异常
		}
		cursize--;//将数组当前大小--
	}

	void Delete(iterator _where)// vector 任意位置的删除
	{
		if(IsEmpty())
		{
			throw exception("vector is null");//为空抛出异常
		}
		iterator first = begin();
		int pos = 0;
		while(first != _where)
		{
			first++;
			pos++;
		}
		for(;pos < cursize;pos++)
		{
			arr[pos] = arr[pos + 1];
		}
		cursize--;
	}

	int size()//容器当前大小
	{
		return cursize;
	}
	
		void resize(int size = 0)//扩容
	{
		if(size == 0)
		{
			size = totalsize * 2;
		}
		T* newarr = new T[size];//开辟新空间
		memcpy(newarr,arr,sizeof(T)*cursize);//memcpy 初始化
		delete[] arr;//释放旧空间
		arr = newarr;//旧空间等于新空间
		totalsize = size;
	}

	void show()
	{
		for(int i = 0;i < cursize;i++)
		{
			cout << arr[i] << "  ";
		}
		cout << endl;
	}

private:
	T *arr;
	int cursize;//数组当前大小
	int totalsize;//数组总大小

	bool IsFull()//判满
	{
		return cursize == totalsize;
	}

	bool IsEmpty()//判空
	{
		return cursize == 0;
	}
};


template<typename Container>//迭代器是面向对象的指针,所以模板类型参数是容器类型
class Iterator
{
public:
	Iterator(Container* vec,int index)//迭代器的构造
		:pvec(vec),pos(index)
	{}

	//1 迭代器对象的实现
	//1.1 比较运算法重载函数(比较迭代器不同代表的是元素位置不同,如何判断? 比较 pos 是否相同)
	bool operator != (const Iterator& rhs)
	{
		return  pos != rhs.pos;
	}

	//1.2 ++运算符重载函数(前置和后置)
	//返回迭代器的引用
	Iterator<Container>& operator++()//前置++
	{
		++pos;
		return *this;
	}
	Iterator<Container>& operator++(int)//后置++
	{
		pos++;
		return *this;
	}

	//针对 vector 是随机访问迭代器,既支持迭代器++,又支持迭代器--
	Iterator<Container>& operator--()
	{
		--pos;
		return *this;
	}
	Iterator<Container>& operator--(int)
	{
		pos--;
		return *this;
	}

	//1.3 解引用运算符重载函数
	//返回的是值类型的引用    Container是容器类型,要的是值类型,在vector容器中,对于每个值类型都会重定义的
	//Container是容器,是类,类里面包含类型 直接用类里面的值类型value_type
	typename Container::value_type& operator*()
	{
		return (*pvec)[pos];//pvec:容器对象的指针   *pvec:解引用变成容器对象   (*pvec)[pos]:pvec对象调用中括号运算符重载函数
		                    //pevc->operator[](pos); pvec 调用 operator 中括号运算符重载函数,将 pos 传进去
	}


	//对于迭代器来说,是一个指针指向,对于是不是堆内存不关心,不用析构函数

private:
	Container* pvec;//最后用 MyVector 这个类型来实例化 Container ,这个模板类型参数被替换成 MyVector* pvec, pvec 是容器对象的指针,也就是面向对象的指针,整个类都是面向对象的指针
	//思考:迭代器指向某一个容器,怎样区分每个元素? 比如MyVector 生成 vec1 对象,拿 pvec 指向 vec1 对象,怎样区分 vector 里面每个元素? 
	//vector 是矢量容器,底层是数组,可以用下标区分每个元素
	int pos;
};

int main()
{
//使用自己的 vector
	MyVector<int> vec(1);
	vec[0] = 10; 
	vec.Insert(vec.begin(),20);
	vec.push_back(30);
	vec.show();
	vec.Delete(vec.begin());
	vec.show();
	vec.pop_back1();
	vec.show();
	
	//迭代器的打印
	MyVector<int>::iterator it = vec.begin();
	for(it;it != vec.end();it++)
	{
		cout << *it << "  ";
	}
	cout << endl;

	return 0;
}

 

标签:容器,arr,顺序,迭代,pos,cursize,vector,vec
来源: https://blog.csdn.net/TUJI67/article/details/89606923