合并数十万个vector的高效方法?

chenjuan815 2008-04-15 10:12:59
我用了个最最笨的压缩方法,在P4,3.0G,512M内存的机器上运行了一天,没有出结果,然后跟踪估计了下时间,大约需要9天时间才能完成数据压缩,太慢了!不知道各位有没有好的压缩方法?

本人有近30万个vector<int>(每个vector<int>中的值为0~179),如:

vector<vector<int>> a;

a[0]={0,3,179}

a[1]={}//该vector为空

a[2]={2,6,8,56,119,36}

a[3]={0,3,179}

a[4]={1,2,3,4,5,6,7,8,9,10...,179}// “满”vector<int>,表示从0到179间的数均在该vector中

....

a[310000]=...

先要对上述31万个vector<int>进行压缩,压缩原则为
1.空vector<int>删除,如a[1]
2.“满”vector<int>删除,如a[4]
3.相同vector<int>删除其中一个,如a[0]和a[3]相同,则删除其中任意一个
4.互补vector<int>删除其中一个,互补的意思是两vector<int>不相交且其并集为“满”vector<int>
...全文
2698 92 打赏 收藏 转发到动态 举报
写回复
用AI写文章
92 条回复
切换为时间正序
请发表友善的回复…
发表回复
crushor 2010-01-16
  • 打赏
  • 举报
回复
从头想,你为什么会有30万个vector?
ljm1212 2010-01-16
  • 打赏
  • 举报
回复
jf每天回帖即可获得10分可用分!小技巧:教您如何更快获得可用分
ljm1212 2010-01-16
  • 打赏
  • 举报
回复
汗。。怎么点了古代的了。。闪。。。
ljm1212 2010-01-16
  • 打赏
  • 举报
回复
邻接表。。。邻接表的邻接表。。。。
用.size相同的在同一链。。
空的满的去掉。。互补的到size对应的链去找(有相同元素的先排除)。。
相同的同条链上找。。。

STL刚接触不久。。。位不熟。。纯属看热闹。。顺便mark。。。LZ要9天估计是用了最原始的方法。。。全部完全搜索。。。。那就挺吓人了。。。。
foxpeter 2010-01-16
  • 打赏
  • 举报
回复
Mark!
yunyun050924 2010-01-16
  • 打赏
  • 举报
回复
好麻烦,具体到数据结构和算法了,麻烦
pengzhixi 2010-01-16
  • 打赏
  • 举报
回复
标记
kingstarer 2010-01-16
  • 打赏
  • 举报
回复
排一下序 1 2 3都能解决(比较大小原则是先比较个数,再比较vector里面的数值)

主要问题在4,要想一个好办法测试两个是否互补

很明显,互补的两个vector满足元素之合为180
并且
由于
a ^ a = 0;
所以可以先算出
0 ^ 1 ^ 2 ^ ... ^179的值
再处出两个vector所有元素异或之合

两个值做比较 相等则说明两个vector互补
fan_yu_feng 2008-05-06
  • 打赏
  • 举报
回复
我不是最擅长Vector<int>,这种使用方法
不过,我觉得可以对每条数据做几个标志;
struct strFlag{
bool del;
int num;
dword FixCheck1;
dword FixCheck2;
};

del 是删除标志位,删除工作最后做
num 是包含元素个数
FixCheck1 是本单元的校验码
FixCheck2 是本单元互补单元的校验码

首先全部生成这些参数,
当num = 0 和num = 180 时 设置del标志
当num相同,FixCheck1相同,del标志没有设置 则设置
当num相加=180,FixCheck1 = FixCheck2,del标志没有设置 则设置

最后再删除所有具有del标志的单元

这样,尽管每个单元都计算了两个校验码,但是每次都不需要对内部数据进行一个一个的比较,应该会节约很多时间
shshsh_0510 2008-05-06
  • 打赏
  • 举报
回复
1、“平均大小为90是咋求出来的呢”
〉〉 平均概率下,vector <int> 的长度从 0到180的概率是相等的,那么平均大小就不言而喻了
〉〉〉〉我的假设前提和你不一样,算出的概率就当然不一样了。
2,3,4
〉〉假设前提不一样,其他当然没啥可讨论的了

不去细分析你的算法了。
还是要多学学数学,才能做到无懈可击。
〉〉太难了,学不会呀。所以有懈可击也没法子了。

loveyouwxw 2008-05-06
  • 打赏
  • 举报
回复
以我的理解 , 大家都忽略了一个问题,

30万 只是2^180 中很少的一个部分,

也就是说, 这个数组有很大的冗余 ,

把这个空余去除, 就可以有很多的改进,

shshsh_0510 2008-05-05
  • 打赏
  • 举报
回复
[Quote=引用 78 楼 Dancing_Sea 的回复:]
这个问题实际最大的难点就是排除补集

shshsh_0510说的hash方法没有考虑 由vector <int>到一个key的时间消耗,也没有考虑到补集问题带来的时间消耗

vector <int> 的平均大小为90。。。
[/Quote]

咋看出来的俺就没考虑呢?没见俺乘了2么。
的平均大小为90是咋求出来的呢?我是在某种假设下,才会求平均大小,你的前提假设和我一样么?如果一样,那么你错了;如果不一样,那么。。。到底是啥意思呢

所以望同志们少学些数学,弄不好就把自己给整晕了 :)
yuanchuang 2008-05-05
  • 打赏
  • 举报
