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 ...
随机推荐
- 带着新人看java虚拟机05(多线程篇)
上一篇我们主要是把一些基本概念给说了一下以及怎么简单的使用线程池,我们这一节就来看看线程池的实现: 1.线程池基本参数 以Executors.newFixedThreadPool()这种创建方式为例: ...
- Sql 优化解决方案
转自:https://blog.csdn.net/jie_liang/article/details/77340905 用以记录: 在sql查询中为了提高查询效率,我们常常会采取一些措施对查询语句进行 ...
- Hibernate工具类_抽取重复核心代码
问题:在Hibernate中每次执行一次操作总是需要加载核心配置文件,获取连接池等等都是重复动作,所以抽取出来 解决: package com.xxx.utils; /** *Hibernate的工具 ...
- html的<h>标签
<h>标签:标题标签. <h>标签只有六个:<h1>........<h6>
- 阿里java编码规范考试总结
前几天,考了阿里编码规范刚好80险过,总结出以下例题,答案有错,欢迎评论 1.关于方法的返回值是否可以为null,下列说法正确的是(BCD) A.方法的返回值可以为null,如果是集合,必须返回空集合 ...
- 搭建环境-Monkeyrunner-自动化测试工具
这篇博客帮助挺大,我补充部分,帮助同样的小白哈哈,侵删 https://www.cnblogs.com/lynn-li/p/5885001.html 1.前期准备 需要安装:JDK,SDK,pytho ...
- WebGL绘制有端头的线
关于WebGL绘制线原理不明白的小伙伴,可以看看我之前的文章WebGL绘制有宽度的线.这一篇我们主要来介绍端头的绘制,先看效果图. 端头一般被称为lineCap,主要有以下三种形式: butt最简单等 ...
- Cocoa包管理器之Carthage详解及CocoaPods中心化+Carthage的二进制化
上篇博客详细的聊了CocoaPods的相关内容,今天我们就来介绍另一个Cocoa的包管理器Carthage.在上家公司用Swift开发工程时,用的就是Carthage.Carthage诞生于14年11 ...
- 这些好用的 Chrome 插件,提升你的工作效率
本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. Google ...
- java~集合分组groupby的实现
对于数据聚合来说,分组操作是很常见的,在.net里有lambda和linq,而在java里也有lambda,现在我们来实现对一个集合进行分组. 一 准备工作,有两个类型 @Value class It ...