您的位置:首页 > 理论基础 > 数据结构算法

数据结构——线性结构(9)——Vector的实现过程详解

2017-10-22 15:56 633 查看

vector的基本操作及其特点

在实现vector之前,我们都知道vector是可以储存任意类型的数值的。为了实现更一般的数据操作,我们当然是得要用模板类代替传统的实现。并且我们要实现[ ]的重载。

头文件

/*
*这个文件包含我们Vector类的模板类的声明,vector是一个高效,方便,安全的数组替代品
*/

#ifndef _Vector_h
#define _Vector_h

template<typename ValueType>
/*
*这个类能储存一系列的元素,并可以随时对它们进行增删查改
*它能提供传统的一些选择运算符的重载
*它能提供一些处理数组常用到的方法
*/

class Vector{
public:
/*
*函数:构造函数
*用法:Vector<ValueType> vec
:Vector<ValueType> vec(n,value) 创建n相同的value数组
*-------------------------------------------------------
*初始化一个空的vector
*/
Vector();
Vector(int n, ValueType value = ValueType());//后面这一句,调用默认构造函数
//用来初始化对应类型的初始值

/*
*函数:析构函数
*用法:隐式调用
*---------------------------------------------------
*用于释放动态分配中的所占用的堆的内存
*/
~Vector();

/*
*方法:size()
*用法:int i = vec.size()
*----------------------------------
*返回vector中的元素个数
*/
int size();

/*
*方法:isEmpty()
*用法:if(vec.isEmpty())
*----------------------------------
*判断vector是否为空
*/
bool isEmpty();

/*
*方法:clear()
*用法:vec.clear
*----------------------------------
*清空vector中的元素
*/
void clear();

/*
*方法:get(int index)
*用法:valueType value = vec.get(index)
*----------------------------------
*返回vector中指定下标的元素,如果指定的下标越界,那么返回一个错误
*/
ValueType get(int index);

/*
*方法:set(index,value)
*用法:vec.set(index,value)
*----------------------------------
*用后面的元素替代指定下标的元素,如果指定的下标越界,那么返回一个错误
*/
void set(int index, ValueType value);

/*
*方法:insertAt(index,value)
*用法:vec.insertAt(index,value)
*----------------------------------
*在指定下标的元素之前插入元素value,如果指定的下标越界,那么返回一个错误
*/
void insertAt(int index, ValueType value);

/*
*方法:removeAt(index)
*用法:vec.removeAt(index)
*----------------------------------
*移除指定下标的元素,如果指定的下标越界,那么返回一个错误
*/
void removeAt(int index);

/*
*方法:add(value)
*用法:vec.add(value)
*----------------------------------
*在数组末尾添加一个元素
*/
void add(ValueType vale);

/*
*运算符[]
*用法vec[index]
*-------------------
*重载运算符,使得我们能在vector中选择我们要处理的元素,如果我们指定的范围
*超出了我们的指定下标,那么我们
*返回一个错误
*/
ValueType &operator[](int index);

#include "Vectorpriv.h"

};

#include "Vectorimpl.cpp"

#endif


私有部分文件Vectorpriv.h

/*这个文件包含了我们vector接口的私有部分*/

/*
*实现说明:Vector的数据结构
*------------------------
*vector的数据是储存在我们的动态数组中,而且当我们动态数组满了的时候,我们实现双倍扩容的操作
*/

private:
static const int INITIAL_CAPACITY = 10;

/*实例化变量*/
ValueType *array; //指向动态数组的指针
int capacity; //数组被分配的容量
int count; //使用中的元素的个数(即数组元素的个数)

/*私有方法声明*/
void expandCapacity();

/* Make it illegal to copy vectors */
Vector(const Vector & value) { }
const Vector & operator=(const Vector & rhs) { return *this; }


实现部分Vectorimpl.cpp

/*
*这个文件包含了我们Vector接口的功能实现
*/

