最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

用位圖排序無重復(fù)數(shù)據(jù)集實(shí)例代碼(C++版)

 更新時(shí)間:2013年11月20日 11:01:16   作者:  
本文講解如何用位圖排序無重復(fù)的數(shù)據(jù)集,我們使用C++實(shí)現(xiàn)一下這個(gè)方法
《Programming Pearls》(編程珠璣下載)第一章講述了如何用位圖排序無重復(fù)的數(shù)據(jù)集,整個(gè)思想很簡潔,今天實(shí)踐了下。

一、主要思想

位圖排序的思想就是在內(nèi)存中申請(qǐng)一塊連續(xù)的空間作為位圖,初始時(shí)將位圖的每一位都置為0,然后依次讀取待排序文件的整數(shù),將整數(shù)所在的位設(shè)置為1,最后掃描位圖,如果某一位為1,則說明這個(gè)數(shù)存在,輸出到已排序文件。比如待排序的數(shù)據(jù)S={3,0,4,1,7,2,5},max(S)=7,我們可以設(shè)置一個(gè)八位的位圖B,將位圖的每一位初始為0,即B=[0,0,0,0,0,0,0,0],對(duì)S中的每一個(gè)整數(shù)d,設(shè)置B[d]=1,即B=[1,1,1,1,1,1,0,1],最后掃描位圖,對(duì)位圖的每一位i,如果B[i]==1,則輸出i到已排序文件,排序后的S={0,1,2,3,4,5,7}。
整個(gè)過程只需要遍歷一遍待排序文件和位圖,時(shí)間復(fù)雜度O(n),需要的輔助空間為(max(S)/8)B。雖然這個(gè)排序算法只能在無重復(fù)的整數(shù)集上運(yùn)行,但對(duì)于有些需求,確實(shí)做到高效實(shí)現(xiàn),比如說給手機(jī)號(hào)碼排序,手機(jī)號(hào)碼11位,第一位始終為1,理論上可以有10^10個(gè)號(hào)碼,但一些號(hào)碼未發(fā)放,即有些號(hào)碼在系統(tǒng)中不存在,假設(shè)系統(tǒng)中有50%的合法號(hào)碼,每個(gè)號(hào)碼用long int表示,這么多號(hào)碼所需要的空間為50%*(10^10)*4B=20GB,不能放在內(nèi)存中進(jìn)行快速排序。一個(gè)可選的方案是分多趟進(jìn)行歸并排序,但需要較長的時(shí)間。我們申請(qǐng)一個(gè)10^10位的位圖,需要的內(nèi)存是10^10/8B=1.25GB,完全可以在當(dāng)代的PC機(jī)上運(yùn)行,在掃描位圖時(shí),假設(shè)某一位i為1,輸出文件時(shí),在前面添加一個(gè)1,例如i=3885201314,輸出為13885201314。

二、算法實(shí)現(xiàn)

 用c語言實(shí)現(xiàn)的話,需要自己封裝位圖操作,這里需要用到三個(gè)操作:設(shè)置位圖的所有位為0(setAllZero);設(shè)定指定的位為1(setOne);查看指定的位是否為1(find);代碼如下:

 

復(fù)制代碼 代碼如下:

 #include <malloc.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>

#define MAX_NUM 16777216//最大的數(shù),也就是需要的位
#define BYTE_NUM (1+MAX_NUM/8)//字節(jié)數(shù)
#define MASK 0x07

