CSDN-markdown

来源:互联网 发布:猫喜欢臭袜子 知乎 编辑:程序博客网 时间:2024/05/16 15:09

C++数据结构Array的实现

记第一次CSDN-markdowm编辑器写博客,访问我的github:

 ·Array的特点
 ·表格列举
 ·代码实现


Array与普通数组、链表的区别

   >STL中的array与普通数组的区别在于它有更完备的机制,更安全,更方便,鲁棒性强,如越界检查等,此外有更多的属性和方法,功能更全面。而vector是一种动态数组,其大小在运行期间确定,可以扩充,内容存储在堆上,C++数组是一种内部类型,其大小运行期间不可变,内容存储在栈上。
—————— [ chen ]

  此外,在线段树数据结构中,数组形式更适合在编程竞赛中使用,在已经知道线段树的最大规模的情况下,直接开足够空间的数组,然后在上面建立线段树。一般不用链表。

表格列举

  首先思考一个问题:
  有100000000000个数从1开始编号
   (1)求位于区间[i,j)中所有数的和(1<=i<=j<=100000000001);
   (2)第i个数更新为x.
  针对(1)(2)问题,有两种解法:
   (1)遍历[i,j),逐个相加;
   (2)先建立保存前n项和的一个数组S,那么[i,j)的和为S[j]-S[i].
  可见,第二种方法明显更优,对于每次统计和只需查表,然后进行一次减法,由于数组的随机访问性,效率极高,这种方法类似于图像处理中的积分图法,配合Hessian矩阵求积求图像的二阶特征,效率大大提高,这也是SURF算法比SIFT算法快三倍的原因。
  但是,在求第二个问题时,第二种解法需要更新前i个前n项和才能重构整个积分数组(我姑且这么叫),而此时第一种解法只需要更新原数组中的第i个数。
  事实上上面的问题就是线段树要解决的问题,即解决统计和修改之间的矛盾
方法一修改快统计慢,方法二修改慢统计快。而线段树统计和修改都比较快,详细可以了解一下线段树。
  下面仅以表格列举出前部分叙述的内容:

数据结构 优缺点 使用场合 C++ 数组 内部类型,粗暴易用 不严谨的实验场合 STL array 安全、方便、全面,用来代替普通数组 严谨的程序,需要强鲁棒性 STL vector 动态数组,可扩容 快速开发 线段树 统计和修改都比较快 符合区间加法,同时有统计的修改两个诉求,如求最大数、最大公因数、数字和

  在线段树的启发下,考虑用线段树的思想做SURF中的积分图。


代码实现

#include <iostream>#include <cstdlib>#include <string>#define DEAFULT_SIZE 100using namespace std;//数组的抽象数据类型描述template <class Type>class Array{private:    Type* element;//建立存放空间    int ArraySize;//数组大小    void getArray();//建立数组空间public:    Array(int size=DEAFULT_SIZE);//构造函数    Array(const Array<Type>& x);//复制构造函数    ~Array();//析构函数    const Type& operator [] (int i);//取元素    Array<Type>& operator = (const Array<Type>& A);//赋值操作    int length() const;//取数组长度    void resize(int size);//扩充数组};/******************************************************////Array实现/////建立数组template <class Type>void Array<Type>::getArray(){    element=new Type[ArraySize];    if(element==NULL){        ArraySize=0;        cerr<<"存储分配错误!"<<endl;        return;    }}//构造函数template <class Type>Array<Type>::Array(int size){    if(size<=0){        ArraySize=0;        cerr<<"非法数组大小"<<endl;        return;    }    ArraySize=size;    getArray();}//复制构造函数template <class Type>Array<Type>::Array(const Array<Type>& x){    int n=x.ArraySize;    ArraySize=n;    element=new Type[n];    if(element==NULL ){        ArraySize=0;        cerr<<"存储分配错误!"<<endl;        return;    }    Type* srcptr=x.element;    Type* dstptr=element;    while(n--) *dstptr++ = *srcptr++;}//析构函数template <class Type>Array<Type>::~Array(){     delete []element;}//取下标元素template <class Type>//Type & Array<Type>::operator [ ] (int i){const Type & Array<Type>::operator [ ] (int i){    if(i < 0 || i > ArraySize-1){        cerr<<"非法索引!"<<endl;        return NULL;               //error C2440: “return”: 无法从“int”转换为“double &”,注释掉可以运行                                   //已解决,关于非常量引用,非常量引用的初始值必须为左值”,左值基本上可以理解为能对其取地址的值,如果地址都没有,怎么可能作为非常量引用的值呢?    }                              //即给左值做const限定即可    return element[i];}//赋值操作template <class Type>Array<Type>& Array<Type>::operator = (const Array<Type>& A){    int n=A.ArraySize;    Type* srcptr=A.element;    Type* dstptr=element;    while(n--) *dstptr++ = *srcptr++;}//取数组长度template <class Type>int Array<Type>::length() const{    if (element==NULL)    {        //ArraySize=0;             //error C3490: 由于正在通过常量对象访问“ArraySize”,因此无法对其进行修改        cerr<<"存储分配错误!"<<endl;        return NULL;    }    return ArraySize;}//扩充数组template <class Type>void Array<Type>::resize(int size){    if(size<0||size==ArraySize){        cerr<<"不合理的请求!"<<endl;        return;    }    Type* newArray=new Type[size];                     //创建新数组    if(newArray==NULL){        cerr<<"存储分配错误!"<<endl;        return;    }    int n=(size<ArraySize)?size:ArraySize;    Type* srcPtr=element;    Type* dstPtr=newArray;    while(n--) *dstPtr++ = *srcPtr++;    delete []element;    element=newArray;    ArraySize=size;}int main(){    Array<double> testArray(DEAFULT_SIZE);    cout<<"testArray的长度是:"<<testArray.length()<<endl;    cout<<"testArray[2]是:"<<testArray[2]<<endl;    testArray.resize(1010);    cout<<"testArray的长度是:"<<testArray.length()<<endl;    cout<<"testArray[1000]是:"<<testArray[1000]<<endl;    return 0;}

0 0