【C++】模拟实现顺序表Vector容器类


一 、什么是Vector?

vector是STL中最常见的容器,它是一种顺序容器,支持随机访问。vector是一块连续分配的内存,从数据安排的角度来讲,和数组极其相似,不同的地方就是数组是静态分配空间,一旦分配了空间的大小,就不可再改变了;而vector是动态分配空间,随着元素的不断插入,它会按照自身的一套机制不断扩充自身的容量。

vector的扩充机制按照容器现在容量的一倍进行增长。vector容器分配的是一块连续的内存空间,每次容器的增长,并不是在原有连续的内存空间后再进行简单的叠加,而是重新申请一块更大的新内存,并把现有容器中的元素逐个复制过去,然后销毁旧的内存。这时原有指向旧内存空间的迭代器已经失效,所以当操作容器时,迭代器要及时更新。

数据结构–顺序表

Vector简而言之就是一个动态变长的一维数组,因此用它来实现顺序表是非常恰当的。顺序表在数据结构中是比较简单的,没有什么复杂的算法。

顺序表的基本操作
概念:顺序表是在计算机内存中以数组的形式保存的线性表,是指用一组地址连续的连续单元依次存储数据元素的线性结构。线性表采用顺序存储的方式存储就称之为顺序表。顺序表是将表中的结点依次存放在计算机内存中一组地址连续的存储单元中。
思路:假设线性表的每个元素需占用L个存储单元,并以所占的第一个单元的存储地址作为数据元素的存储位置。则线性表中第L+1个数据元素的存储位置LOC(ai+1)和第i个数据元素的存储位置LOC(ai)之间满足下列关系:
LOC(ai+1) = LOC(ai) + L
一般来说,线性表的第i个元素的存储位置为:
LOC(ai) = LOC(a1) + (i - 1) * L
插入:在顺序表第i个位置插入,先将该位置到表末尾从后到i后移一位,在给第i位赋值即可。
删除:删除顺序表的第i个元素,从i+1到表末尾前移一位即可。(鉴于顺序表相对简单,不做图示)
线性表的顺序存储结构示意图
在这里插入图片描述

源代码及注释

