Chinaunix首页 | 论坛 | 博客
  • 博客访问: 101656
  • 博文数量: 18
  • 博客积分: 681
  • 博客等级: 中士
  • 技术积分: 295
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-17 13:33
文章分类
文章存档

2012年(8)

2011年(10)

分类: C/C++

2011-11-20 21:05:00

该文主要来自于编程珠玑第一章上的题目。

输入:一个最多包含n个正整数的文件,每个数都小于n,其中n=10^7。如果在输入文件中有任何证书重复出现就是致命错误。没有其它数据与该整数关联。
输出:按升序排列的输入整数的列表。
约束:最多有(大约)1MB的内存空间可用,有充足的磁盘空间可用。运行时间最多为几分钟,运行时间为10秒就不需要进一步优化了。

解决方案,定义一个位向量,如bit_vector[10000000],初始化为0;遍历文件中的每个正整数i,设置bit_vector[i]为1。最后,遍历bit_vector,输出元素为1的下标。

下面给出代码,位向量的实现程序
  1. #ifndef BIT_VECTOR
  2. #define BIT_VECTOR
  3. /*
  4.  * bit_vector.h
  5.  *
  6.  * 使用二进制位存放向量的数据结构。举个例子,如果我们有个向量{1,2,4,7,15}
  7.  * 那么,用二进制位可以表示成 10000000 10010110,从右往左看,第n位为1表示
  8.  * n处在向量中(从0开始)。
  9.  * 
  10.  * 使用示例:
  11.  * bit_vector bv(64); // 能存放[0, 64)的整数
  12.  * bv.put(0);
  13.  * bv.print();
  14.  * bv.put(63);
  15.  * bv.print();
  16.  * bv.get(0); // 1
  17.  * bv.get(1); // 0
  18.  * bv.get(63); // 1
  19.  */ 
  20. #include <cstdio>
  21. #define INT_BITS (sizeof(int)*8)

  22. class bit_vector {
  23.   int * bits_;
  24.   int n_;

  25. public:
  26.   // 申请n位的位向量,并初始化为0
  27.   bit_vector(int n=INT_BITS){
  28.     n_ = n / INT_BITS;
  29.     if (% INT_BITS != 0) {
  30.       n_++;
  31.     }
  32.     bits_ = new int[n_];
  33.     for (int i=0; i<n_; ++i) {
  34.       bits_[i] = 0;
  35.     }
  36.   }

  37.   // 清除申请的内存
  38.   ~bit_vector() {
  39.     delete bits_;
  40.   }

  41.   // 把数m放入位向量中,即位向量的第m位置为1
  42.   void put(int x) {
  43.     int i = x / INT_BITS;
  44.     int j = x % INT_BITS;
  45.     bits_[i] |= 1 << j;
  46.   }

  47.   // 把第x位重置为0
  48.   void clear(int x) {
  49.     int i = x / INT_BITS;
  50.     int j = x % INT_BITS;
  51.     bits_[i] &= ~(<<);
  52.   }

  53.   // 如果数x在位向量中,返回不为0,否则返回0
  54.   int get(int x) {
  55.     int i = x / INT_BITS;
  56.     int j = x % INT_BITS;
  57.     return bits_[i] & 1 << j;
  58.   }
  59.   
  60.   // 打印出位向量
  61.   void print() {
  62.     for (int i=n_-1; i>=0; --i) {
  63.       printf("%08x ", bits_[i]);
  64.     }
  65.     printf("\n");
  66.   }
  67. };
  68. #endif // BIT_VECOTR
生成测试数据的程序
  1. /*
  2.  * gen_data.cc
  3.  *
  4.  * 生成[0,n)之间的k个不同的随机顺序的随机整数。
  5.  *
  6.  * 主要思想是定义个长度为n的数组a,a[i]=i。第一次从a[0:n-1]中随机取个
  7.  * 元素,并和a[n-1]调换。第二次,从a[0:n-2]中随机取个元素,并和a[n-2]调换。
  8.  * 经过k次这样的调换之后,a[n-k-1,n-1]就是我们需要的随机整数序列。
  9.  *
  10.  * 不计算初始化数组的复杂度,复杂度为O(k)
  11.  */
  12. #include <cstdio>
  13. #include <cstdlib>
  14. #define N 10000000
  15. #define K 1000000

  16. int main(int argc, char *argv[])
  17. {
  18.   int *= new int[N];
  19.   for (int i=0; i<N; ++i) {
  20.     a[i] = i;
  21.   }
  22.  
  23.   int end = N;
  24.   while (N-end <= K) {
  25.     int r = rand() % end; // 取随机数r in [0, end)
  26.     
  27.     int temp = a[r];
  28.     a[r] = a[end-1];
  29.     a[end-1] = temp; 
  30.     
  31.     end--;
  32.   }
  33.   
  34.   FILE* out_file = fopen("data.txt", "w");
  35.   for (int i=N-K; i<N; i++) {
  36.     fprintf(out_file, "%08d\n", a[i]);
  37.   }
  38.   fclose(out_file);

  39.   delete a;

  40.   return 0;
  41. }
主程序文件:
  1. #include "bit_vector.h"
  2. #include <cassert>

  3. #define N 10000000

  4. int main(int argc, char *argv[])
  5. {
  6.   FILE* in_file = fopen("data.txt", "r");
  7.   bit_vector bv(N);
  8.   
  9.   int x;
  10.   while (!feof(in_file)) {
  11.     fscanf(in_file, "%d\n", &x);
  12.     bv.put(x);
  13.   }
  14.   fclose(in_file);

  15.   FILE * out_file = fopen("sorted_data.txt", "w");
  16.   for (int i=0; i<N; ++i) {
  17.     if (bv.get(i) != 0) {
  18.       fprintf(out_file, "%08d\n", i);
  19.     }
  20.   }
  21.   fclose(out_file);

  22.   return 0;
  23. }
组织文件Makefile和run.sh:
  1. all:
  2. g++ -Wall -o main main.cc
  3. g++ -Wall -o gen_data gen_data.cc
  1. make
  2. ./gen_data
  3. ./main
  4. wc -l data.txt sorted_data.txt
阅读(1819) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~