热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

C++实现位图排序实例

这篇文章主要介绍了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 
#include 
using namespace std; 
 
#define MAX 20 
 
int main() 
{ 
  int arr[10] = {5,1,2,13,7,10,0,20,16,9}; 
 
  bitset bit; 
   
  /* 将对应位置置1 */ 
  for(int i=0; i<10; ++i) 
  { 
    bit.set(arr[i]); 
    /* bit.set(n)表示将第n位置1 */ 
  } 
 
  /* 输出排序结果 */ 
  for(int i=0; i

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


推荐阅读
  • 大华股份2013届校园招聘软件算法类试题D卷
    一、填空题(共17题,每题3分,总共51分)1.设有inta5,*b,**c,执行语句c&b,b&a后,**c的值为________答:5 ... [详细]
  • 使用Echarts for Weixin 小程序实现中国地图及区域点击事件
    本文介绍了如何使用Echarts for Weixin在微信小程序中构建中国地图,并实现区域点击事件。包括效果展示、条件准备和逻辑实现的具体步骤。 ... [详细]
  • 面试题总结_2019年全网最热门的123个Java并发面试题总结
    面试题总结_2019年全网最热门的123个Java并发面试题总结 ... [详细]
  • HNOI2003 激光炸弹问题(二维前缀和的应用)难度:中等
    HNOI2003 激光炸弹问题是一个经典的二维前缀和应用题目。本文将详细介绍如何使用二维前缀和解决该问题。 ... [详细]
  • 题目编号:2049 [SDOI2008]Cave Exploration。题目描述了一种动态图操作场景,涉及三种基本操作:断开两个节点间的连接(destroy(a,b))、建立两个节点间的连接(connect(a,b))以及查询两节点是否连通(query(a,b))。所有操作均确保图中无环存在。 ... [详细]
  • 本文探讨了 Koa 框架中中间件为何需要遵循洋葱模型,并解释了如何通过使用 async 和 await 来确保中间件按正确的顺序执行。 ... [详细]
  • 本文详细介绍了进程、线程和协程的概念及其之间的区别与联系。进程是在内存中运行的独立实体,具有独立的地址空间和资源;线程是操作系统调度的基本单位,属于进程内部;协程则是用户态下的轻量级调度单元,性能更高。 ... [详细]
  • 作为一名图像识别专家,在使用数码相机拍摄时遇到了一些困惑。为了能够拍摄出自己满意的图像,我查阅了大量资料,并在此分享一些关键的拍摄技巧和参数设置。 ... [详细]
  • 深入浅出C语言指针
    指针是C语言中极其重要的数据类型,广泛应用于各种数据结构的表示、数组和字符串的操作以及内存地址的处理。本文将通过实例详细解析指针的基本概念及其应用。 ... [详细]
  • Python 日志记录模块详解
    日志记录机制是软件开发中不可或缺的一部分,它帮助开发者追踪和调试程序运行时的各种异常。Python 提供了内置的 logging 模块,使我们在代码中记录和管理日志信息变得更加方便。本文将详细介绍如何使用 Python 的 logging 模块。 ... [详细]
  • 深入解析Pod中的容器关系
    容器之间的紧密协作如何实现?本文探讨了Kubernetes中Pod的概念及其在处理容器间超亲密关系中的作用。 ... [详细]
  • 通过马老师的视频学习了Java中的容器相关内容,包括Collection、Set、List、Map及其常见实现类,并深入了解了这些容器的基本操作方法。 ... [详细]
  • 直播带货系统中的推流技术详解
    本文介绍了RTMP(实时消息传输协议)及其在直播带货系统中的应用,并详细探讨了带货直播系统的连麦方案,包括服务端合流和客户端合流的优势与劣势。 ... [详细]
  • CSS 百分比单位的取值依据是什么
    本文详细探讨了 CSS 中百分比单位的取值依据,包括不同定位方式下的包含块概念及其应用。通过具体的示例和代码,帮助读者更好地理解和掌握这一知识点。 ... [详细]
  • Docker 环境下 MySQL 双主同步配置指南
    本文介绍了如何在 Docker 环境中配置 MySQL 的双主同步,包括目录结构的创建、配置文件的编写、容器的创建与设置以及最终的验证步骤。 ... [详细]
author-avatar
手机用户2502912891
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有