Sequence container - vector

#include <iostream>
#include <vector>
#Include < iterator > / / iterator header file
#Include < algorithm > / / generic algorithm header file

using namespace std;

int main()
{
	//Use vector in Library 
	int arr[] = {1,24,62,63,3,34,85,32};
	int len = sizeof(arr) / sizeof(arr[0]);
	vector<int> vec(arr,arr + len);//Constructing vec object with interval of array and vector in system
	cout << vec.size() << endl;//Current container size
	cout << vec.max_size() << endl;//The maximum number of elements that can be stored in the container is related to the platform and implementation. On my machine, the max_size of vector < int > is 1073741823, while the max_size of string is 4294967294
	vec[0] = 222; //Change the first element to 222. For vec, it is a container object. How can an object be made with subscripts? Prove that the overloaded function of bracket operator is implemented in the library

	vec.push_back(20);//Tail insertion
	vec.insert(vec.begin(),30);//Insert at start position

	vector<int>::iterator index1 = find(vec.begin(),vec.end(),62);//Insert by element position
	vec.insert(index1,66);

	vec.pop_back();//Tail deletion
	vec.erase(vec.begin());//Delete by start

	vector<int>::iterator index2 = find(vec.begin(),vec.end(),85);//Delete by element location
	vec.erase(index2);

Iterators: object-oriented pointers

The iterator masks the data inside the container object. When used externally, you cannot point to an internal space with a normal pointer. When traversing the whole element, a method of traversing the container is given by means of iterator. Iterator is an object-oriented pointer, which can't get the internal things. The container needs to return an interval (iterator returning the starting position: begin() end()). Determine the container interval through the container interface begin() and end(). Traverse from begin to end, and then traverse all data. The iterator interval is a semi open and semi closed interval. For a normal forward iterator, what is returned for begin() is the starting position (closed interval) element iterator, pointing to the first element, while end() returns the last element's subsequent position (open interval)

        //Print of iterator
	vector<int>::iterator it = vec.begin();//Defines the object it of an iterator, pointing to the starting position element
	for(it;it != vec.end();it++)
	{
		cout << *it << "  ";//it can dereference, and realize the dereference of overloaded function pointers that understand reference operators. Iterators are object-oriented pointers
	}
	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;//Define T type as value type
	//For all containers, there is a default constructor, that is, a constructor without parameters
	MyVector()
	{
		//cursize = totalsize = 0; 
		arr = new T[1];
		cursize = 0;
		totalsize = 1;
	}

~MyVector()
	{
		delete[] arr;//If the default (parameterless) constructor is called, the arr in it does not have any processing, points to 0XCCCC, and delete causes the program to crash
		             //In order to unify resource release, no judgment is needed. At the beginning, a byte is opened
	}

	MyVector(int size)//An integer parameter constructor can be used to construct how many elements the container object size represents. For example, passing in 20 means opening up 20 size arrays and initializing them to 0
	{
		if(size < 0)
			return;
		arr = new T[size]();
		cursize = size;
		totalsize = size;
	}

	MyVector(const MyVector<T>& rhs)//The implementation has pointer copy constructor. If it is not written, the copy constructor provided by the system is used as a shallow copy, resulting in the same block of memory being destructed twice. So we need to realize our own deep copy
	{
		arr = new T[rhs.totalsize]();//Open up space
		memcpy(arr,rhs.arr,sizeof(T)*rhs.cursize);//Content copy function
		cursize = rhs.cursize;
		totalsize = rhs.totalsize;
	}

	MyVector<T>& operator = (const MyVector<T>&rhs)//Overloaded functions to implement assignment operators
	{
		if(this != &rhs)//Judge self assignment
		{
			delete[] arr;//Free up old space
			arr = new T[rhs.totalsize]();//Open up new space
			memcpy(arr,rhs.arr,sizeof(T)*rhs.cursize);
			cursize = rhs.cursize;
			totalsize = rhs.totalsize;
		}
		return *this;//Hit self assignment return
	}

	typedef Iterator<MyVector<T>> iterator;//Container type should be passed
	iterator begin()
	{
		return iterator(this,0);
	}
	iterator end()
	{
		return iterator(this,cursize);
	}

	T& operator[](int index)//Implement the overloaded function of bracket operator in container
	{
		return arr[index];
	}

	// Vector is a vector container (growing at one end). It must support push operation. Only tail insertion is push back
	void push_back(T val)//Equivalent to the underlying call to Insert, the iterator is a tail iterator
	{
		Insert(end(),val);
	}

	void Insert(iterator _where,T val)//Insert the element iterator according to the current iterator location T* val: element
	//What can I do to insert elements in the current iterator's location Insert by position, there must be movement of array.
	//How to move an array? Move the elements one by one from the back. When you move them to a certain position, they just reach the iterator position 
	//Question: without pos in the iterator, the iterator type cannot be converted to built-in type. Can the built-in type be converted to iterator type?
	//Sure
	{
		//When inserting, it will be full first. If it is full, the capacity will be expanded
		if(IsFull())
		{
			resize();
		}
		iterator last = end();//Define an iterator last pointing to the end
		int pos = cursize;
		while(last != _where)
		{
			arr[pos] = arr[pos - 1];
			last--;
			pos--;
		}
		arr[pos] = val;
		cursize++;
	}

	// vector delete
	void pop_back1()// vector delete
	{
		Delete(end());//Call Delete directly
	}
	void pop_back2()// vector delete
	{
		if(IsEmpty())
		{
			throw exception("vector is null");//Throw an exception for null
		}
		cursize--;//Set the current size of the array--
	}

	void Delete(iterator _where)// Deletion of vector anywhere
	{
		if(IsEmpty())
		{
			throw exception("vector is null");//Throw an exception for null
		}
		iterator first = begin();
		int pos = 0;
		while(first != _where)
		{
			first++;
			pos++;
		}
		for(;pos < cursize;pos++)
		{
			arr[pos] = arr[pos + 1];
		}
		cursize--;
	}

	int size()//Current container size
	{
		return cursize;
	}
	
		void resize(int size = 0)//Capacity expansion
	{
		if(size == 0)
		{
			size = totalsize * 2;
		}
		T* newarr = new T[size];//Open up new space
		memcpy(newarr,arr,sizeof(T)*cursize);//memcpy initialization
		delete[] arr;//Free up old space
		arr = newarr;//Old space equals new space
		totalsize = size;
	}

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

private:
	T *arr;
	int cursize;//Array current size
	int totalsize;//Total array size

	bool IsFull()//Sentence full
	{
		return cursize == totalsize;
	}

	bool IsEmpty()//Sentence blank
	{
		return cursize == 0;
	}
};


