《编程珠玑》笔记1 开篇

  为了克服自己看过就忘的毛病,现在决定用文字把这些东西记录下来。以下大部分是对书上内容的总结。

1.开篇第一部分主要是使用位图法进行排序。

  问题描述:一个最多包含n个整数的文件,每个数小于m,n=10^7,数据不重复(所以m>=n),且随机出现。对该数据进行排序,最多有1MB的内存空间可用。

2.首先分析问题,对n=10^7个数据,设每个int型为4字节,那么总共需要40MB的大小。所以如果要使用归并排序,需要进行40趟磁盘IO,这显然在时间上是难以忍受的。

  考虑该问题的特点:1)数据大小范围有限;2)不重复。

  针对第一个特点,计数排序是一个很好的方法,我们可以申请一个m大小的数组,用对应的值来标记该数是否存在。在考虑到第二个特点,可以用某一位是1还是0就可以完成标记。

  假设有m=n,那么此时需要大小为 10^7 bit = 1.25MB。(注意不要用bool变量的数组来标记是否存在,因为bool变量占一个字节Byte,所以总大小仍需10MB)

代码实现:(直接使用C++中bitset类模板来实现)

 1 #include<iostream>
 2 #include<fstream>
 3 #include<bitset>
 4 using namespace std;
 5 
 6 #define M 10        //the range 
 7 #define N 5        //the number
 8 
 9 int main(int argc, char **argv)
10 {
11     ifstream fin(argv[1]);
12     ofstream fout(argv[2]);
13     bitset<M> data;        //the initial ensure that every bit is 0
14     data.reset();
15 
16     int temp;
17     while(fin >> temp)
18         data.set(temp);
19 
20     for(int i = 0; i < M; i++)
21     {
22         if(data.test(i))
23             fout << i << " ";
24     }
25     return 0;
26 }

 

3.习题:

  3.1 C标准库中的比较函数:

    #include <stdlib.h>

    void qsort ( void * base, size_t num, size_t size, int ( * comparator ) ( const void *, const void * ) );

    base为基本数组,num为元素个数,size为每个元素的大小(一般为sizeof(int)作为参数),最后一个是比较器,大于正,小于负,相等0

    C++中STL提供了很多排序函数位于<algorithm>中。

  3.2主要实现如下三个操作:  

#define BITSPERWORD 32
#define SHIFT 5        //used to divide 20
#define MASK 0x1F
#define N 10000000

int a[1+N/BITSPERWORD];

// 设置为1 就是将该值与一个 只有第i位为1,其余为0的数进行 位或“|”。i>>SHIFT表示 i/32,就得到相应数组元素。 
//  i&MASK得到最后5位值,即 i%32,表示i在该元素的第几位。然后将0x0001左移这么多位即可
void set(int i)
{
    a[i>>SHIFT] |= (1<<(i&MASK));
}

//clr就是设置为0,将该值与 只有第i位为0, 其余为都为1的值 位与
void clr(int i)
{
    a[i>>SHIFT] &= ~(1<<(i&MASK));
}

//test是判断第i位值,将该值与 只有第i位为1,其余位都为0的值 进行 位与,若原值的第i位也为1, 则结果为1,否则结果为0。
//与 int get(int i) 具有同样的函数内容
int test(int i)
{
     return a[i>>SHIFT] & (1<< (i&MASK));
}

  3.3

  3.4 随机生成小于n且没有重复k个整数的算法

              这部分主要在第12章讲述

  3.5 因为前面可以看到位图法要1.25MB的内存空间,如果严格限制1MB的话。

    这时需要使用 多趟算法,第一遍遍历整个输入数据时,只处理其中范围在0~499 9999内的数据,这样只需要500 0000/8=0.625MB即可。第二趟再次从头读取数据,对处于后面范围的数据进行排序处理。

  3.6 如果每个整数最多出现10次,那么0~10就需要4个bit,所以一个整数占4个bit位。总共需1.25*4 = 5MB内存。简单的方法,就是5趟算法即可。

  3.7 对1.4节的程序,要做的就是 检查不合法输入 和 对特殊输入进行处理:

for i = [0,n)
   bit[i] = 0

for each i in input file
  Assert(i>=0 && i <= n)
  if(bit[i] = 1)
    error("duplicate data!");
  bit[i] = 1;

for i = [0,n
  if(bit[i] == 1)
    write i to output file

  可能理解有误,应该是可能出现字母等非数字,然后如何对这些非数字实现bitmap(使用一个特定的hash将出现的负数,字母hash到正确的结构中去?)

3.8 先对区号进行bitmap排序,然后在对每一个区号,遍历一遍输入数据,进行bitmap排序

posted @ 2012-08-27 22:56  dandingyy  阅读(534)  评论(0编辑  收藏  举报