回复
就10w条int记录,又不耗什么内存。
9天?如果光合并而不做其他事的话,取出每个放到数组里,100毫秒都不要,呵呵。
Dancing_Sea 2008-05-05
  • 打赏
  • 举报
回复
[Quote=引用 79 楼 shshsh_0510 的回复:]
引用 78 楼 Dancing_Sea 的回复:
这个问题实际最大的难点就是排除补集

shshsh_0510说的hash方法没有考虑 由vector <int>到一个key的时间消耗,也没有考虑到补集问题带来的时间消耗

vector <int> 的平均大小为90。。。


咋看出来的俺就没考虑呢?没见俺乘了2么。
的平均大小为90是咋求出来的呢?我是在某种假设下,才会求平均大小,你的前提假设和我一样么?如果一样,那么你错了;如果不一样,那么。。。到底是啥意…
[/Quote]

1、“平均大小为90是咋求出来的呢” 〉〉 平均概率下,vector<int> 的长度从 0到180的概率是相等的,那么平均大小就不言而喻了
2、“咋看出来的俺就没考虑呢?没见俺乘了2么” >> 这个不知道指的是什么?如果指的是排除补集,那么很想知道你如何排除补集,如果没有一个恰当的转换,在本案例下,从hash key是不可能直接排除掉补给的;如果指的是由vector<int> 到hash key的时间消耗,根据你的算法,碰撞的概率不是8%,计算公式超级复杂。先给你解释一下什么是碰撞,两个不同的value,对应到同一个hash key,才是碰撞。而相同的value对一个hash key不是碰撞,你再看看你的公式300000/2 * C(90-32,180)/2^180 =0.08 --- 这部分似乎求的是发生相同的value的概率(也许不是,确实没有看明白)。由于碰撞的计算公式特别复杂,涉及到连续概率分布,这里给你一个近似的计算方法:如果你的hash key算法对的话,长度小于等于32时,不存在碰撞,但当长度大于32时,就会碰撞。如果有补集转换(300000*180的时间消耗),平均概率下长度小于32的个数为 300000 * 32 / 90, 长度大于32的为300000 * (90-32) / 90 ,那么碰撞概率是 (90-32) / 32。如果没有补集转换,碰撞概率为(180-32)/ 32。
3、不过由于hash key计算的不对 —— 这里的vector<int> 里面的元素是无序的,可能元素完全一致,但是前32位不一致,根据你的描述,相同的两个集合(vector<int>)极大的可能得到两个完全不一致的hash key。如果转变为有序,要么排序,要么采用我所有的补集转换代码,排序、补集一次性获得。在面对集合的时候,如果使用hash 表,最好要能够将所有的元素加入考虑,否则会出现较多漏洞。

4、“遍历300000vector进行判断时,有8%的可能需要重新查一下原vector,同样还有8%的可能不能确定是否互补” 〉〉 不知道这位老大有什么高招通过hash key来判断是否互补,而且互补的概率是8%(可能本人表述有误)

不去细分析你的算法了。
还是要多学学数学,才能做到无懈可击。


MagiSu 2008-05-05
  • 打赏
  • 举报
回复
看到楼上的,我就想起来编程珠玑上的确有类似的技巧。
Dancing_Sea 2008-05-03
  • 打赏
  • 举报
回复
这个问题实际最大的难点就是排除补集

shshsh_0510说的hash方法没有考虑 由vector<int>到一个key的时间消耗,也没有考虑到补集问题带来的时间消耗

vector<int> 的平均大小为90。。。
newerC 2008-04-26
  • 打赏
  • 举报
回复
[Quote=引用 74 楼 archy 的回复:]
引用 45 楼 x86 的回复:
前面有人说了用bits,不过有更好的办法,那就是直接用整形。比如在64位系统下,一个long是64位,那么三个long就可以包含0到179这样的范围,其中每一位表示某个数是否在vector中。如果低180位都是1,那么这个vector是满的。

首先,把vector转换成三个long的一个结构。比如:
typedef struct tagLLL{
long long f1;
long long f2;
long long f3;
}LLL;
从f1到f3,分别表示一…
[/Quote]
根据
4.互补vector <int>删除其中一个,互补的意思是两vector <int>不相交且其并集为“满”vector <int>
考虑一下这些种情况
L1 : ..... 0 0 1 0
L2 : ..... 1 0 0 0
或者
L1 : ..... 1 1 1 1 (全满)
L2 : ..... 1 0 0 0

这种情况明显不是是互补
条件应该是 ((L1 & L2) == 0) && ((L1 | L2)==M)

ll_2008 2008-04-25
  • 打赏
  • 举报
回复
好多高手
mhzjy 2008-04-24
  • 打赏
  • 举报
回复
我想问1下你们想出1种解决方法,并写上来需要多少时间?
archy 2008-04-22
  • 打赏
  • 举报
回复
[Quote=引用 45 楼 x86 的回复:]
前面有人说了用bits,不过有更好的办法,那就是直接用整形。比如在64位系统下,一个long是64位,那么三个long就可以包含0到179这样的范围,其中每一位表示某个数是否在vector中。如果低180位都是1,那么这个vector是满的。

首先,把vector转换成三个long的一个结构。比如:
typedef struct tagLLL{
long long f1;
long long f2;
long long f3;
}LLL;
从f1到f3,分别表示一个“大”整数的第0位到第179位,多…
[/Quote]

"如果互补,那么L1 & L2==M (二者按位与,低180位全为1) "
应该是 "如果互补,那么L1 & L2==0“ 吧 ??? 或者 L1 | L2==M
加载更多回复(72)

64,696

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