数据结构(04)_数组类的实现

C++中支持原生数组,但由于原生数组的天然缺陷(不能获取长度信息、越界访问不会报错...),我们有必要来开发自己的数组类,从而解决这些问题。
数组类的继承关系如图:

19.数组类的实现_1

19.1.抽象类模板Array

需求分析:
1、由于线性表,不能作为数组直接使用,我们需要自己实现一个数组类来代替原生数组。
2、解决原生数组越界访问不会报错的问题
3、提供数组的长度信息

19.2.Array设计要点:

  • 抽象类模本,存储空间的位置和大小由子类指定。
  • 重载数组操作符,并判断访问下标是否越界(合法)
  • 提供数组长度信息的抽象访问函数
  • 提供数组对象间的复制操作(通过重载拷贝构造函数和赋值操作符完成)
    template < typename T >
    class Array : public Object
    {
    protected:
    T *m_array;
    public:
    T& operator [] (int index)
    T operator [] (int index) const
    bool get(int index, const T& e)
    bool set(int index, const T& e)
    virtual int length(void) = 0;
    };

    19.2.1. Array的实现

#ifndef ARRRY_H
#define ARRRY_H

#include "Object.h"
#include "Exception.h"

namespace DTLib
{
template < typename T >
class Array : public Object
{
protected:
    T *m_array;
public:
    T& operator [] (int index)
    {
        if( (index>=0) && (index<length()) )
        {
            return m_array[index];
        }
        else
        {
            THROW_EXCEPTION(IndexOutOfBoundsException, "array index out of range...");
        }
    }

    T operator [] (int index) const
    {
        return const_cast<Array<T>&>(*this)[index];
    }

    bool get(int index, const T& e)
    {
        bool ret = (index>=0) && (index<length());

        if( ret )
        {
            e = m_array[index];
        }

        return ret;
    }

    bool set(int index, const T& e)
    {
        bool ret = (index>=0) && (index<length);

        if( ret )
        {
            m_array[index] = e;
        }

        return ret;
    }

    virtual int length(void) = 0;
};
}

#endif // ARRRY_H

19.3.StaticArray的实现

设计要点:

  • 封装原生数组;
  • 使用模板参数决定数组大小
  • 实现函数返回数组长度
  • 拷贝构造和赋值重载
    template < typename T, int N >
    class StaticArray : public Array<T>
    protected:
    T m_space[N];
    public:
    StaticArray()
    // 提供拷贝构造喊赋值重载函数,实现数组的拷贝
    StaticArray(const StaticArray<T, N>& obj)
    T& operator = (const StaticArray<T, N>& obj)
    int length(void)
    };

    19.3.1. StaticArray的实现

#ifndef STATICARRAY_H
#define STATICARRAY_H

#include "Array.h"

namespace DTLib
{
template <typename T, int N>
class StaticArray : public Array<T>
{
protected:
    T m_space[N];
public:
    StaticArray()
    {
        this->m_array = m_space;
    }

    StaticArray(const StaticArray<T, N>& obj)
    {
        this->m_array = m_space;

        for(int i=0; i<length();i++)   // 数组元素拷贝
        {
            m_space[i] = obj.m_space[i];
        }
    }

    T& operator ==(const StaticArray<T, N>& obj)
    {
        if(this != &obj)
        {
            this->m_array = m_space;

            for(int i=0; i<length();i++)
            {
                m_space[i] = obj.m_space[i];
            }
        }
    }

    int length(void)
    {
        return N;
    }
};
}
#endif // STATICARRAY_H

20.数组类的实现_2

20.1.DynamicArray的实现

设计要点:类模板

  • 动态确定内部数组空间的大小
  • 实现函数返回数组的长度
  • 拷贝构造和赋值操作
    template < typename T >
    class DynamicArray : public Array<T>
    {
    protected:
    int m_length;
    public:
    DynamicArray(int length)
    DynamicArray(const DynamicArray<T>& obj)
    DynamicArray<T>& operator = (const DynamicArray<T>& obj)
    void resize(int length)
    ~DynamicArray()
    };

    20.2.DynamicArray代码优化

    DynamicArray类中的函数实现存在重复的逻辑,可以进行代码优化。
    重复代码逻辑的抽象:
    — init 函数中实现对象构造时的初始化操作
    — copy 函数负责从堆空间中申请内存,并执行拷贝构造操作
    — updata 将指定的堆空间作为内部存储数组使用

    20.2.1. DynamicArray实现

#ifndef DYNAMICLIST_H
#define DYNAMICLIST_H

#include "SeqList.h"

namespace DTLib
{

template <typename T>
class DynamicList : public SeqList<T>
{

protected:
    int m_capacity;
public:
    DynamicList(int capacity)
    {
        this->m_array = new T[capacity];
        if(this->m_array != NULL)
        {
            this->m_length = 0;
            this->m_capacity = capacity;
        }
        else
        {
            THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create DynamicList object ...");
        }
    }

    int capacity()const
    {
        return m_capacity;
    }

    void resize(int capacity)
    {
        if(capacity != m_capacity)
        {
            T* array = new T[capacity];
            if(array != NULL)
            {
                int length = (this->m_length < capacity ? this->m_length : capacity);
                for(int i=0;i<length;i++)
                {
                    array[i] = this->m_array[i];
                }

                T* temp = this->m_array;
                this->m_array = array;
                this->m_length = length;
                this->m_capacity = capacity;
                delete[] temp;
            }
            else
            {
                THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create DynamicList object ...");
            }
        }
    }

    ~DynamicList()
    {
        delete[] this->m_array;
    }
};

}

#endif // DYNAMICLIST_H

