现在的位置: 首页 > 综合 > 正文

求大数据量数组中不重复元素的个数

2013年09月05日 ⁄ 综合 ⁄ 共 3608字 ⁄ 字号 评论关闭
有2.5亿个整数(这2.5亿个整数存储在一个数组里面,至于数组是放在外存还是内存,没有进一步具体说明);
要求找出这2.5亿个数字里面,不重复的数字的个数(那些只出现一次的数字的数目)
另外,可用的内存限定为600M;
要求算法尽量高效,最优;

1. caoxic的算法
BYTE    marks[2^29];//512M   // BYTE marks[2^32/8]; //用这个就更清楚了,标志所有整数(2^32)出现的可能
BYTE    repmarks[2^25];//32M 32M*8>2.5亿  //标志2.5亿个数字数组里面的数字是否重复过
const BYTE bitmarks[8]={1,2,4,8,16,32,64,128};
DWORD    CalcDifNum(DWORD
*pBuf,DWORD bufcount)
{
    DWORD dw ;
    DWORD count
= 0 ;// 不重复的数字(包括出现多次的数字,只算一个)的个数,例子:1 2 2 3 5 3 4 算5个
    DWORD count2 = 0 ;//重复出现的数字的个数,例子:1 2 2 3 5 3 4 算2个
    memset(marks,0,sizeof(marks));
    memset(repmarks,
0,sizeof(repmarks));
    ASSERT(
sizeof(repmarks)*8>=bufcount);//断言repmarks数组够用
    for(dw=0;dw<bufcount;dw++)
    {
       
if(marks[pBuf[dw]>>3]&bitmarks[pBuf[dw]&7])
        {
            repmarks[dw
>>3] |= bitmarks[dw&7];//标志pBuf[dw]这个数字出现重复
        }
       
else
        {
            count
++;
            marks[pBuf[dw]
>>3] |= bitmarks[pBuf[dw]&7];//标志pBuf[dw]这个数字出现
        }
    }

    memset(marks,0,sizeof(marks));
   
for(dw=0;dw<bufcount;dw++)
    {
       
if(repmarks[dw>>3] & bitmarks[dw&7])//
        {
           
if(marks[pBuf[dw]>>3]&bitmarks[pBuf[dw]&7])
            {
            }
           
else
            {
                count2
++; //重复的数字的数量
                marks[pBuf[dw]
>>3] |= bitmarks[pBuf[dw]&7];
            }
        }
    }
   
return count-count2;
}

2. 改一下,应该也可以:

BYTE    marks[2^29];//512M   // BYTE marks[2^32/8]; //用这个就更清楚了,标志所有整数(2^32)出现的可能
BYTE    repmarks[2^25];//32M 32M*8>2.5亿  //标志2.5亿个数字数组里面的数字是否重复过
const BYTE bitmarks[8]={1,2,4,8,16,32,64,128};
DWORD    CalcDifNum(DWORD
*pBuf,DWORD bufcount)
{
    DWORD dw ;
    DWORD count
= 0 ;// 不重复的数字(包括出现多次的数字,只算一个)的个数,例子:1 2 2 3 5 3 4 算5个
    DWORD count2 = 0 ;//只出现一次数字的个数,例子:1 2 2 3 5 3 4 算3个
    memset(marks,0,sizeof(marks));
    memset(repmarks,
0,sizeof(repmarks));
    ASSERT(
sizeof(repmarks)*8>=bufcount);//断言repmarks数组够用
    for(dw=0;dw<bufcount;dw++)
    {
       
if(marks[pBuf[dw]>>3]&bitmarks[pBuf[dw]&7])
        {
            repmarks[dw
>>3] |= bitmarks[dw&7];//标志pBuf[dw]这个数字出现重复
        }
       
else
        {
            count
++;
            marks[pBuf[dw]
>>3] |= bitmarks[pBuf[dw]&7];//标志pBuf[dw]这个数字出现
        }
    }

    for(dw=0;dw<bufcount;dw++)
    {
       
if(!(repmarks[dw>>3] & bitmarks[dw&7]))//非重复的位置
        {
                count2 ++; //只出现一次的数字的数量
        }
    }
   
return count2;
}

3. 把数组里面的数字分两类,正数负数,marks数组分成两部分标志,1.该数已经标志[0 -->  2^28-1] 2.标识该数已经重复[2^28 -->2^29-1]。

BYTE    marks[2^29];//512M   // BYTE marks[2^32/8]; //用这个就更清楚了,标志所有整数(2^32)出现的可能
const BYTE bitmarks[8]={1,2,4,8,16,32,64,128};
DWORD    CalcDifNum(DWORD *pBuf,DWORD bufcount)
{
    DWORD dw ;
    DWORD count = 0 ;// 不重复的数字(包括出现多次的数字,只算一个)的个数,例子:1 2 2 3 5 3 4 算5个
    DWORD count2 = 0 ;//重复出现的数字的个数,例子:1 2 2 3 5 3 4 算2个
    memset(marks,0,sizeof(marks));
    for(dw=0;dw<bufcount;dw++)
    {
        if(pBuf[dw]>=0)
        {
         if(marks[pBuf[dw]>>3]&bitmarks[pBuf[dw]&7])
         {
            if(marks[2^28+pBuf[dw]>>3]&bitmarks[pBuf[dw]&7])
            {
            
            }else
            {
               marks[2^28+pBuf[dw]>>3] |= bitmarks[dw&7];//标志pBuf[dw]这个数字出现重复
               count2 ++;
            }
         }
         else
         {
             count ++;
             marks[pBuf[dw]>>3] |= bitmarks[pBuf[dw]&7];//标志pBuf[dw]这个数字出现
         }
        }
    }
   
    memset(marks,0,sizeof(marks));
    for(dw=0;dw<bufcount;dw++)
    {
        if(pBuf[dw]<0)
        {
         pBuf[dw] = -pBuf[dw];
         if(marks[pBuf[dw]>>3]&bitmarks[pBuf[dw]&7])
         {
            if(marks[2^28+pBuf[dw]>>3]&bitmarks[pBuf[dw]&7])
            {
            
            }else
            {
               marks[2^28+pBuf[dw]>>3] |= bitmarks[dw&7];//标志pBuf[dw]这个数字出现重复
               count2 ++;
            }
         }
         else
         {
             count ++;
             marks[pBuf[dw]>>3] |= bitmarks[pBuf[dw]&7];//标志pBuf[dw]这个数字出现
         }
        }
    }
   
    return count-count2;
}
 

抱歉!评论已关闭.