1. 程式人生 > >對大數據量進行排序--位圖法

對大數據量進行排序--位圖法

思想 重復數 不變 nbsp 要求 void 最大 sig 元素

題目:對2G的數據量進行排序,這是基本要求。

數據:1、每個數據不大於8億;2、數據類型位int;3、每個數據最多重復一次。

內存:最多用200M的內存進行操作。

我聽過很多種類似問題的解法,有的是內存多次利用,有的用到了外存,我覺得這兩種做法都不是比較好的思想,太慢。由於這個題目看起來沒有對效率進行約束,所以這兩種方法也是對的,但是我這次提出一個比較好的算法來解答此題,如果有更好的做法請趕快跟帖留言,共同討論。希望大神們的加入。。。。。

思想:把200M的內存平分,可以開兩個數組,一個數組arr存放一遍不重復的所有數據,另一個數組arr_2只存放重復的數據。存放方法是對數組中的每個數據的位進行操作。比如:18這個數,18/32=0,18就會對應arr[0]這個數組中的某一位,而每一個數組元素都是32位組成,18%32=18,也就是說arr[0]那個數的第18位對應18這個數。同樣道理再來一個數:43 43/32=1,43%32=11,也就是說43對應的是arr[1]中的第11位。只要找到了對應位置,把該位置1,其余位置不變(默認為0),遍歷一次數據,就會把內存中的對應位置1.如果遇到重復數據,此時就會用到第二個數組了,若本次查詢該位已經為1,那麽就要把arr_2這個數組中的對應位置1。在輸出的時候就要同步遍歷兩個數組。

輸出:就是一個反向還原過程,遍歷內存中的每一位,該位對應的有數組下標和所處位,進行一次乘、和運算就能還原回來數據,並依次寫入文件或者打印到屏幕上。

/*
如何對某一位置0或者置1?
#define setbit(x,y) x|=(1<<y) //將X的第Y位置1
#define clrbit(x,y) x&=!(1<<y) //將X的第Y位清0
*/

#define BITSPERWORD 32 //數組每個元素32位
#define SHIFT 5
#define MASK 0x1F
#define MAXNUM 10000         //最大整數
const int num = 6000;        //整數個數
int length = 1 + MAXNUM / BITSPERWORD; //最大數值除以32得到數組大小
unsigned int *a = new unsigned int[length];

//i>>SHIFT表示i在數組中的下標 等價於i/32;1<<(i & MASK))等價於i%32,表示第幾個bit
//i & MASK == i % 32 == 余數 == i & (32 - 1) == i & MASK 就是對32做MOD求余數 
void set(int i)  {    a[i>>SHIFT] |=  (1<<(i & MASK)); }  //將某bit置1
void clr(int i)  {    a[i>>SHIFT] &= ~(1<<(i & MASK)); }  //將某bit置0

//若第0 bit為1,返回1;若第3 bit為1,則返回8;若第10 bit為1,則返回1024
int  test(int i) { return a[i>>SHIFT] &   (1<<(i & MASK)); }  

int main(void)
{   
    for (int i=0;i!=length;++i)     
        a[i]=0;             //每bit都初始化為0
    srand(time(0));
    int i = 0;
    while(i != num)        //生成num個大小不超過MAXNUM的整數
    {
        int p = rand() % MAXNUM;
        if (!test(p))
        {
            set(p);
            ++i;
        }
    }

    for (i=0; i<MAXNUM; ++i)       //按升序打印出這些整數
    {
        if(test(i))
            cout<<i<<endl;
    }

    return 0;
}

  

對大數據量進行排序--位圖法