void setAllZero(unsigned char *p,long size);
void setOne(unsigned char *p,long loc);
int find(unsigned char *p,long loc);
bool getSorted(unsigned char *bitmap,char *fileName);
bool setBitmap(unsigned char *bitmap,char *fileName);
int bitmapSort();
int main(){
    return bitmapSort();
}
int bitmapSort(){
    unsigned char *bitmap;    //位圖指針
    bitmap = (unsigned char *)malloc(BYTE_NUM*sizeof(unsigned char));
    if(bitmap == NULL){
        printf("Malloc failed\n");
        return -1;
    }   
    setAllZero(bitmap,BYTE_NUM);//將位圖所有位設(shè)置為0
    setBitmap(bitmap,"phoneNumber.txt");//掃描待排文件,將位圖對(duì)應(yīng)位設(shè)置為1
    getSorted(bitmap,"bitmapSort.txt");    //掃描位圖,將位圖為1的位號(hào)輸出到文件
    free(bitmap);//釋放位圖
    return 0;
}
/***********設(shè)置待排序數(shù)據(jù)的位圖**************/
bool setBitmap(unsigned char *bitmap,char *fileName){
    FILE *readFp;
    printf("Setting bitmap...\n");
    readFp = fopen(fileName,"r");
    if(readFp == NULL)
        return false;   
    long phoneNum=0;
    while(fscanf(readFp,"%ld\n",&phoneNum) != EOF){
        setOne(bitmap,phoneNum);//將    phoneNum位設(shè)置為1   
    }
    fclose(readFp);
    return true;
}
/*****順序遍歷位圖輸出記錄,從而實(shí)現(xiàn)排序****************/
bool getSorted(unsigned char *bitmap,char *fileName){
    printf("Search bitmap...\n");
    FILE *writeFp;
    writeFp = fopen(fileName,"w");
    if(writeFp == NULL)
        return false;
    long phoneNum=0;
    for(phoneNum = 0; phoneNum < MAX_NUM; phoneNum += 1){
        if(find(bitmap,phoneNum)){
            fprintf(writeFp,"%ld\n",phoneNum);
        }
    }
    fclose(writeFp);
    return true;
}
/******先將位圖清零********/
void setAllZero(unsigned char *bitmap,long size){
    for(long i=0;i<size;i++)
        *(bitmap+i) &= 0;
}
/*************************************************
將指定的位置為1
(loc>>3)相當(dāng)于整除2^3=8,即定位到字節(jié)數(shù),MASK=0x07,loc&MASK相當(dāng)于loc%8
***************************************************/
void setOne(unsigned char *bitmap,long loc){
    *(bitmap+(loc>>3)) |= (1<<(loc&MASK));//
}

/******查找指定的位是否為1********/
int find(unsigned char *bitmap,long loc){
    return ((*(bitmap+(loc>>3))) & (1<<(loc&MASK))) == (1<<(loc&MASK));   
}
 

 C++的STL中有一個(gè)數(shù)據(jù)結(jié)構(gòu)bitset,操作位圖很方便。

 

復(fù)制代碼 代碼如下:

 #include <bitset>
#define MAX_NUM 4000000//最多的數(shù),即需要的位數(shù)
using namespace std;

int main(){
    FILE *readFp,*writeFp;
    readFp = fopen("phoneNumber1.txt","r");       
    writeFp = fopen("bitsetSorted.txt","w");   
    bitset<MAX_NUM> bitmap;
    for(long i=0;i<MAX_NUM;i++){//先將位圖初試化為0
        bitmap.set(i,0);
    }
    printf("Begin set bitmap...\n");
    long number = 0;
    while(fscanf(readFp,"%ld\n",&number) != EOF){
        bitmap.set(number,1);//將number所在位設(shè)置為1       
    }
    printf("Begin search bitmap...\n");
    for(long i=0;i<MAX_NUM;i++){
        if(bitmap[i] == 1)//將位1的位輸出到已排序文件
            fprintf(writeFp,"%ld\n",number);
    }
    fclose(writeFp);
    fclose(readFp);
}
 

排序算法很快就寫好了,就開始生成測(cè)試數(shù)據(jù),想生成0—2^31的亂序數(shù)據(jù)集還真不容易,首先要保證不重復(fù),第二要丟掉40%的數(shù)(無效手機(jī)號(hào)碼),第三要盡可能的亂序,搗了很久,最終還是找到了實(shí)現(xiàn)辦法,生成了12GB的數(shù)據(jù)集,關(guān)于生成這個(gè)數(shù)據(jù)集的辦法,歡迎一起討論,我將會(huì)在下一篇中總結(jié)一下我的方法。
完整的代碼可以參考github。

