《编程珠玑》第一章

摘要:
1MB总共有8388608个可用位。(耗时)3)位图方法使用一个1000万位的字符串来表示每个数字,例如,{0,2,3}是10110000。(注意:左边的第一位表示0。第二位表示1。第三位表示2。如果有1,则为1。否则为0。)遍历每个整数。如果有,则标记为1。否则,标记为0。有时,在分析问题的约束条件时,可以将极其复杂的问题简化为简单的问题。位图数据结构:描述有限域内的集合。

一、题目:                                                                  

  如何在1MB的空间里面对一千万个整数进行排序?并且每个数都小于1千万。实际上这个需要1.25MB的内存空间(这里所说的空间是考虑用位图表示法时,每一位代表一个数,则1千万/(1024*1024*8) 约为1.25MB  )。

       1MB总共有838,8608个可用位。所以估计也可以在1MB左右的空间里面进行排序了。

分析:                         

        1)基于磁盘的归并排序(耗时间)

        2)每个号码采用32位整数存储的话,1MB大约可以存储250 000 个号码,需要读取文件40趟才能把全部整数排序。(耗时间)

        3)位图法,采用一个1千万位的字符串表示每个数,比如{0,2,3}表示为   1  0 1 1 0 0 0 0 。(说明:左边第一位表示 0 第二位表示1 第三位表示 2 。如果有则表示为1,否则为0)遍历每一个整数,有则标记为1,否则标记为0。然后按顺序输出每个整数。这种方法实际需要1.25MB内存,如果可以方便弄到内存的话可以采用此种方法。

二、代码实现                                                               

《编程珠玑》第一章第1张《编程珠玑》第一章第2张
/*C++中的bitset实现位图*/

#include <iostream>
#include<bitset>
using namespace std;

#define MAXNUMBER 10000000

//利用bitset完成在一定范围内的正整数排序,并标准输出
int IntRangeSort(int pdata[],int n)
{
    //static bitset<MAXNUMBER> intset;
    //或者new一个
    bitset<MAXNUMBER> * intset = new bitset<MAXNUMBER>;
    //用位图记录数据
    for(int i = 0;i < n;i++)
        (*intset)[pdata[i]]=1;
        //intset[pdata[i]]= 1;
    //输出有序数据
    for(int i = 0;i < MAXNUMBER;i++)
        //if(intset[i] == 1)
        if((*intset)[i] == 1)
            cout<<i<<" ";
    cout<<endl;
    return 0;
}

void main()
{
     int pdata[10];
     for(int i = 0;i < 10;i++)
     {
         pdata[i] = rand()%10000000;
         cout<<pdata[i]<<" ";
     }
     cout<<endl;
     IntRangeSort(pdata,10);
    system("pause");
}
View Code

注:利用bitset时设置大于1M的栈大小时,vs会报错误(vs默认分配的栈大小约为1M),解决办法是声明为static(相当于将这些数据放于全局数据区) 或者 new一个bitset(相当于在栈上分配内存)。

《编程珠玑》第一章第3张《编程珠玑》第一章第4张
/*用数组实现位图*/
#include <stdio.h>
#include<stdlib.h>

#define MAXNUMBER 10000000
#define MASK 0x1F
#define SHIFT 5
int sets[1+MAXNUMBER/32];

void set(int i){sets[i>>SHIFT] |= (1<<(i & MASK));}
void clr(int i){sets[i>>SHIFT] &= ~(1<<(i & MASK)); }
int test(int i){return sets[i>>SHIFT] & (1<<(i & MASK));}

