[编程珠玑]第一章 开篇
2012-06-12 14:01
351 查看
1.问题描述
输入:一个最多包含n个整数的文件,文件中的每个整数都小于n,其中n=10^7。输入文件中没有重复的整数。输出:按升序排列的整数列表
约束:最多有大约1MB的内存空间,有充足的磁盘存储空间可用。
(1)采用外排序;每次读入一部分数据至内存进行排序,然后对各部分进行归并。
(2)采用位图法;用一个一千万位的bit串来表示所有的整数,从左到右每一位分别代表整数1,2,3,4,... ...。初始时,所有bit位都为0,顺序扫描一遍输入数据,对每一个待排序的整数,都将对应的bit位置为1. 最后扫描bit串,将所有为1的位对应的整数输出即可。
#include <stdio.h> #include <stdlib.h> #define SHIFT 5 #define MASK 0x1F #define N 10000000 int a[1 + N/32]; void set(int i) { a[i>>SHIFT] |= (1<<(i & MASK)); } void clr(int i) { a[i>>SHIFT] &= ~(1<<(i & MASK)); } int test(int i){ return a[i>>SHIFT] & (1<<(i & MASK)); } int main() { int i = 0; for(i=0;i<N;i++) clr(i); while (scanf("%d", &i)) set(i); for (i = 0; i < N; i++) if (test(i)) printf("%d\n", i); return 0; }
课后题目:
1. 如果不缺内存,使用一个具有库的语言来实现一种排序算法c语言:
头文件【#include<stdlib.h>】
函数形式【qsort(s,n,sizeof(s[0]),cmp);】
比较函数【int cmp(const void *a, const void *b) {return(*(int *)a-*(int *)b);} // 升序】
c++语言:
采用STL中提供的sort函数,或者也可以采用set容器进行排序。
python语言:
python中的列表对象带用sort方法,可以直接调用。
2.如何使用为逻辑运算,来实现位向量
void set(int i) { a[i>>SHIFT] |= (1<<(i & MASK)); } void clr(int i) { a[i>>SHIFT] &= ~(1<<(i & MASK)); } int test(int i) { return a[i>>SHIFT] & (1<<(i & MASK)); }此外也可以直接使用C++中的bitset
3. 略
4.随机生成K个[0,N-1]之间的整数。
(a)分配N个元素的整数数组:A[N],并初始化每个元素为:0,1,2,3,。。。。。。
对于数组的前K个元素,分别将其和数组的其他元素随机调换,调换的最终结果就是,数组的前K个元素为所需的随机整数
(b)使用概率方法,遍历[0,N-1]中的每一个元素,以一定的概率决定是否输出当前元素。第一个元素0被选中的概率为K/N, 如果第一个元素被选中,那么第二个元素1被选中的概率为K-1/N-1, 如果第一个元素0未被选中,则1被选中的概率为K/N-1, 。。。
代码如下:
select = m remaining = n for i = [0, n) if (bigrand() % remaining) < select print i --select --remaining
9.
首先,我们应该对题目进行彻底分析---我们需要访问的是一个长度(假设为n)非常大的数组,一般而言对数组中某个元素访问前我们必须要进行初始化,但是当n值非常大而程序对time要求较严格时,对所有的数组元素都进行统一的初始化是不可取的。为了达到程序对time的要求,我们应该对需要访问的元素(它的个数相对于n来说很小)进行初始化。
其次,对元素初始化的判断---为了提高判断的准确性,答案引入了两个数组from和to以及整数top,且对于元素data[i]已初始化的条件是from[i]<top && to[from[i]]==i。
现在让我们来具体分析这些规则是如何被应用的:假设当我们第一次访问的数组元素下标为1时,先判断初始化条件(此时数组from和to都没有初始化,当然time也不允许让我们多管闲事),一般而言from[1]中的随机数是大于top(现在为0)的,但我们不能保证,于是我们加入了第二个判断条件--to[from[1]]==1,对于这个表达式我们两次取随机值且让后者等于1,这样的概率有但几乎为0!因此,data[1]未被初始化,于是执行from[1]=top; to[top]=1; data[1]=0; top++;这样做的目的就是保证以后再次访问data[1]时不需要再初始化(条件满足了直接读取即可)。
最后,对于该方法的可靠性分析---让我们先来分析一下整数top的作用,不难发现,top记录了当前data中已初始化元素的个数,但主要是保证了from中已初始化的元素都小于top(通过from[i]=top; top++),这给我们的判断条件(from[i]<top)提供了一定的可靠性,当然再加上第二到保险(to[from[i]]==i)使得此方法可靠性值得信赖!
相关文章推荐
- 编程珠玑第一章开篇 总结
- 【读后感】编程珠玑(第二版) 第一章 开篇
- 编程珠玑:第一章开篇课后题解答
- 《编程珠玑》习题练习In Python——第一章 开篇
- 《编程珠玑》读书笔记——第一章.开篇
- 编程珠玑_第一章_ 开篇
- 编程珠玑(开篇)--第一章习题
- 编程珠玑_第一章开篇
- 编程珠玑第一章开篇
- 编程珠玑 第一章习题1
- 开篇第一章<简要IOT技术栈分析>
- 第一章开篇,项目经理的准备,第一篇,为什么要有中国式的项目管理
- 编程珠玑第一章之产生数据1000000-9999999
- 《编程珠玑》第一章笔记
- 编程珠玑第一章,电话号码排序问题
- 【编程珠玑】第一章 开篇
- 编程珠玑第一章 习题2,习题9
- 编程珠玑第一章
- 编程珠玑第一章的算法,Java实现,通俗易懂
- 《编程珠玑》(第二版)第一章习题2(用位运算实现位向量)