template<typename Container>//Iterators are object-oriented pointers, so template type parameters are container types
class Iterator
{
public:
	Iterator(Container* vec,int index)//Construction of iterator
		:pvec(vec),pos(index)
	{}

	//Implementation of iterator object
	//1.1 comparison algorithm overloaded function (different comparison iterators represent different element positions, how to judge Compare pos)
	bool operator != (const Iterator& rhs)
	{
		return  pos != rhs.pos;
	}

	//1.2 + + operator overloaded functions (pre and post)
	//Returns a reference to an iterator
	Iterator<Container>& operator++()//Prefix + +
	{
		++pos;
		return *this;
	}
	Iterator<Container>& operator++(int)//Post + +
	{
		pos++;
		return *this;
	}

	//vector is a random access iterator, which supports both iterator + + and iterator--
	Iterator<Container>& operator--()
	{
		--pos;
		return *this;
	}
	Iterator<Container>& operator--(int)
	{
		pos--;
		return *this;
	}

	//1.3 dereference operator overload function
	//The returned reference Container of value type is the Container type, and the value type is required. In the vector Container, each value type will be redefined
	//Container is a container and a class. The type contained in the class is the value type of the class
	typename Container::value_type& operator*()
	{
		return (*pvec)[pos];//Pvec: pointer to container object * pvec: dereference to container object (* pvec)[pos]:pvec object calls bracket operator overloaded function
		                    //Pevc - > operator []; pvec calls the operator bracket operator overloaded function to pass pos in
	}


	//For an iterator, it is a pointer point. It does not care whether it is heap memory or not. It does not need a destructor

private:
	Container* pvec;//Finally, use MyVector to instantiate the Container. The template type parameter is replaced by MyVector* pvec, which is the pointer of the Container object, that is, the object-oriented pointer. The whole class is the object-oriented pointer
	//Thinking: how to distinguish each element when an iterator points to a container For example, MyVector generates vec1 objects and points pvec to vec1 objects. How to distinguish each element in vector? 
	//Vector is a vector container, and the bottom layer is an array. Each element can be distinguished by subscripts
	int pos;
};

int main()
{
//Use your own 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();
	
	//Print of iterator
	MyVector<int>::iterator it = vec.begin();
	for(it;it != vec.end();it++)
	{
		cout << *it << "  ";
	}
	cout << endl;

	return 0;
}

 

Posted by EverLearning on Thu, 21 Nov 2019 08:47:09 -0800