zList一个块状链表算法可以申请和释放同种对象指针,对于大数据量比直接new少需要差不多一半内存

Posted virtualnatural

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了zList一个块状链表算法可以申请和释放同种对象指针,对于大数据量比直接new少需要差不多一半内存相关的知识,希望对你有一定的参考价值。

zList是一个C++的块状内存链表,特点:

1、对于某种类别需要申请大量指针,zList是一个很好的帮手,它能比new少很多内存。

2、它对内存进行整体管理,可以将数据和文件快速互操作

3、和vector对象存储对比,vector存储的对象不能使用其指针,因为vector内容变化时vector存储对象的指针会变化

4、zList也可以当做顺序的数组使用,它有自己的迭代器,可以遍历整个数组

下面是申请5千万个RECT指针对比结果:

zList申请五千万RECT指针内存占用:技术分享图片

直接new五千万RECT指针内存占用:技术分享图片

从对比看节省了724.6M的内存

下面是zList实现代码:

技术分享图片
  1 #include "stdafx.h"
  2 #include <set>
  3 #include <map>
  4 #include <string>
  5 #include <vector>
  6 #include <windows.h>
  7 using namespace std;
  8 
  9 template <class T>
 10 struct zElem
 11 {
 12     zElem() { memset(this, 0, sizeof(zElem)); }
 13     int has() //查找空闲的位置
 14     {
 15         return extra < 1024 ? extra : -1;
 16     }
 17     bool empty() { return 0 == size; };
 18     bool full() { return 1024 == size; };
 19     T *add(int i, const T &r)
 20     {
 21         bit[i] = 1;
 22         R[i] = r;
 23         size++;
 24         if (extra == i)//指向下一个位置
 25         {
 26             extra++;
 27             while (extra < 1024)
 28             {
 29                 if (bit[extra] == 0)break;
 30                 extra++;
 31             }
 32         }
 33         return R + i;
 34     }
 35     void remove(T *r)
 36     {
 37         int i = (int)(r - R);
 38         if (i >= 0 && i < 1024)
 39         {
 40             bit[i] = 0;
 41             if (extra > i)extra = (unsigned short)i;
 42             size--;
 43         }
 44     }
 45     bool in(T *r)
 46     {
 47         int i = (int)(r - R);
 48         return i >= 0 && i < 1024;
 49     }
 50     T* get(int i)
 51     {
 52         int ind = getInd(i);
 53         return ind == -1 ? NULL : R + ind;
 54     }
 55     int getInd(int i)
 56     {
 57         if (i >= 0 && i < extra)return i;
 58         int k = extra + 1, t = extra;
 59         while (k < 1024)
 60         {
 61             if (bit[k] != 0)
 62             {
 63                 if (t == i)return k;
 64                 t++;
 65             }
 66             k++;
 67         }
 68         return -1;
 69     }
 70     bool getInd(size_t &ind, size_t &off, size_t n)
 71     {
 72         if (ind + n < extra)
 73         {
 74             ind += n;
 75             off = ind;
 76             return true;
 77         }
 78         while (++ind < 1024)
 79         {
 80             if (bit[ind] != 0)
 81             {
 82                 n--;
 83                 off++;
 84                 if (n==0)return true;
 85             }
 86         }
 87         return false;
 88     }
 89     unsigned short extra;//指向当前空闲位置
 90     unsigned short size; //当前已有数据个数
 91     byte bit[1024];         //标记是否使用
 92     T R[1024];             //数据存储
 93 };
 94 template <class T>
 95 struct zList
 96 {
 97     struct iterator
 98     {
 99         T* operator *()
100         {
101             return p ? &p->head[ind]->R[zind] : NULL;
102         }
103         T* operator ->()
104         {
105             return p ? &p->head[ind]->R[zind] : NULL;
106         }
107         iterator& operator ++()
108         {
109             bool bend = true;
110             if (p&&p->head.size() > ind)
111             {
112                 for (; ind < p->head.size(); ind++)
113                 {
114                     zElem<T>*a = p->head[ind];
115                     if (zsize + 1 < a->size)
116                     {
117                         a->getInd(zind,zsize,1);
118                         bend = false;
119                         break;
120                     }
121                     zind = zsize = -1;
122                 }
123             }
124             if (bend)
125             {
126                 ind = zsize = zind = 0; p = 0;
127             }
128             return (*this);
129         }
130         bool operator ==(const iterator &data)const
131         {
132             return ind == data.ind&&zind == data.zind&&zsize == data.zsize&&p == data.p;
133         }
134         bool operator !=(const iterator &data)const
135         {
136             return ind != data.ind||zind != data.zind||zsize != data.zsize||p != data.p;
137         }
138         explicit operator bool() const 
139         {    
140             return (!p);
141         }
142         size_t ind;            //p的位置
143         size_t zind;        //zElem中的R位置
144         size_t zsize;        //zElem中zind位置所在的次序
145         zList *p;            //指向链表的指针
146     };
147     zList() :size(0),  extra(0) { }
148     ~zList() 
149     {
150         for (auto &a: head)
151         {
152             delete a;
153         }
154     }
155     T *add(const T &r)
156     {
157         zElem<T>* e;
158         if (extra >= head.size())
159         {
160             e = new zElem<T>();
161             head.push_back(e);
162         }
163         else
164         {
165             e = head[extra];
166         }
167         int i = e->has();
168         T *R = e->add(i, r);
169         size++;
170         while (extra < head.size() && e->full())
171         {
172             e = head[extra];
173             extra++;
174         }
175         return R;
176     }
177     void remove(T  *r)
178     {
179         if (r == NULL)return;
180         zElem<T> *rem;
181         size_t i = 0;
182         for (; i < head.size(); i++)
183         {
184             rem = head[i];
185             if (rem->in(r))
186             {
187                 size--;
188                 rem->remove(r);
189                 if (rem->empty())//删除当前节点
190                 {
191                     head.erase(head.begin() + i);
192                     if (extra == i)
193                     {
194                         //往后查找空闲的位置
195                         while (extra < head.size())
196                         {
197                             if (!head[extra]->full())break;
198                             extra++;
199                         }
200                     }
201                     delete rem;
202                 }
203                 else if(extra > i)
204                 {
205                     extra = i;
206                 }
207                 break;
208             }
209         }
210     }
211     T* get(int i)
212     {
213         for (auto &a : head)
214         {
215             if (i < a->size)
216             {
217                 return a->get(i);
218             }
219             i -= a->size;
220         }
221         return NULL;
222     }
223     void clear()
224     {
225         for (auto &a : head)
226         {
227             delete a;
228         }
229         head.clear();
230         size = extra = 0;
231     }
232     iterator begin()
233     {
234         iterator it = { 0,0,0,NULL };
235         if (head.size() > 0)
236         {
237             int i = 0;
238             for (;it.ind < head.size(); it.ind++)
239             {
240                 zElem<T>*a = head[it.ind];
241                 if (i < a->size)
242                 {
243                     it.p = this;
244                     it.zind = a->getInd(i);
245                     break;
246                 }
247                 i -= a->size;
248             }
249         }
250         return it;
251     }
252     iterator end()
253     {
254         iterator it = {0,0,0,NULL};
255         return it;
256     }
257     size_t size;                //个数
258     vector<zElem<T>*> head;        //开头
259     size_t extra;                //有空余位置的
260 };
View Code

