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 };
使用方法如下:
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 }