//Vector.h
#pragma once
#include <iostream>
#include <Windows.h>
#include <assert.h>
using namespace std;
typedef int DataType;
class Vector
{
public:
	explicit Vector(size_t capacity = 3)
	{
		_pData = (DataType*)malloc(capacity * sizeof(DataType));
		_capacity += 3;
		_size = 0;
	}
	//构造函数 有size个值为data的元素
	Vector(size_t n, const DataType& data)
	{
		_pData = (DataType*)malloc(_capacity * sizeof(DataType));
		_size = n;
		_capacity = n;
		for(size_t idx = 0;idx < _size;++idx)
		{
			_pData[idx] = data;
		}
	}
	//拷贝构造
	Vector(const Vector& v)
		: _capacity(v._capacity)//容量
		, _size(v._size)//有效元素的个数
	{
		_pData = new DataType[_capacity];
		// 比较1和2的优缺点?
		// 1 memcpy如果src与dst指向的内存空间重叠,则不能保证是否内容覆盖
		//memcpy(_pData, v._pData, sizeof(DataType)*_size);
		// 2 效率较低,但比较安全
		for(size_t idx = 0; idx < _size; ++idx)
			_pData[idx] = v._pData[idx];
	}
	//重载赋值运算符
	Vector& operator=(const Vector& v)
	{
		if(this != &v)
		{
			_pData = v._pData;
			_size = v._size;
			_capacity = v._capacity;
		}
	}
	//析构函数
	~Vector()
	{
		if(_pData != NULL)
		{
			free(_pData);
			_pData = NULL;
			_size = 0;
			_capacity = 0;
		}
	}
	void PushBack(const DataType& data);//尾插
	void PopBack();//尾删
	void Insert(size_t pos, const DataType& data);//在pos位置后面插入值为data的元素
	void Erase(size_t pos);//删除pos位置上的元素
	int Find(const DataType& data)const;//寻找值为data的元素返回下标
	void Clear();//清空顺序表
	size_t Size()const;//计算顺序表的大小
	void ReSize(size_t size, const DataType& data);//将_size 到 size之间的元素赋值为data
	size_t Capacity()const;//顺序表容量的大小
	bool Empty()const;//判断顺序表是否为空
	DataType& Front();//返回第一个元素的引用
	const DataType& Front()const;//同上 成对出现
	DataType& Back();//返回最后一个元素的引用
	const DataType& Back()const;//同上
	//赋n个值为data的元素到vector中.这个函数将会清除掉为vector赋值以前的内容.
	void Assign(size_t n, const DataType& data);
	DataType& operator[](size_t index);//下标访问界定符
	const DataType& operator[](size_t index)const;//同上
	DataType& At(size_t index);//
	const DataType& At(size_t index)const;//同上

private:
	void _CheckCapacity();
	friend std::ostream& operator<<(std::ostream& _cout, const Vector& v);
private:
	DataType* _pData;//空间首地址
	size_t _capacity;//容量
	size_t _size;//有效元素的个数
};
//main.cpp
#include "Vector.h"
void Vector::_CheckCapacity()
{
	if(_size >= _capacity)
	{
		_pData = (DataType*)realloc(_pData,_capacity * sizeof(DataType) * 2);
		assert(_pData);
		_capacity *= 2;
	}
}
void Vector::PushBack(const DataType& data)
{
	_CheckCapacity();
	_pData[_size] = data;
	_size += 1;
}
void Vector::PopBack()
{
	assert(_size > 0);
	--_size;
}
void Vector::Insert(size_t pos,const DataType& data)
{
	_CheckCapacity();
	assert(pos >= 0 && pos <= _size);
	for(size_t idx = _size - 1;idx >= pos;--idx)
	{
		_pData[idx+1] = _pData[idx];
	}
	_pData[pos] = data;
	_size += 1;
}
void Vector::Erase(size_t pos)
{
	assert(pos >= 0 && pos <= _size);
	for(size_t idx = pos;idx < _size;++idx)
	{
		_pData[idx] = _pData[idx+1];
	}
	_size -= 1;
}
int Vector::Find(const DataType& data)const
{
	for(size_t idx = 0;idx < _size;)
	{
		if(_pData[idx] == data)
			return idx;
		++idx;
	}
	return 0;
}
void Vector::Clear()
{
	if(_size == 0)
		return;
	_size = 0;
}
size_t Vector::Size()const
{
	return _size;
}
void Vector::ReSize(size_t size,const DataType& data)
{
	_CheckCapacity();
	if(size < _size)
		_size = size;
	if(size > _size)
	{
		for(size_t idx = _size;idx < size;++idx)
		{
			_pData[idx] = data;
		}
		_size = size;
	}
}
size_t Vector::Capacity()const
{
	return _capacity;
}
bool Vector::Empty()const
{
	if(_size == 0)
		return true;
	if(_size > 0)
		return false;
}
DataType& Vector::Front()
{
	return (*this)._pData[0];
}
const DataType& Vector::Front()const
{
	return (*this)._pData[0];
}
DataType& Vector::Back()
{
	return (*this)._pData[_size - 1];
}
const DataType& Vector::Back()const
{
	return (*this)._pData[_size];
}
void Vector::Assign(size_t n,const DataType& data)
{
	free(_pData);
	_pData = NULL;
	_pData = (DataType*)malloc(_capacity * sizeof(DataType));
	for(size_t idx = 0;idx < n;++idx)
	{
		_pData[idx] = data;
	}
	_size = n;
	_capacity = n;
}
DataType& Vector::operator[](size_t index)
{
	return _pData[index];
}
const DataType& Vector::operator[](size_t index)const
{
	return _pData[index];
}
DataType& Vector::At(size_t index)
{
	assert(index <= _size);
	return _pData[index];
}
const DataType& Vector::At(size_t index)const
{
	assert(index <= _size);
	return _pData[index];
}
ostream& operator<<(ostream& _cout,const Vector& c)
{
	for(size_t idx = 0;idx < c._size;++idx)
	{
		_cout<<c._pData[idx]<<"  ";
	}
	return _cout;
}
//test.cpp
#include "Vector.h"
void FunTest()
{
	Vector v1(5,8);
	cout<<"v1:"<<v1<<endl;
	Vector v2(v1);
	cout<<"v2:"<<v2<<endl;
	v1.Insert(2,10);
	cout<<"v1:"<<v1<<endl;
	v1.PushBack(100);
	cout<<"v1:"<<v1<<endl;
	v1.PopBack();
	cout<<"v1:"<<v1<<endl;
	v1.Assign(3,5);
	cout<<"v1:"<<v1<<endl;
	v1.At(3);
	cout<<v1<<endl;
	v1.Back();
	cout<<v1<<endl;
	v1.Capacity();
	cout<<v1<<endl;
}
int main()
{
	FunTest();
	system("pause");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农印象

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值