后台开发:核心技术与应用实践3.3.4 Vector类的简单实现

news/2024/7/5 7:12:11

3.3.4 Vector类的简单实现


实现一个vector,绝对是C++中的重点知识。下面例3.13中提供了类的简单实现。

【例3.17】 vector类的简单实现。

#include<algorithm>

#include<iostream>

#include <assert.h>

using namespace std;

template<typename T>

class myVector

{

private:

    /*walk length*/

    /*myVector each time increase space length*/

    #define WALK_LENGTH 64;

 

public:

    /*default constructor*/

    myVector():array(0),theSize(0),theCapacity(0){    }

    myVector(const T& t,unsigned int n):array(0),theSize(0),theCapacity(0){

        while(n--){

            push_back(t);

        }

    }

 

    /*copy constructor*/

    myVector(const myVector<T>& other):array(0),theSize(0),theCapacity(0){

        *this = other;

    }

 

    /*= operator*/

    myVector<T>& operator =(myVector<T>& other){

        if(this == &other)

            return *this;

        clear();

        theSize = other.size();

        theCapacity = other.capacity();

        array = new T[theCapacity];

        for(unsigned int i = 0 ;i<theSize;++i)

        {

            array[i] = other[i];

        }

        return *this;

    }

 

    /*destructor*/

    ~myVector(){

        clear();

    }

 

    /*the pos must be less than myVector.size();*/

    T& operator[](unsigned int pos){

        assert(pos<theSize);

        return array[pos];

    }

 

    /*element theSize*/

    unsigned int size(){

        return theSize;

    }

 

    /*alloc theSize*/

    unsigned int capacity(){

        return theCapacity;

    }

 

    /*is  empty*/

    bool empty(){

        return theSize == 0;

    }

 

    /*clear myVector*/

    void clear(){

        deallocator(array);

        array = 0;

        theSize = 0;

        theCapacity = 0;

    }

 

    /*adds an element in the back of myVector*/

    void push_back(const T& t){

        insert_after(theSize-1,t);

    }

 

    /*adds an element int the front of myVector*/

    void push_front(const T& t){

        insert_before(0,t);

    }

 

    /*inserts an element after the pos*/

    /*the pos must be in [0,theSize);*/

    void insert_after(int pos,const T& t){

        insert_before(pos+1,t);

    }

 

    /*inserts an element before the pos*/

    /*the pos must be less than the myVector.size()*/

    void insert_before(int pos,const T& t){

        if(theSize==theCapacity){

            T* oldArray = array;

            theCapacity += WALK_LENGTH;

            array = allocator(theCapacity);

            /*memcpy(array,oldArray,theSize*sizeof(T)):*/

            for(unsigned int i = 0 ;i<theSize;++i){

                array[i] = oldArray[i];

            }

            deallocator(oldArray);

        }

 

        for(int i = (int)theSize++;i>pos;--i){

            array[i] = array[i-1];

        }

        array[pos] = t;

    }

 

    /*erases an element in the pos;*/

    /*pos must be in [0,theSize);*/

    void erase(unsigned int pos){

        if(pos<theSize){

            --theSize;

            for(unsigned int i = pos;i<theSize;++i){

                array[i] = array[i+1];

            }

        }

    }

 

private:

    T*  allocator(unsigned int size){

        return new T[size];

    }

 

    void deallocator(T* arr){

        if(arr)

            delete[] arr;

    }

private:

    T*                                array;

    unsigned int    theSize;

    unsigned int    theCapacity;

};

 

void printfVector(myVector<int>& vector1){

    for(unsigned int i = 0 ; i < vector1.size();++i){

        cout<<vector1[i]<<",";

    }

    cout<<"alloc size = "<<vector1.capacity()<<",size = "<<vector1.size()<<endl;

}

 