void main()
{
    int i = 0;
    while(scanf("%d",&i))
        set(i);
    for(i = 0;i < MAXNUMBER;i++)
        if(test(i))
            printf("%d
",i);
    system("pause");
}
View Code

 注:位操作解释请看:http://zjianjia.blog.163.com/blog/static/17408947520137249535631/

三、课后习题                                                                 

习题1-1:

《编程珠玑》第一章第5张《编程珠玑》第一章第6张
#include <stdio.h>
#include<stdlib.h>

#define MAXNUMBER 10000000

int cmp(const void *a,const void *b)
{
    return (*(int*)a) - (*(int*)b);
}

void main()
{
    static int data[MAXNUMBER];
    int n,i;
    while(scanf("%d",&n) != EOF)
    {
        for(i = 0;i < n;i++)
            scanf("%d",&data[i]);
        qsort(data,n,sizeof(int),cmp);
        for(i = 0;i < n;i++)
            printf("%d  ",data[i]);
        printf("
");
    }
    system("pause");
}
View Code

习题1-4:使用两趟排序

习题1-6:

《编程珠玑》第一章第7张《编程珠玑》第一章第8张
#include <stdio.h>
#include<stdlib.h>

#define MAXNUMBER 10000000
#define BIN 8
#define MASK 0x07
#define SHIFT 3
#define TEST 0x0F
#define POS ((i & MASK)<<2)

int sets[1+MAXNUMBER/BIN];

void set(int i){sets[i>>SHIFT] += 1<<POS;}
void clr(int i){sets[i>>SHIFT] &= ~(TEST<<POS); }
int test(int i){return (sets[i>>SHIFT] & TEST << POS) >> POS;}

void main()
{
    int i = 0,j = 0;
    while(scanf("%d",&i) != EOF)
        set(i);
    for(i = 0;i < MAXNUMBER;i++)
            for(j=test(i);j>0;j--)
            {
                printf("%d  ",i);
                printf("
");
            }
    system("pause");
}
View Code

四、总结                                                                       

1 正确的问题:分析问题的输入、输出、约束。有时在分析问题的约束时可以将一个极其复杂的问题简化为一个简单的问题。

2 位图数据结构:描述了一个有限定义域内的集合。 

这儿是一些面试题中位图的应用【位图数据结构应用】

参考:                                                                          

http://blog.csdn.net/tianshuai1111/article/details/7555563  感谢该作者的分享

http://bbs.csdn.net/topics/110056809 

免责声明:文章转载自《《编程珠玑》第一章》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Vue切换页面时中断axios请求visual Assist常用快捷键下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

编程珠玑第二章

问题A 题目:给定一个包含40亿个随机排列的顺序文件,找到一个不在文件中的32位整数,在有足够内存的情况下应该如何解决该问题?如果有几个外部的临时文件可用,但是仅有几百字节的内存,又该如何解决? (1)对于有足够内存的情况,完全可以采用位图存储的方法,详细内容看《编程珠玑》第一章。 (2)Ed Reingold 给出了另外一种解法。 问题的关键是...

编程珠玑第三章

第三章的总的原则: 1.将重复性代码改到数组中,使用最简单的数据结构---数组来表示一段冗长的相类似的代码往往可以达到最佳效果 2.封装复杂的结构时,使用抽象的术语对她进行定义,并将那些操作表示成一个类。 3.尽可能地使用高级工具。超文本,名称-值对,电子表格,数据库 4.让数据去构造程序。 习题1代码实现: #include <stdio.h>...

全方位掌握nsis脚本

NSIS 确实是一个不错的安装程序制作软件。新版本 2.0a7 真正实现了中文支持和支持 WinXP 的安装对话框。 不过要用它实现漂亮的安装界面和完美的安装功能就必须好好的写脚本。 而 NSIS 的脚本指令是在是太多了,有时候觉得好像又回到了学习 C 语言的年代。他丰富而起强大的功能甚至 可以编译出一些小而使用的软件(例如查找窗口句柄,然后...) 好了...

图片存储类型的种类、特点、区别

BMP 是 DOS 和 Windows 兼容计算机上的标准 Windows图像格式。BMP 格式支持 RGB、索引颜色、灰度和位图颜色模式。可以为图像指定 Windows 或 OS/2&reg; 格式和位深度。对于使用 Windows 格式的 4 位和 8 位图像,还可以指定 RLE 压缩。 BMP 图像通常是自下而上编写出;但您也可以选择“翻转行...

Altium中Logo的导入方法及大小调整

Altium中Logo的导入方法及大小调整 LOGO识别性是企业标志的重要功能之一,特点鲜明、容易辨认,很多客户需要在PCB设计阶段导入LOGO标示归属特性。如果LOGO是CAD图纸,可以直接按照前面DXF导入方法进行导入,如果LOGO是图片文档,我们可以按照如下操作进行导入。 1、位图的转换,利用Windows画图工具,把图片转换成单色的BMP位图...

【WPF学习】第五十二章 动画性能

  通常,为用户界面应用动画只不过是创建并配置正确的动画和故事板对象。但在其他情况下,特别是同时发生多个动画时,可能需要更加关注性能。特定的效果更可能导致这些问题——例如,那些涉及视频、大位图以及多层透明等的效果通常需要占用更多CPU开销。如果不谨慎实现这类效果,运行它们使可能造成明显抖动,或者会从其他同时运行的应用程序抢占CPU时间。   幸运的是,WP...