总结:

  • StaticArray通过封装原生数组的方式,实现数组类
  • DynamicArray动态申请堆空间,使得数组长度动态可变
  • 数组对象能够代替原生数组,并且使用上更安全
  • 代码优化时项目开发必不可少的环节

原文地址:http://blog.51cto.com/11134889/2126831

时间: 2024-10-17 19:18:40

数据结构(04)_数组类的实现的相关文章

数据结构(一)_数组

数组基本知识 数组对于每一门编程语言来说都是重要的数据结构之一,当然不同语言对数组的实现及处理也不尽相同. Java语言中提供的数组是用来存储固定大小的同类型元素. public class Demo1 { public static void main(String[] args) { // 定义一个数组,保存五名学生的成绩 int[] scores = { 78, 93, 97, 84, 63 }; // 输出数组中的第二个成绩 System.out.println("数组中的第2个成绩为:

网易云课堂_C++程序设计入门(下)_第10单元:月映千江未减明 – 模板_第10单元 - 单元作业:OJ编程 - 创建数组类模板

第10单元 - 单元作业:OJ编程 - 创建数组类模板 查看帮助 返回 温馨提示: 1.本次作业属于Online Judge题目,提交后由系统即时判分. 2.学生可以在作业截止时间之前不限次数提交答案,系统将取其中的最高分作为最终成绩. 本单元作业练习创建模板类.单元作业会涉及冒泡排序.线性查找等算法.如果对排序.查找不熟悉,可以自行baidu或者google 依照学术诚信条款,我保证此作业是本人独立完成的. 1 编写一个数组类模板 Array,能够存储不同类型的数组元素.对数组元素进行查找.

当数据结构遇到编程语言——数组

赵振江 数据结构 数组 一维数组 "数组"你真的很了解吗? 数组大家都不是很陌生,它已经"植入"了许多编程语言,但初学者一提到数组,可能不会联想到"数据结构",而是想到的会是一种"数据类型",数组本质上就是一种极其简单的数据结构.所谓数组,就是相同数据类型的元素按一定顺序排列的集合.也就是在内存中划分一段连续的且大小固定(注意是连续)的内存空间(或者其他存储器)保存相同数据类型的数据,如下图.一般说的简单数组,都是静态的数组,

[数据结构]最小堆的类模板实现

堆数据结构是一种数组对象,它可以被视为一科完全二叉树结构. 它的特点是父节点的值大于(小于)两个子节点的值(分别称为最大堆和最小堆).它常用于管理算法执行过程中的信息,应用场景包括堆排序,优先队列等. 1.根结点若有子树,则子树一定也是堆. 2.根结点一定大于(或小于)子结点. 因为要求堆必须是完全二叉树,所以可以用线性的数据结构,比如数组,来实现堆. 利用数组实现,则对于长为N的堆中的元素从0到N-1排列,有: i的父结点:Parent(i)=(i+1)/2-1 i的左叶子:Left(i)=(

java中的数组类与集合类详解及原理介绍

一.类结构概述 当需要存储大量数据对象时,需要用到数组类或者集合类.java中的类结构如下(红色为接口,蓝色为类): Iterator接口:是对collection进行迭代的迭代器,它允许调用者利用定义良好的语义在迭代期间从迭代器所指向的collection移除元素. Collection接口:Collection表示一组对象,最小存储数据颗粒是单一的 List接口:是数组形式,允许数据重复:是有序的 collection(也称为序列),此接口的用户可以对列表中每个元素的插入位置进行精确地控制,

数组类模板(四十九)

之前我们学习了类模板,今天我们来看看数组类模板.模板参数可以是数值型参数(非类型参数),如下 使用数值型模板参数是有限制的,如:a> 变量不能作为模板参数:b> 浮点数不能作为模板参数:c> 类对象不能作为模板参数.其本质是模板参数是在编译阶段被处理的单元,因此在编译阶段必须准确无误的唯一确定. 下来我们用函数模板来实现一个面试题:用最高效的方法求 1+2+3+...+N 的值. #include <iostream> #include <string> usin

第二十二篇 玩转数据结构——构建动态数组

1.. 数组基础 数组就是把数据码成一排进行存放. Java中,数组的每个元素类型必须相同,可以都为int类型,string类型,甚至是自定义类型. 数组的命名要语义化,例如,如果数组用来存放学生的成绩,那么命名为scores就比较合适. 索引(index)是数组中的一个重要概念,它是我们给数组中的每个元素分配的编号,从0开始,依次递增.如果数组中存放了n个元素,第一个元素的索引是0,最后一个元素的索引是n-1. 通过索引,我们可以对数组中的元素进行快速访问,例如,我们访问索引为2的元素也就是数

04 JAVA数组

04.01_Random的概述和基本使用 Random的使用步骤我们想产生1~100(包含1和100)的随机数该怎么办呢? 我们不需要自己去写算法,因为Java已经为我们提供好了产生随机数的类---Random: 作用:– 用于产生一个随机数? 使用步骤(和Scanner类似)– 导包? import java.util.Random;– 创建对象? Random r = new Random();– 获取随机数? int number = r.nextInt(10);? 产生的数据在0到10之

从零开始实现数据结构(一) 动态数组

从零开始实现数据结构(一) 动态数组 动态数组是所有数据结构中最简单的一种,甚至在很多的语言中,数组本身就是可以不定长的.因为在学习c++的时候,使用动态数组的各种操作都不是很方便(数据结构的学习最好还是c或c++,基础打好了其他的语言数据结构就很简单).所以开始学习如何去实现一个像STL中的vector一样的动态数组. 创建数组基类CArray 因为后面还准备写一个有序数组,所以这里使用一个CArray类,把数组的各种基本特性先创建好.后面需要写什么数组,就可以写它下面的子类,来完成特殊的功能