使用方法如下:

 1 int main()
 2 {
 3     zList<RECT> z;
 4     for (int i = 0; i < 50000000; i++)
 5     {
 6         //1、申请内存
 7         RECT r = { rand(), rand(), rand(), rand() };
 8         RECT *p = z.add(r);
 9         //2、可以对p进行使用...
10         //3、释放内存
11         z.remove(p);
12     }
13     getchar();
14     return 0;
15 }

对zList进行元素遍历,迭代器方法:

1 int t = 0;
2 zList<RECT>::iterator its = z.begin();
3 zList<RECT>::iterator ite = z.end();
4 for (; its != ite; ++its)
5 {
6     RECT *p = *its;
7     t = p->left;
8 }

对zList进行随机访问遍历,效率没有迭代器高:

1 int t = 0;
2 for (int i = 0; i < z.size; i++)
3 {
4     RECT *p = z.get(i);
5     t = p->left;
6 }

 

以上是关于zList一个块状链表算法可以申请和释放同种对象指针,对于大数据量比直接new少需要差不多一半内存的主要内容,如果未能解决你的问题,请参考以下文章

Python数据结构与算法(附录)——块状链表的动态调整

动态内存分配

算法漫游指北(第三篇):数组(列表)链表跳表在python中实现链表

块状链表

常用概念比较

分块,莫队,BSGS,块状链表