C++实现位图排序实例

 更新时间:2014年08月14日 09:45:59   投稿:shichen2014  
这篇文章主要介绍了C++实现位图排序,是比较重要的排序算法,需要的朋友可以参考下

在《编程珠玑》一书里提到了一种算法导论里没有提到过的位图排序方法,这种排序方法是通过牺牲空间效率来追求时间效率(线性时间)以达到时间-空间折中与双赢的目的。本文以实例形式简单讲一下位图排序思想。

一、问题描述

     1.输入:一个至多包含1千万个非负整数的文件

     2.特征:①每个数都是小于10000000的非负整数;②没有重复的数字;③数据之间不存在关联关系。

     3.约束:①最多1MB的内存空间可用;②磁盘空间充足;③运行时间最多几分钟,最好是线性时间。
    
     4.输出:按升序排列的整数序列。

二、位图排序思想

由于待排序的数据记录较多,我们单纯地使用常见的排序方法时间效率较低,运行时间会很长。而且内存空间有限(限制为1MB左右),所以我们不能同时把所有整数读入内存(如果每个整数使用7个字节来存储,那么1MB内存空间只能存大约143000个数字)。当然我们可以多次读取输入文件,多次排序,但是更好的方案是使用位图排序,可以使用有限的1MB内存空间并只进行一趟排序。

1.根据待排序集合中最大的数,开辟一个位数组,用来表示待排序集合中的整数;

2.待排序集合中的数字在位数组中的对应位置置1,其他的置0;

例如,待排序集合{1,2,3,5,8,13}可以表示为:0-1-1-1-0-1-0-0-1-0-0-0-0-1

这样排序过程自然可以分为三步:

第一步:将所有的位都置为0;

第二步:通过读入文件中的每个整数,将每个对应的位都置为1;

第三步:检验每一位,如果该位为1,输出对应的整数。

注意:位图排序是使用一个二进制位而不是一个整数来表示0或1,这样可以大大地减少所需要的内存空间。使用位图排序的前提是要知道待排序序列中的最大数。位图排序的缺点是有些数没有出现过,仍要为其保留一个位。故位图排序比较适合关键字密集的序列,例如一个城市的电话号码。

伪代码如下:

/*Phase 1: initialize set to empty*/ 
  for i = [0, n) 
    bit[i] = 0 
/*Phase 2: insert present elements into the set*/ 
  for each i in the input file 
    bit[i] = 1 
/*Phase 3: write sorted output*/ 
  for i = [0, n) 
    if bit[i] == 1 
      write i on the output file 

性能:时间复杂度可达O(n),1MB包含8*1024*1024个位,所需内存10000000/(8*1024*1024)=1.20MB,如果不是严格限制的话可以看做基本符合要求。

三、位图排序实现

位图排序时,我们需要考虑:给出一个数,如何找到其对应位图的位置,方法就是首先找到该数对应的字节,然后在找到该数对应的位。例如:

unsigned char bitmap[2]; 
/* 可以表示16个数,即0~15 */ 

一个字节有八位,5表示第0个字节的第5位上;14表示第1个字节的第6个位上。

在这里为了简化位处理,我们使用C++标准库的bitset容器。bitset是C++提供的一种位集合的数据结构,它让我们可以像使用数组一样使用位,可以访问指定下标的bit位。和其他容器一样,bitset也是一个模板类。具体的bitset方法可以查看std::bitset reference。

下面我们使用bitset容器进行位图排序:

/************************************************************************* 
  > File Name: BitSort.cpp 
  > Author: SongLee 
 ************************************************************************/ 
#include<bitset> 
#include<iostream> 
using namespace std; 
 
#define MAX 20 
 
int main() 
{ 
  int arr[10] = {5,1,2,13,7,10,0,20,16,9}; 
 
  bitset<MAX+1> bit; 
   
  /* 将对应位置置1 */ 
  for(int i=0; i<10; ++i) 
  { 
    bit.set(arr[i]); 
    /* bit.set(n)表示将第n位置1 */ 
  } 
 
  /* 输出排序结果 */ 
  for(int i=0; i<MAX+1; ++i) 
  { 
    /* bit.test(n)判断第n位是否为1 */ 
    if(bit.test(i)) 
    { 
      cout << i << " "; 
    } 
  } 
  cout << endl; 
} 

输出结果:0 1 2 5 7 9 10 13 16 20

相关文章

  • C++ OpenCV实现物体尺寸测量示例详解

    C++ OpenCV实现物体尺寸测量示例详解

    本文主要介绍了利用OpenCV对物体的尺寸进行测量,即先定位到待测物体的位置,然后测量物体的宽高。感兴趣的同学可以跟随小编一起学习学习
    2022-01-01
  • C++实现学校运动会管理系统

    C++实现学校运动会管理系统

    这篇文章主要为大家详细介绍了C++实现学校运动会管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-10-10
  • C语言模拟实现扫雷游戏

    C语言模拟实现扫雷游戏

    这篇文章主要为大家详细介绍了C语言模拟实现扫雷游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-01-01
  • C语言经典例程100例(经典c程序100例)

    C语言经典例程100例(经典c程序100例)

    这篇文章主要介绍了C语言经典例程100例,经典c程序100例,学习c语言的朋友可以参考一下
    2018-03-03
  • C语言中各种运算类型全面总结

    C语言中各种运算类型全面总结

    C语言运算符是说明特定操作的符号,它是构造C语言表达式的工具,C语言的运算异常丰富,除了控制语句和输入输出以外的几乎所有的基本操作都为运算符处理
    2022-04-04
  • C语言预处理预编译命令及宏定义详解

    C语言预处理预编译命令及宏定义详解

    这篇文章主要为大家介绍了C语言预处理预编译命令及宏定义的详解,其中包含运行环境命名约定条件及#under等基础详解,有需要的朋友可以借鉴参考下
    2021-10-10
  • 数据结构之位图(bitmap)详解

    数据结构之位图(bitmap)详解

    这篇文章主要介绍了数据结构之位图详解,本文讲解了位图的基本知识、位图的实现方法、位图的应用等内容,需要的朋友可以参考下
    2014-08-08
  • 一篇文章彻底弄懂C++虚函数的实现机制

    一篇文章彻底弄懂C++虚函数的实现机制

    C++中的虚函数的作用主要是实现了多态的机制,基类定义虚函数,子类可以重写该函数,在派生类中对基类定义的虚函数进行重写时,需要在派生类中声明该方法为虚方法,这篇文章主要给大家介绍了关于如何通过一篇文章彻底弄懂C++虚函数的实现机制,需要的朋友可以参考下
    2021-06-06
  • C语言 ffmpeg与sdl实现播放视频同时同步时钟详解

    C语言 ffmpeg与sdl实现播放视频同时同步时钟详解

    使用ffmpeg和sdl实现播放视频后,需要再实现时钟同步才能正常的播放视频,尤其是有音频的情况,我们通常需要将视频同步到音频来确保音画同步
    2022-09-09
  • C++算法系列之日历生成的算法代码

    C++算法系列之日历生成的算法代码

    日历算法首先要知道日历的编排规则,也就是历法。所谓历法,指的就是推算年、月、日的时间长度和它们之间的关系,指定时间序列的法则。
    2018-05-05

最新评论