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

来源:互联网 发布:淘宝幸运抽奖 编辑:程序博客网 时间:2024/06/04 20:12

vector的基本操作及其特点

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

头文件

/* *这个文件包含我们Vector类的模板类的声明,vector是一个高效,方便,安全的数组替代品 */#ifndef _Vector_h#define _Vector_htemplate<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循环条件的思考):
这里写图片描述

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

阅读全文
1 0