需要对数据进行分析处理,数据特征如下:
---------------------------------------------
1、每条数据Record有一个ID标识
2、不同数据record之间通过这个ID关联,但是ID关系并不是对应相等,也就是说组合后的数据ID并不是唯一的。
3、数据之间的关系通过两个ID值关联起来,比如ID1+ID2可以唯一确定一组有关系的数据。也就是说这组数据内的每条数据的ID满足如下关系:ID = ID1或者ID = ID2
4、数据处理的开始确定ID1和ID2,要求查找满足要求的数据。判决条件就是 ID = ID1 || ID = ID2给定的ID值对很多,需要设计一个数据结构实现快速的查找。请各位大侠帮忙设计设计,什么样的数据结构以及算法可以较好的实现这个功能呢?
---------------------------------------------
1、每条数据Record有一个ID标识
2、不同数据record之间通过这个ID关联,但是ID关系并不是对应相等,也就是说组合后的数据ID并不是唯一的。
3、数据之间的关系通过两个ID值关联起来,比如ID1+ID2可以唯一确定一组有关系的数据。也就是说这组数据内的每条数据的ID满足如下关系:ID = ID1或者ID = ID2
4、数据处理的开始确定ID1和ID2,要求查找满足要求的数据。判决条件就是 ID = ID1 || ID = ID2给定的ID值对很多,需要设计一个数据结构实现快速的查找。请各位大侠帮忙设计设计,什么样的数据结构以及算法可以较好的实现这个功能呢?
组合后的记录有很多,比如已经处理好一组数据group 1:rec1、rec2、rec3 。
其中rec1.id = 1 rec2.id = 2 rec3.id = 1 rec4.id = 2 ......
MB_ee 2
MB_UU 4
MB_OO 8
.
.
.利用二进制的位实现标志?
GROUD#01: REC1,REC2,REC3,REC4,...
这样的一组数据,REC1.ID=0X01, REC2.ID=0X02,REC3.ID=0X01,REC4.ID=0X01可以看到这样的一组数据他的特征是ID=0X01或者ID=0X02,这时就说明ID(0X01,0X02)为这组数据的ID对,ID=0X01可以关联起来一部分数据,ID=0X02可以关联一部分数据,而又知道ID=0X01和ID=0X02是同属一个组,所以就可以实现全部记录的关联了。这里我考虑能否设计一个hash_map类似的容器,比如通过id=0x01,id=0x02作为key可以索引到相同的node,这样后续的rec都可以根据id进入自己的group了。请各位xd帮忙设计一个算法与数据结构吧。
每次查找时,总数据量大约有多少?ID的取值范围有多大?每条记录的长度是否固定、大约是多少?
现在有一个文件,里面有很多Record,每个Record有一个不唯一的ID,ID取值范围是0~655536,Record的长度不固定,无序存放。要做的是先建立一个索引,以便后面任意给出一对ID就能快速地找出这一对ID对应的所有Record(这些Record合在一起作为一个group)。
如果上面的理解没错,还需要知道Record的大约数量及总数据量的多少。
基本没错!只不过不是给出一个ID,而是你自己从这对文件里面自行解析出来每一个ID,然后根据ID把后续的属于一个ID pair的记录组合到一起。record的数量从是百万到上千万都有。总数据量大概上TB的量吧。总结来讲:给你一堆文件TB级大小,上千万记录,每个记录有一个ID标识,ID = 0~65535,根据ID把所有的记录分组GROUP,每一组数据都有开始BEGIN、结束END标识,但是在一定不同组相同的ID不会在同一个时间段内出现,所以处理的时候首先得到begin,到end之间出现的ID都肯定是该group的记录。处理结果:TB文件,几千万记录,最后按照ID被分成几十万个、几百万个group,每个group内有自己的记录rec。需要做的:建立数据结构保存各组rec索引,利用解析到的每个记录的ID结合begin、end起止信息建立索引机制,利用ID作为索引信息定位分组后续的每一个记录数据(ID = IDx),每一组数据有一个ID PAIR标识GROUP
还有,为什么要用一对ID来标识一个group?这一对ID如何确定?不可能把任意两个ID都搞一个group吧?
不好意思,打字乱掉了。是这样的:
一个group数据是由一个ID值对(ID1,ID2)唯一标识的,比如说记录双方设计到两个人,每方一个ID标识,每个group标识begin的那条记录是可以获取到这个ID值对的(ID1,ID2),就好像告诉你以下这两个人是一个组,他们后续各自的所有记录是属于一个group的。由于ID总归会重复使用,但是在同一个时间段内,所有group的ID值对肯定是互不相同的。比如说,开始ID(ID1,ID2)标识GROUP1,但过一段时间这个ID(ID1,ID2)值对可能会被用来标识GROUP100了,当然可能它过一会又被用来标识其他的group了。不知道我有没用描述清楚,谢谢!
如果是这样,那么如何确定一组对话结束?
类似的东西吧。对每一个记录处理时候会首先检查其rec.TYPE,如果REC.TYPE = BEGIN,则说明这个记录包含两个ID(ID1,ID2),这时就获取了GROUP的标识ID PAIR(ID1,ID2),后续的每个记录REC.TYPE = DATA,说明这个记录只有一个ID,要么ID = ID1,要么ID = ID2,直到遇到一个记录REC.TYPE = END,这个记录也包含两个ID,并且为ID PAIR(ID1,ID2),则说明这个GROUP可以个关闭了。所以总结来看:
REC.TYPE = BEGIN, ID = ID pair(ID1,ID2) 开始
REC.TYPE = DATA, ID = ID1 or ID2 GROUP组内数据记录
REC.TYPE = END ID = ID pair(ID1,ID2) 结束谢谢。
也就是楼上所说的整理一哈。
我的意见是按每天记录的ID、时间什么排个序,然后针对有序的数据文件做索引。
当然,有可能我没有确切理解楼主的意图。
呵呵。
目的是把混乱的records整理成groups,便于后续的查找和统计使用。由于数据量太大,所以考虑效率多些。谢谢!
在读写磁盘文件方面,要注意集中读、集中写,就是在读数据的过程中不要执行其它访问磁盘的操作,在写的过程中也不要执行其它访问磁盘的操作,每次连续读或连续写的数据量越多越好,在集中读或集中写的过程中可以对内存中的数据进行处理,但要尽量避免虚拟内存交换。这样可以尽量避免反复的磁盘寻道操作,提高效率。磁盘操作中最费时的就是寻道。另外提一下,很多人以为使用文件映射可以大大提高效率,其实不然,文件映射只是略过了磁盘缓冲和一些中间代码,在进行大量不重复的磁盘读写操作时,其节省的时间是忽略不计的,而且,如果使用不当,反而会大大降低效率,所以不建议使用。
查找group时,可以通过哈希表快速定位。
处理过程中,先将整理好的group保存在内存中,处理一定量的数据后,集中对groups进行一次保存,并更新哈希表。根据系统中物理内存资源的情况,充分利用物理内存,但要留出一些,以免物理内存不足时影响效率。
整理过程中建立一个索引,记录ID对对应的group的位置,以便后续查找。
多谢!您说的非常有道理,这里我的问题就集中在这部分了。我也打算使用hash表进行处理,不过如何使用这里的ID PAIR(ID(n),ID(m))设计HASH_MAP呢?由于只有BEGIN/END record携带有ID PAIR,其他的组内记录只具有ID PAIR中的一个。还请大虾指点。谢谢!
如果这样就更简单了,不用hash table,用一个64K长的指针数组,指向每个ID当前对应的group信息结构。
对,一个时间段内的ID PAIR可以唯一的确定一个通话双方。比如:
REC.TYPE = BEGIN,ID = ID PAIR(ID1,ID2)
REC.TYPE = DATA , ID = ID1 or ID2
REC.TYPE = END ,ID = ID PAIR(ID,ID2)在BEGIN ... END之间,这个ID PAIR不可能被两个通话过程使用的。请指点!
分配一个64K长的指针数组,以ID值作为数组下标,每个元素指向该ID当前对应的group信息结构,整个数组初始化为NULL。
begin的时候分配group结构,将结构指针写入数组(ID1、ID2对应的两个元素)。
end的时候清除数组中对应的两个指针。
typedef struct GROUP_DATA
{
int id1;
int id2;
int name;
int source;
int dest;
} MY_GROUP_DATA,*PMY_GROUP_DATA;
// 声明指针数组
PMY_GROUP_DATA MyGroups[65535];
memset(MyGroups,sizeof(MY_GROUP_DATA),0);
//
while(!BeEnd)
{
GetData();
ParseData();
if(rec.type == BEGIN)
createData();
else if (rec.type == DATA)
appendData();
else if (rec.type == END)
deleteData();
}
//
createNew()
{
PMY_GROUP_DATA pData = new MY_GROUP_DATA pData();
MyGroups[rec.id1] = pData;
MyGroups[rec.id2] = pData;
}
//
appendData()
//
deleteData()
{
MyGroups[rec.id1] = NULL;
MyGroups[rec.id2] = NULL;
}
大致这个思路是么?这么实现和使用hash_map(int,MY_GROUP_DATA pData)比较如何?
memset(MyGroups,sizeof(MY_GROUP_DATA),0);更改为
memset(MyGroups,sizeof(int),0);
这种方法比用hash要快,但浪费储存空间,不过你现在处理的问题只需要sizeof(void*)*0x10000字节,几百KB而已,所以不用在意空间问题。