• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C语言 > 用位图排序无重复数据集实例代码(C++版)

用位图排序无重复数据集实例代码(C++版)

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了位图数据结构,位图数据,位图数据流,无效的位图原始数据,都市美好家园摆位图等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com
《Programming Pearls》(编程珠玑下载)第一章讲述了如何用位图排序无重复的数据集,整个思想很简洁,今天实践了下。

一、主要思想

位图排序的思想就是在内存中申请一块连续的空间作为位图,初始时将位图的每一位都置为0,然后依次读取待排序文件的整数,将整数所在的位设置为1,最后扫描位图,如果某一位为1,则说明这个数存在,输出到已排序文件。比如待排序的数据S={3,0,4,1,7,2,5},max(S)=7,我们可以设置一个八位的位图B,将位图的每一位初始为0,即B=[0,0,0,0,0,0,0,0],对S中的每一个整数d,设置B[d]=1,即B=[1,1,1,1,1,1,0,1],最后扫描位图,对位图的每一位i,如果B[i]==1,则输出i到已排序文件,排序后的S={0,1,2,3,4,5,7}。
整个过程只需要遍历一遍待排序文件和位图,时间复杂度O(n),需要的辅助空间为(max(S)/8)B。虽然这个排序算法只能在无重复的整数集上运行,但对于有些需求,确实做到高效实现,比如说给手机号码排序,手机号码11位,第一位始终为1,理论上可以有10^10个号码,但一些号码未发放,即有些号码在系统中不存在,假设系统中有50%的合法号码,每个号码用long int表示,这么多号码所需要的空间为50%*(10^10)*4B=20GB,不能放在内存中进行快速排序。一个可选的方案是分多趟进行归并排序,但需要较长的时间。我们申请一个10^10位的位图,需要的内存是10^10/8B=1.25GB,完全可以在当代的PC机上运行,在扫描位图时,假设某一位i为1,输出文件时,在前面添加一个1,例如i=3885201314,输出为13885201314。

二、算法实现

 用c语言实现的话,需要自己封装位图操作,这里需要用到三个操作:设置位图的所有位为0(setAllZero);设定指定的位为1(setOne);查看指定的位是否为1(find);代码如下:

 

#define MAX_NUM 16777216//最大的数,也就是需要的位
#define BYTE_NUM (1+MAX_NUM/8)//字节数
#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);//将位图所有位设置为0
    setBitmap(bitmap,"phoneNumber.txt");//扫描待排文件,将位图对应位设置为1
    getSorted(bitmap,"bitmapSort.txt");    //扫描位图,将位图为1的位号输出到文件
    free(bitmap);//释放位图
    return 0;
}
/***********设置待排序数据的位图**************/
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位设置为1   
    }
    fclose(readFp);
    return true;
}
/*****顺序遍历位图输出记录,从而实现排序****************/
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)相当于整除2^3=8,即定位到字节数,MASK=0x07,loc&MASK相当于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));   
}
 </div>

 C++的STL中有一个数据结构bitset,操作位图很方便。

 

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所在位设置为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);
}
 </div>

排序算法很快就写好了,就开始生成测试数据,想生成0—2^31的乱序数据集还真不容易,首先要保证不重复,第二要丢掉40%的数(无效手机号码),第三要尽可能的乱序,捣了很久,最终还是找到了实现办法,生成了12GB的数据集,关于生成这个数据集的办法,欢迎一起讨论,我将会在下一篇中总结一下我的方法。
完整的代码可以参考github。

</div>
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 数据结构之位图(bitmap)详解
  • 用位图排序无重复数据集实例代码(C++版)

相关文章

  • 2017-05-28浅析C++中结构体的定义、初始化和引用
  • 2017-05-28浅析C++字节对齐容易被忽略的两个问题
  • 2017-05-28C++实现调用系统时间简单示例
  • 2017-05-28C++流程控制中用于跳转的return和goto语句学习教程
  • 2017-05-28VC++ 获取系统时间的方法汇总
  • 2017-05-28C++中将string类型转化为int类型
  • 2017-05-28深入理解Java事务的原理与应用
  • 2017-05-28浅析结束程序函数exit, _exit,atexit的区别
  • 2017-05-28构造函数定义为private或者protected的好处
  • 2017-05-28C语言怎么获得进程的PE文件信息

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 详解C++的模板中typename关键字的用法
    • C语言的fork函数在Linux中的进程操作及相关面试题讲解
    • C#将Unicode编码转换为汉字字符串的简单方法
    • C语言自动生成enum值和名字映射代码
    • C++编程中用put输出单个字符和cin输入流的用法
    • linux根据pid获取进程名和获取进程pid(c语言获取pid)
    • c++中的消息框messagebox()详细介绍及使用方法
    • C++ 11实现检查是否存在特定的成员函数
    • 通俗地理解什么是编程语言
    • HDOJ 1443 约瑟夫环的最新应用分析详解

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有