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

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(){
    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的一些思考

  1. insertAt的理解(主要是for循环条件的思考):
    这里写图片描述

2.removeAt的理解(主要是for循环条件的思考):
这里写图片描述

没错,就是插入排序算法的原理!!

猜你喜欢

转载自blog.csdn.net/redrnt/article/details/78310629