C/C++语言实现动态数组

C数组的小问题

     这里说的动态数组是可以根据需要动态增长占用内存的数组,比如程序初始分配了100个元素,可是运行了一段时间后区区100个空间不能满足了,现在需要400个,怎么办呢;那肯定需要再额外分配300个。
     C语言有realloc()函数来解决空间扩充的问题,但是不要忘了realloc可能会迁移内存,很多时候数组中的元素会被其它函数/模块引用,如果地址发生了变化,结果将是灾难性的。
     那么STL的vector呢?它也有相同的问题。
     一次分配足够的空间是可以解决这个问题,很明显这会造成内存的浪费,这个做法不算明智。
     不使用数组呢?使用list能解决一部分问题,但是list不能支持随机访问啊,鉴于效率上的硬伤,显然不能随便用list替换数组。
     怎么解决这个问题呢?动态数组!在HPServer 的Demutex Table就用到了动态数组,事实证明效果不错。

动态数组的特征

动态数组是一个很简单易用的数据结构,但是简单不代表优点小,它的特征如下:
1 根据需要动态批量增长内存;
2 一经分配,元素地址不会再次变化;
3 实现简单,效率高,事实上它和普通数组相比基本没有效率损失;
4 最大个数固定;
 
其实最重要的就是特征2了,不然直接使用realloc多方便呢,当然动态数组的实现也很方便,下面就会详细说说。
特征4实际上是个限制,但是相信我,你的程序不可能达到这个最大值。

动态数组的实现

如上面所说的,动态数组实现起来很简单,以下都假设数组元素类型是T,首先需要一个辅助数据结构。

  1. struct ARRAY_ELE_S  
  2. {  
  3.     T item_array[1024];  
  4. };  
  5. ARRAY_ELE_S *pArray[2000];  
  6. int iSize;   

变量pArray是一个ARRAY_ELE_S类型的指针数组,这个也就是你的动态数组了;iSize记录了当前数组的大小。
上面的代码表明:
1 数组每次动态增长1024个元素;
2 数组的最大元素个数可以到:2000*1024个,如果这个还不够,你可以把这个值改的更大点。
先来看看内存占用,pArray本身占用2000*4,大约是8K的内存,基本可以忽略了。
如果一次分配一个2000*1024的数组array[2000*1024],那么一次就要分配的内存是:2*sizeof(T) M,空间浪费严重。

再来看看效率,下面就从数组最主要的操作——随机访问来看看它的效率如何;接下来再看看它是如何根据需要动态增长的。

 

随机访问

访问指定的索引位置上的数组元素,这个需要两步计算,首先定位到元素在哪个子数组上,然后再定位到子数组的元素上;其实很简单。

  1. T *get(int idx)  
  2. {  
  3.     // 确保索引有效  
  4.     if((idx>=0) && (idx<iSize))  
  5.     {  
  6.         int idx_maj = idx/1024; // 主索引  
  7.         int idx_mor = idx - (idx_maj); // 次索引  
  8.         return (&(pArray[idx_maj]->item_array[idx_mor]));  
  9.     }  
  10.     return NULL;  
  11. }  

 

动态增长

如果当前空间不够,需要动态增长数组,不然怎么叫动态呢,基本思想就是如果需要的size超过当前的数组大小,就需要增长数组,直到能够容纳size个元素,代码如下所示。

  1. int reclac(int size)  
  2. {  
  3.     if(size >= 1024*2048)     return -1; // 太大了  
  4.     while(iSize <= size)  
  5.     {  
  6.         // 分配内存,并初始化为0  
  7.         int idx = iSize/1024;  
  8.         pArray[idx] = (ARRAY_ELE_S*)calloc(1, sizeof(ARRAY_ELE_S));  
  9.         if(pArray[idx] == NULL)  
  10.         {  
  11.             return (-1);  
  12.         }  
  13.         iSize += 1024;  
  14.     }  
  15.     return 0;  
  16. }  

动态数组就这么多零碎了,怎么样,实现起来够简单吧。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值