int main(){

    myVector<int> myVector1;

    myVector<int> myVector2(0,10);

    myVector2.push_front(1);

    myVector2.erase(11);

    printfVector(myVector2);

    myVector1.push_back(2);

    myVector1.push_front(1);

    printfVector(myVector1);

    myVector1.insert_after(1,3);

    printfVector(myVector1);

 

    myVector2 = myVector1;

    myVector2.insert_before(0,0);

    myVector2.insert_before(1,-1);

    printfVector(myVector2);

    return 0;

}

程序的执行结果为:

1,0,0,0,0,0,0,0,0,0,0,alloc size = 64,size = 11

1,2,alloc size = 64,size = 2

1,2,3,alloc size = 64,size = 3

0,-1,1,2,3,alloc size = 64,size = 5

STL库中vector是一个自动管理的动态数组,只要明白vector的类型是一个数组,至于怎么去实现它其实不难。例3.17中选择了一种简单的方式去实现它:定义一个步长WALK_LENGTH,在数组空间不够时,再重新申请长度为theCapacity +WALK_LENGTH的内存,这样就避免了每次当myVector元素增加的时候,需要去重新申请空间的问题,当然不好的地方就是会浪费一定的空间,但是时间效率上会提高很多。因为vector可以支持下标访问,所以就不用单独构造一个iterator,从而提高效率。

例3.17中,myVector拥有3个成员变量:元素的个数theSize、容量theCapacity和一个指针数组array。

默认构造函数里,把元素的个数theSize、容量theCapacity都赋值为0,数组赋值为空,代码如下:

myVector():array(0),theSize(0),theCapacity(0){    }

用几个相同的值赋值给myVector,那应该是逐个添加的:

    myVector(const T& t,unsigned int n):array(0),theSize(0),theCapacity(0){

        while(n--){

            push_back(t);

        }

    }

进行重载:

    myVector<T>& operator =(myVector<T>& other){

        if(this == &other)

            return *this;

        clear();

        theSize = other.size();

        theCapacity = other.capacity();

        array = new T[theCapacity];

        for(unsigned int i = 0 ;i<theSize;++i)

        {

            array[i] = other[i];

        }

        return *this;

    }

如果参数与本myVector相同,那就无需赋值了;不相同时才需要赋值,并需要分别对3个成本变量进行赋值,元素个数、容量大小和数组内容。

析构函数里直接调用clear函数,如下所示:

    ~myVector(){

        clear();

    }

用下标的方式访问myVector中的元素,其实就是访问数组array中的元素,注意下标必须小于元素个数,如下所示:

    T& operator[](unsigned int pos){

        assert(pos<theSize);

        return array[pos];

    }

获得元素个数和容器大小,直接返回成员变量即可,如下所示:

    /*element theSize*/

    unsigned int size(){

        return theSize;

    }

 

    /*alloc theSize*/

    unsigned int capacity(){

        return theCapacity;

    }

判断myVector是否为空,直接判断元素个数是否等于0即可,如下所示:

    bool empty(){

        return theSize == 0;

    }

清空myVector中的元素,需要删除掉数组指针,并把元素个数和容量大小都置0,如下所示:

    void clear(){

        deallocator(array);

        array = 0;

        theSize = 0;

        theCapacity = 0;

    }

push_back、push_front都可以归根于insert,在哪个位置插入,如下所示:

    void push_back(const T& t){

        insert_after(theSize-1,t);

    }

 

    void push_front(const T& t){

        insert_before(0,t);

    }

 

    void insert_after(int pos,const T& t){

        insert_before(pos+1,t);

    }

 

    void insert_before(int pos,const T& t){

        if(theSize==theCapacity){

            T* oldArray = array;

            theCapacity += WALK_LENGTH;

            array = allocator(theCapacity);

            /*memcpy(array,oldArray,theSize*sizeof(T)):*/

            for(unsigned int i = 0 ;i<theSize;++i){

                array[i] = oldArray[i];

            }

            deallocator(oldArray);

    }

 

        for(int i = (int)theSize++;i>pos;--i){

            array[i] = array[i-1];

        }

        array[pos] = t;

}

