zList一个块状链表算法可以申请和释放同种对象指针,对于大数据量比直接new少需要差不多一半内存
zList是一个C++的块状内存链表,特点:
1、对于某种类别需要申请大量指针,zList是一个很好的帮手,它能比new少很多内存。
2、它对内存进行整体管理,可以将数据和文件快速互操作
3、和vector对象存储对比,vector存储的对象不能使用其指针,因为vector内容变化时vector存储对象的指针会变化
4、zList也可以当做顺序的数组使用,它有自己的迭代器,可以遍历整个数组
下面是申请5千万个RECT指针对比结果:
zList申请五千万RECT指针内存占用:
直接new五千万RECT指针内存占用:
从对比看节省了724.6M的内存
下面是zList实现代码:
#include "stdafx.h"
#include <set>
#include <map>
#include <string>
#include <vector>
#include <windows.h>
using namespace std; template <class T>
struct zElem
{
zElem() { memset(this, , sizeof(zElem)); }
int has() //查找空闲的位置
{
return extra < ? extra : -;
}
bool empty() { return == size; };
bool full() { return == size; };
T *add(int i, const T &r)
{
bit[i] = ;
R[i] = r;
size++;
if (extra == i)//指向下一个位置
{
extra++;
while (extra < )
{
if (bit[extra] == )break;
extra++;
}
}
return R + i;
}
void remove(T *r)
{
int i = (int)(r - R);
if (i >= && i < )
{
bit[i] = ;
if (extra > i)extra = (unsigned short)i;
size--;
}
}
bool in(T *r)
{
int i = (int)(r - R);
return i >= && i < ;
}
T* get(int i)
{
int ind = getInd(i);
return ind == - ? NULL : R + ind;
}
int getInd(int i)
{
if (i >= && i < extra)return i;
int k = extra + , t = extra;
while (k < )
{
if (bit[k] != )
{
if (t == i)return k;
t++;
}
k++;
}
return -;
}
bool getInd(size_t &ind, size_t &off, size_t n)
{
if (ind + n < extra)
{
ind += n;
off = ind;
return true;
}
while (++ind < )
{
if (bit[ind] != )
{
n--;
off++;
if (n==)return true;
}
}
return false;
}
unsigned short extra;//指向当前空闲位置
unsigned short size; //当前已有数据个数
byte bit[]; //标记是否使用
T R[]; //数据存储
};
template <class T>
struct zList
{
struct iterator
{
T* operator *()
{
return p ? &p->head[ind]->R[zind] : NULL;
}
T* operator ->()
{
return p ? &p->head[ind]->R[zind] : NULL;
}
iterator& operator ++()
{
bool bend = true;
if (p&&p->head.size() > ind)
{
for (; ind < p->head.size(); ind++)
{
zElem<T>*a = p->head[ind];
if (zsize + < a->size)
{
a->getInd(zind,zsize,);
bend = false;
break;
}
zind = zsize = -;
}
}
if (bend)
{
ind = zsize = zind = ; p = ;
}
return (*this);
}
bool operator ==(const iterator &data)const
{
return ind == data.ind&&zind == data.zind&&zsize == data.zsize&&p == data.p;
}
bool operator !=(const iterator &data)const
{
return ind != data.ind||zind != data.zind||zsize != data.zsize||p != data.p;
}
explicit operator bool() const
{
return (!p);
}
size_t ind; //p的位置
size_t zind; //zElem中的R位置
size_t zsize; //zElem中zind位置所在的次序
zList *p; //指向链表的指针
};
zList() :size(), extra() { }
~zList()
{
for (auto &a: head)
{
delete a;
}
}
T *add(const T &r)
{
zElem<T>* e;
if (extra >= head.size())
{
e = new zElem<T>();
head.push_back(e);
}
else
{
e = head[extra];
}
int i = e->has();
T *R = e->add(i, r);
size++;
while (extra < head.size() && e->full())
{
e = head[extra];
extra++;
}
return R;
}
void remove(T *r)
{
if (r == NULL)return;
zElem<T> *rem;
size_t i = ;
for (; i < head.size(); i++)
{
rem = head[i];
if (rem->in(r))
{
size--;
rem->remove(r);
if (rem->empty())//删除当前节点
{
head.erase(head.begin() + i);
if (extra == i)
{
//往后查找空闲的位置
while (extra < head.size())
{
if (!head[extra]->full())break;
extra++;
}
}
delete rem;
}
else if(extra > i)
{
extra = i;
}
break;
}
}
}
T* get(int i)
{
for (auto &a : head)
{
if (i < a->size)
{
return a->get(i);
}
i -= a->size;
}
return NULL;
}
void clear()
{
for (auto &a : head)
{
delete a;
}
head.clear();
size = extra = ;
}
iterator begin()
{
iterator it = { ,,,NULL };
if (head.size() > )
{
int i = ;
for (;it.ind < head.size(); it.ind++)
{
zElem<T>*a = head[it.ind];
if (i < a->size)
{
it.p = this;
it.zind = a->getInd(i);
break;
}
i -= a->size;
}
}
return it;
}
iterator end()
{
iterator it = {,,,NULL};
return it;
}
size_t size; //个数
vector<zElem<T>*> head; //开头
size_t extra; //有空余位置的
};
使用方法如下:
int main()
{
zList<RECT> z;
for (int i = ; i < ; i++)
{
//1、申请内存
RECT r = { rand(), rand(), rand(), rand() };
RECT *p = z.add(r);
//2、可以对p进行使用...
//3、释放内存
z.remove(p);
}
getchar();
return ;
}
对zList进行元素遍历,迭代器方法:
int t = ;
zList<RECT>::iterator its = z.begin();
zList<RECT>::iterator ite = z.end();
for (; its != ite; ++its)
{
RECT *p = *its;
t = p->left;
}
对zList进行随机访问遍历,效率没有迭代器高:
int t = ;
for (int i = ; i < z.size; i++)
{
RECT *p = z.get(i);
t = p->left;
}
zList一个块状链表算法可以申请和释放同种对象指针,对于大数据量比直接new少需要差不多一半内存的更多相关文章
- php 大数据量及海量数据处理算法总结
下面的方法是我对海量数据的处理方法进行了一个一般性的总结,当然这些方法可能并不能完全覆盖所有的问题,但是这样的一些方法也基本可以处理绝大多数遇到的问题.下面的一些问题基本直接来源于公司的面试笔试题目, ...
- 解决WCF大数据量传输 ,System.Net.Sockets.SocketException: 远程主机强迫关闭了一个现有的连接
开发中所用的数据需要通过WCF进行数据传输,结果就遇到了WCF大量传输问题 也就是提示System.Net.Sockets.SocketException: 远程主机强迫关闭了一个现有的连接 网上解决 ...
- 大数据量表中,增加一个NOT NULL的新列
这次,发布清洗列表功能,需要对数据库进行升级.MailingList表加个IfCleaning字段,所有的t_User*表加个IfCleaned字段. 脚本如下 对所有的t_User表执行 a ...
- 【POJ2887】【块状链表】Big String
Description You are given a string and supposed to do some string manipulations. Input The first lin ...
- 读<大数据日知录:架构与算法>有感
前一段时间, 一个老师建议我能够学学 '大数据' 和 '机器学习', 他说这必定是今后的热点, 学会了, 你就是香饽饽.在此之前, 我对大数据, 机器学习并没有非常深的认识, 总觉得它们是那么的缥缈, ...
- php获胜的算法的概率,它可用于刮,大转盘等彩票的算法
php获胜的算法的概率,它可用于刮,大转盘等彩票的算法. easy,代码里有具体凝视说明.一看就懂 <?php /* * 经典的概率算法, * $proArr是一个预先设置的数组. * 假设数组 ...
- 滴滴大数据算法大赛Di-Tech2016参赛总结
https://www.jianshu.com/p/4140be00d4e3 题目描述 建模方法 特征工程 我的几次提升方法 从其他队伍那里学习到的提升方法 总结和感想 神经网络方法的一点思考 大数据 ...
- parquet文件格式——本质上是将多个rows作为一个chunk,同一个chunk里每一个单独的column使用列存储格式,这样获取某一row数据时候不需要跨机器获取
Parquet是Twitter贡献给开源社区的一个列数据存储格式,采用和Dremel相同的文件存储算法,支持树形结构存储和基于列的访问.Cloudera Impala也将使用Parquet作为底层的存 ...
- 教你做一个牛逼的DBA(在大数据下)
一.基本概念 大数据量下,搞mysql,以下概念需要先达成一致 1)单库,不多说了,就是一个库 2)分片(sharding),水平拆分,用于解决扩展性问题,按天拆分表 3)复制(replication ...
随机推荐
- Python爬虫入门教程 60-100 python识别验证码,阿里、腾讯、百度、聚合数据等大公司都这么干
常见验证码 之前的博客中已经解决了一些常见验证码的问题,但是验证码是层出不穷的,目前解决验证码除了通过常规手段解决以外,还可以通过人工智能领域的深度学习去解决 深度学习?! 无疑对爬虫coder提高了 ...
- 关于JVM的垃圾回收(GC) 这可能是你想了解的
目录 1 JVM中Java对象的分类 2 JVM的GC类型及触发条件 2.1 Young GC 2.2 Full GC 3 Java对象生成时的内存申请过程 3 Oracle JDK中的垃圾收集器 3 ...
- Winform/WPF中内嵌BeetleX的HTTP服务
在新版本的BeetleX.FastHttpApi加入了对netstandard2.0支持,如果程序基于.NetFramework4.6.1来构建WinForm或WPF桌面程序的情况下可以直接把Beet ...
- 在已有的Asp.net MVC项目中引入Taurus.MVC
Taurus.MVC是一个优秀的框架,如果要应用到已有的Asp.net MVC项目中,需要修改一下. 1.前提约定: 走Taurus.MVC必须指定后缀.如.api 2.原项目修改如下: web.co ...
- 第一课《.net之--泛型》
今天我来学习泛型,泛型是编程入门学习的基础类型,从.net诞生2.0开始就出现了泛型,今天我们开始学习泛型的语法和使用. 什么是泛型? 泛型(generic)是C#语言2.0和通用语言运行时(CLR) ...
- js 对象拷贝
在JavaScript中,数据类型分为两大类:基本数据类型和复杂数据类型.基本数据类型包括Number.Boolean.String.Null.String),而复杂数据类型包括Object.Func ...
- svn统计代码行数(增量)
转载请标明出处,维权必究:https://www.cnblogs.com/tangZH/p/10770296.html android代码,两个版本之间,代码行数增加了多少,怎么得出呢? 1.安装To ...
- Adreno OpenCL坑——bool转int
在项目代码中为了避免条件分支,需要把bool变成int的形式,然后通过向量运算的形式和单个单个的形式,其结果却是不同,向量的方式为(-1, 0),而单个的转换则为(1, 0) 有如下kernel代码: ...
- 运维DBA要不要学python
运维DBA要不要学python 我个人认为是:要 现在python在运维数据库的工作中主要用在 1.编写一些运维脚本 2.编写运维管理平台 3.研究互联网大厂的运维脚本/工具并应有 特别是运维开源数据 ...
- 4.29 初始mysql