1. 程式人生 > >zList一個塊狀連結串列演算法可以申請和釋放同種物件指標,對於大資料量比直接new少需要差不多一半記憶體

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 }