程序设计1的问题,简单叙述其需求如下:
需要一种结构,要满足
(1) 其访问速度需要与数组基本一致,可随机存取。
(2) 无法预先知道其精确的存储空间,不应该先行扫描文本串来获得这个值,以避免时间效率的损失。
(3) 在申请存储空间失败的时候,可以进行有效的反应,不应使程序失控。
后来跟踪那个问题,发现文本数据中因为是专业技术文档的缘故,有大量的格式标注符号,其中的词汇信息若按不重复计应该是不超出百万级别的(中文词汇的个数有个基本的上限)。所以简单写了个模板类,实现:预先设定空间时并不申请所有空间、而在实际存取过程中动态分配空间,并且可以基本满足上述三个目标 这些特征。代码如下:
#ifndef __SIMPLEARRAY_H__
#define __SIMPLEARRAY_H__
/*
* 数组的模板类
* 数组的对象有两种类型,一是可c指针输出的(称为C格式Array),另一个是有着自己内存管理
* 方式的数组。后者的管理方式是,对于超过MAX_BLOCK_SIZE的数据,以块的方式进行组织。块的
* 最大个数为MAX_BLOCK_NUM。如此对于一定规模内(MAX_BLOCK_NUM*MAX_BLOCK_SIZE)的数据
* 既可以按照数组的随机存取方式访问数据,又可以根据实际需要自动申请空间,且不存在存储
* 数据移动的现象(如在动态数组中);代价是最多浪费近一个块的空间。
* 在实例化对象时需要指定类型(默认类型为非c格式数组),且类型不可改变。
****************************************************************************************/
#define MAX_BLOCK_NUM 100
#define MAX_BLOCK_SIZE 10000
template<typename T>
class CSimpleArray
{
public:
CSimpleArray(bool bCArray = false);
~CSimpleArray(void);
// 设置存储空间大小
bool SetSize(int Size);
// 获得存储空间大小
int GetSize(void);
// 获得某位置的值引用
T& GetValue(int At);
// 转换成c形式的数组(指针表示)
T* TO_C_ARRAY(void);
// 释放资源
void Clear(void);
private:
void SetBlockNum(void);
private:
T* pValue;
T** pBlockValue;
int size;
int blockNum;
int curBlockNum;
bool bAsCArray;
};
template<typename T>
CSimpleArray<T>::CSimpleArray(bool bCArray/* = false*/)
{
pValue = NULL;
pBlockValue = NULL;
size = 0;
blockNum = 0;
curBlockNum = 0;
bAsCArray = bCArray;
}
template<typename T>
CSimpleArray<T>::~CSimpleArray(void)
{
Clear();
}
template<typename T>
void CSimpleArray<T>::SetBlockNum(void)
{
blockNum = size/MAX_BLOCK_SIZE + 1;
if( blockNum > MAX_BLOCK_NUM )
blockNum = MAX_BLOCK_NUM;
}
template<typename T>
bool CSimpleArray<T>::SetSize(int Size)
{
if( Size <= 0 || this->size == Size )
{
curBlockNum = 0;
return true;
}
Clear();
this->size = Size;
if( Size > MAX_BLOCK_SIZE && !bAsCArray )
{
SetBlockNum();
curBlockNum = 0;
if( NULL == (pBlockValue = new T*[MAX_BLOCK_NUM]) )
return false;
for( int i = 0; i < MAX_BLOCK_NUM; i ++ )
pBlockValue[i] = NULL;
}
else
{
if( NULL == (pValue = new T[size]) )
return false;
}
return true;
}
template<typename T>
int CSimpleArray<T>::GetSize(void)
{
return size;
}
template<typename T>
T& CSimpleArray<T>::GetValue(int At)
{
if( At < 0 || At >= size )
throw "GetElemException of wrong pos in CSimpleArray";
if( pValue || bAsCArray )
return pValue[At];
else //if( pBlockValue )
{
int blockPos = At/MAX_BLOCK_SIZE;
int valPos = At%MAX_BLOCK_SIZE;
if( blockPos >= blockNum )
throw "GetElemException of wrong pos in CSimpleArray";
// 取到没有值的块则对该位置申请空间
if( blockPos >= curBlockNum )
{
for( int i = curBlockNum; i <= blockPos; i ++ )
if( !pBlockValue[i] )
if( NULL == (pBlockValue[i] = new T[MAX_BLOCK_SIZE]) )
throw "New Block Failed in CSimpleArray";
curBlockNum = blockPos + 1;
}
return (pBlockValue[blockPos])[valPos];
}
}
template<typename T>
void CSimpleArray<T>::Clear(void)
{
if( pValue )
{
delete[] pValue;
pValue = NULL;
size = 0;
}
if( pBlockValue )
{
for( int i = 0; i < curBlockNum; i ++ )
{
delete[] pBlockValue[i];
pBlockValue[i] = NULL;
}
delete[] pBlockValue;
pBlockValue = NULL;
blockNum = 0;
curBlockNum = 0;
size = 0;
}
}
template<typename T>
T* CSimpleArray<T>::TO_C_ARRAY(void)
{
return pValue;
}
#endif //__SIMPLEARRAY_H__