myVector通过一个连续的数组存放元素,如果集合已满,在新增数据的时候,就要分配一块更大的内存,将原来的数据复制过来,释放之前的内存,再插入新增的元素。这个元素后面的所有元素都向后移动一个位置,在空出来的位置上存入新增的元素。

删除某个元素,则要把这个元素后面的都往前挪,并把元素个数-1,如下所示:

void erase(unsigned int pos){

    if(pos<theSize){

        --theSize;

        for(unsigned int i = pos;i<theSize;++i){

            array[i] = array[i+1];

        }

    }

}

通过分析代码,可以发现vector的特点,如下所述。

(1)随即访问元素效率很高。

(2)push_back的效率也会很高。

(3)push_front的效率非常低,不建议使用。

(4)insert需要把插入位置以后的元素全部后移,效率比较低,不建议使用。

(5)erase需要把删除位置后面的元素全部前移,效率比较低,不建议使用。

(6)当内存不够时,需要重新申请内存,再把以前的元素复制过来,效率也比较低。

3.4 map


http://www.niftyadmin.cn/n/3451267.html

相关文章

拥抱Linux

本文转载自『恋花蝶的博客!』http://blog.csdn.net/lanphaday更多精彩内容,欢迎访问恋花蝶的博客!在这个微软的“黑屏”时代&#xff0c;作为 windows 的替代品&#xff0c;Linux 变得倍受关注。今天 CSDN 的名博阿朱写了篇文章《我可以抱你吗&#xff1f;Linux》&#xff08;h…

实用保健方法

忙碌上班族实用保健有13招 http://samueli.javaeye.com/blog/254121 1、双手捂住耳朵&#xff0c;手指弹动脑袋&#xff0c;10~20次&#xff0c;可促进大脑血液循环。  2、扯耳朵&#xff0c;右手经过后脑勺&#xff0c;往下扯动左耳垂&#xff1b;随后&#xff0c;左手经过后…

一些软件设计网址

本文转载自『恋花蝶的博客!』http://blog.csdn.net/lanphaday更多精彩内容,欢迎访问恋花蝶的博客!作者&#xff1a;赖勇浩&#xff08;http://blog.csdn.net/lanphaday&#xff09;在社区混久了&#xff0c;总看到许多新朋友问“我学会了XX语言&#xff0c;怎么深入&#xff08…

隐藏tabBarViewController底部的tabBar

2019独角兽企业重金招聘Python工程师标准>>> 隐藏tabBarViewController底部的tabBar /// 重写push方法 - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {//隐藏底部barviewController.hidesBottomBarWhenPushed YES;[sup…

面试的准备

1&#xff0e;请介绍一下你自己。 这是外企常问的问题。一般人回答这个问题过于平常&#xff0c;只说姓名、年龄、爱好、工作经验&#xff0c;这些在简历上都有&#xff0c;其实&#xff0c;外企最希望知道的是求职者能否胜任工作&#xff0c;包括&#xff1a;最强的技能、最深…

快速掌握一门语言的50%要点

现在的开发工作要求我们能够快速掌握一门语言。一般来说应对这种挑战有两种态度&#xff1a;其一&#xff0c;粗粗看看语法&#xff0c;就撸起袖子开干&#xff0c;边查Google边学习&#xff1b;其二是花很多时间完整地把整个语言学习一遍&#xff0c;做到胸有成竹&#xff0c;…

linux下修改串口权限

Linux下的设备使用都需要使用sudo或root用户才能打开&#xff0c;为了能让普通用户也能使用串口&#xff0c;可以增加udev规则来实现&#xff0c;具体方法如下&#xff1a; sudo vim /etc/udev/rules.d/70-ttyusb.rules增加如下内容&#xff1a;KERNEL"ttyUSB[0-9]*"…

交友经验

100句经典交友经验 100句经典交友经验有 这样一句话&#xff1a;没有交际能力的人&#xff0c;就象陆地上的船&#xff0c;永远到不了人生的大海。虽然简单&#xff0c;但富有哲理。这话充分说明一个问题&#xff1a;生活中&#xff0c;无论有多么强的能力&#xff0c;多么 好…