教训1:Careful analysis of a small problem can sometimes yield tremendous practical benefits!!!
====================================================================
问题:
输入,输入为一个文件,至多包含n个正整数,每个正整数都小于n,这里n=10 的7次方(最多用40MB主存空间)。
如果输入时某个整数出现了两次,就会产生致命错误。
输出:以增序输出经过排序的整数列表。
约束:只有1MB的可用主存(代码除外);但磁盘空间非常充足。
解决方法:分40次读入输入文件,第一次读入0-249999之间的数(最多占1MB),排序后输出到文件中,
第二次读入250000-499999之间的数,排序后输出到文件,第40次读入排序9750000-9999999之间的整数
并输出到文件,至此所有数据都已经排好序。这个方法确实很巧妙,但我想说的是排序方法,书中指出
用快速排序很快,但我想在没有多余空间的情况下是否能用快速排序呢?并且在目前这种情况下,快速排序
未必是最快的方法。基于排序对象是整数而且无重复数据的这一事实,我们可以设一个250000个元素的整数数组,第一次
输入(0-249999)可以各就各位,即0存入元素0,249999存入元素249999,一遍即可排好序,而且也无须
额外的存储空间,第二次(250000-499999)把每个待排序的数减去250000,一样可以与数组一一对应,第三次则减去500000,
以后以此类推。
思路1:1M内存大约可以存储250000个整数。因此我们可以对输入文件遍历40次,第一次遍历过程中将值大于0、小于249999的所有整数读入内存,然后进行快速排序,再写入目标文件;第二次遍历过程中将值大于250000、小于499999的所有整数读入内存,排完序后写入目标文件,后面依此类推;第40次遍历过程中将大于9750000、小于9999999的所有整数读入内存,排完序后写入目标文件。此时目标文件中的整数已按增量排完序,顺序输出即可。
思路2:系统排序
(Command命令行)>sort originalFileName.ext >> targetFileName.ext
思路3:位图数据结构。








如果不限内存,还可以使用下面两种排序方法:
思路1:C++/STL











思路2:C/qsort














-----------------------------------------------------------------------------------------------------------------------------------------------
在我们写程序的的时候,有时候我们经常需要存储许多的二值的信息量,如:一件事情有没有发生、很多灯的亮灭的状态、网络传输中判断重复数据包等。这时我们就需用用一个信息单元来存储1、0 信息来表示有或无。那我们该怎么表示呢?最简单的方法就是使用数组了
这个数组中就可以存储256个信息量的状态,每个数组单位中存储一个0或1(buf[0] = 1, buf[1] = 0;)。这里我们有一种更好的方法就是用C语言中的位操作来实现这个需求。使用char类型的8位表示8个信息量,使用每一位01表示不同。这样我们用char buf[32]就可以存储256个二值信息量,大大节约了空间。位操作不能像数组操作那样直接简单,所以我们封装了几组函数如下:
#define SHIFT 5
#define MASK 0x1F
#define N 10000000
int a [ 1 + N /BITSPERWORD ];
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类型表示32个信息量。
a[i>>SHIFT]来确定设置a数组的哪一个元素,(1<<(i & MASK))用来确定设置一个a数组元素中的某一位!
我们的需求是判断0 ~ 10000000 之中的数字是否出现过,而set(1)、clr(1)、test(1)函数就可以将表示数字一是否存在的哪一位置为1、清零、判断是否为1。这样我们就可以通过这几个函数来实现位的操作。
源代码:
/* Copyright (C) 1999 Lucent Technologies */
/* From 'Programming Pearls' by Jon Bentley */
/* bitsort.c -- bitmap sort from Column 1
* Sort distinct integers in the range [0..N-1]
*/
#include <stdio.h>
#define BITSPERWORD 32
#define SHIFT 5
#define MASK 0x1F
#define N 10000000
int a[1 + N/BITSPERWORD];
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;
for (i = 0; i < N; i++)
clr(i);
/*Replace above 2 lines with below 3 for word-parallel init
int top = 1 + N/BITSPERWORD;
for (i = 0; i < top; i++)
a[i] = 0;*/
while (scanf("%d", &i) != EOF)
set(i);
for (i = 0; i < N; i++)
if (test(i))
printf("%d/n", i);
return 0;
}