相關(guān)文章

  • C語言單值二叉樹真題講解

    C語言單值二叉樹真題講解

    單值二叉樹你可能之前沒見過,如果二叉樹每個(gè)節(jié)點(diǎn)都具有相同的值,那么該二叉樹就是單值二叉樹,讓我們通過一個(gè)真題來深刻了解它吧
    2022-04-04
  • C語言實(shí)現(xiàn)排雷游戲(多文件)

    C語言實(shí)現(xiàn)排雷游戲(多文件)

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)排雷游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • C/C++實(shí)現(xiàn)樹操作的實(shí)例代碼

    C/C++實(shí)現(xiàn)樹操作的實(shí)例代碼

    這篇文章主要介紹了C/C++實(shí)現(xiàn)樹操作的實(shí)例代碼,代碼簡單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-02-02
  • C++中宏的使用問題詳解

    C++中宏的使用問題詳解

    宏替換是C/C++系列語言的技術(shù)特色,C/C++語言提供了強(qiáng)大的宏替換功能,源代碼在進(jìn)入編譯器之前,要先經(jīng)過一個(gè)稱為“預(yù)處理器”的模塊,這個(gè)模塊將宏根據(jù)編譯參數(shù)和實(shí)際編碼進(jìn)行展開,展開后的代碼才正式進(jìn)入編譯器,進(jìn)行詞法分析、語法分析等等。
    2016-05-05
  • C++類靜態(tài)成員與類靜態(tài)成員函數(shù)詳解

    C++類靜態(tài)成員與類靜態(tài)成員函數(shù)詳解

    靜態(tài)成員不可在類體內(nèi)進(jìn)行賦值,因?yàn)樗潜凰性擃惖膶?duì)象所共享的。你在一個(gè)對(duì)象里給它賦值,其他對(duì)象里的該成員也會(huì)發(fā)生變化。為了避免混亂,所以不可在類體內(nèi)進(jìn)行賦值
    2013-09-09
  • C語言入門篇--關(guān)鍵字static詳解

    C語言入門篇--關(guān)鍵字static詳解

    本篇文章是C語言系列基礎(chǔ)篇,C語言中,static是用來修飾變量和函數(shù):1.修飾局部變量–>靜態(tài)局部變量2.修飾全局變量–>靜態(tài)全局變量3.修飾函數(shù)–>靜態(tài)函數(shù)
    2021-08-08
  • C++類型兼容規(guī)則詳情

    C++類型兼容規(guī)則詳情

    這篇文章主要介紹了C++類型兼容規(guī)則詳情,共有繼承時(shí),任何需要父類對(duì)象的地方,都能使用子類對(duì)象“替代”,這就是類型兼容規(guī)則,下面一起來了解文章相關(guān)內(nèi)容吧
    2022-03-03
  • 一起來學(xué)習(xí)C語言的輸入和輸出

    一起來學(xué)習(xí)C語言的輸入和輸出

    這篇文章主要為大家詳細(xì)介紹了C語言的輸入和輸出,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • C++學(xué)生信息管理系統(tǒng)

    C++學(xué)生信息管理系統(tǒng)

    這篇文章主要為大家想詳細(xì)介紹了C++學(xué)生信息管理系統(tǒng)的實(shí)現(xiàn)代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-06-06
  • C++超詳細(xì)講解auto與nullptr的使用

    C++超詳細(xì)講解auto與nullptr的使用

    C++11提供了nullptr用來取代0或者NULL。在C++11之前,使用NULL為空指針賦初值,但NULL其實(shí)就是0,這時(shí)會(huì)把NULL當(dāng)成0來用;在C++11中,我們?cè)诼暶饕粋€(gè)變量或?qū)ο?,指定它的類型時(shí),可以不使用變量本身的類型而使用auto替代
    2022-05-05

最新評(píng)論

阳山县| 普洱| 林甸县| 长武县| 兴化市| 淮滨县| 乐山市| 嘉黎县| 葵青区| 南宫市| 丰宁| 扎鲁特旗| 呼伦贝尔市| 东安县| 汉川市| 漯河市| 黄浦区| 中西区| 阳朔县| 清丰县| 双城市| 玉田县| 上思县| 延寿县| 酒泉市| 韶山市| 深泽县| 江城| 恩平市| 庄河市| 陕西省| 红安县| 黔东| 湘乡市| 皋兰县| 江陵县| 康马县| 咸丰县| 东乡族自治县| 祁门县| 苍溪县|