#ifdef _Vector_h
#include "error.h"
/*
*实现说明:构造函数与析构函数
*首先,这两个构造函数的实现都是先在堆中为动态数组分配空间,并且为我们的对象成员赋予初始值
*而我们的析构函数则释放我们之前申请的那段空间
*/

template <typename ValueType>
Vector<ValueType>::Vector(){
capacity = INITIAL_CAPACITY;
count = 0;
array = new ValueType[capacity];
}

template <typename ValueType>
Vector<ValueType>::Vector(int n, ValueType value){
//这里注意,因为n是用户输入的,很有可能会大于我们预设的容量,所以要进行判断
capacity = (n > INITIAL_CAPACITY) ? n :INITIAL_CAPACITY;
array = new ValueType[capacity];
count = n;
//将value值全部复制在我们在堆中new出来的空间内
for (int i = 0; i < n; i++)
{
array[i] = value;
}
}

template <typename ValueType>
Vector<ValueType>::~Vector(){
delete []array;
}

/*
*Vector的基本操作实现
*/
template <typename ValueType>
int Vector<ValueType>::size(){
return count;
}

template <typename ValueType>
bool Vector<ValueType>::isEmpty(){
return count == 0;
}

template <typename ValueType>
void Vector<ValueType>::clear(){

d454
return count = 0;
}

template <typename ValueType>
ValueType Vector<typename ValueType>::get(int index){
if (index >= count || index < 0)
{
error("get: index out of range");
}
return array[index];
}

template <typename ValueType>
void Vector<ValueType>::set(int index,ValueType value){
if (index >= count || index < 0)
{
error("set: index out of range");
}
array[index] = value;
}

/*选择运算符重载
*这里为了我们不但能查看,还能引用这里的值,所以我们用的是&符号
*/
template <typename ValueType>
ValueType & Vector<ValueType>::operator[](int index) {
if (index < 0 || index >= count) {
error("Vector selection index out of range");
}
return array[index]; //引用返回堆中的对应下标的值
}

/*
*实现说明 : add insertAt removeAt
*这些方法必须移动数组中的现有元素,为新元素腾出空间,或者关闭被删除元素留下的空间
*/
template<typename ValueType>
void Vector<ValueType>::add(ValueType value){
insertAt(count,value);
}

template<typename ValueType>
void Vector<ValueType>::insertAt(int index, ValueType value){
if (index == count) expandCapacity();//如果这里写成 =  那么这个功能就变成了add
if (index > count || index < 0) error("insertAt: index out of range");
//反向遍历,并且所有元素后移一位
for (int i = count; i > index; i--){
array[i] = array[i - 1];
}
array[index] = value;
count++;
}
template<typename ValueType>
void Vector<ValueType>::removeAt(int index){
if (index >= count || index < 0) error("removeAt: index out of range");
/*顺序遍历,并将所有的元素前移一位,这里如果反向遍历会麻烦一点
*为什么不能是count?因为我们后面用的是i+1,
*  i < count的最大整数就是 count -1,所以count -1 +1 = count
* 取array[count] 越界!
*/
for (int i = index; i < count - 1; i++)
{
array[i] = array[i + 1];
}
count--;
}
//扩展容量五部曲
template<typename ValueType>
void Vector<ValueType>::expandCapacity(){
ValueType *oldArray = array;
capacity = capacity * 2;
array = new ValueType[capacity];
for (int i = 0; i < count; i++)
{
array[i] = oldArray[i];
}
delete[] oldArray;
}

#endif


测试代码及结果:

#include <iostream>
#include "Vector.h"

using namespace std;

int main(){
Vector<int> vec(4,9);//9 9 9 9
vec.insertAt(2,0); //9 9 0 9 9
vec.add(4);//9 9 0 9 9 4
vec.removeAt(3);//9 9 0 9 4
for (int i = 0; i < vec.size(); i++)
{
cout << vec[i] << " ";
}
return 0;
}




对removeAt和insertAt的一些思考

insertAt的理解(主要是for循环条件的思考):



2.removeAt的理解(主要是for循环条件的思考):



没错,就是插入排序算法的原理!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息