问题描述
一、输入及约束:在1MB内存中花费10s的时间对10^7个均小于10^7的不重复的数。
二、输出:按升序输出。
(p.s:1MB总共有 1028*1024*8=838,8608个可用位。)
分析:
1. 基于磁盘的归并排序(虽然代码长度减少了,但是运行时间很长)
2.每个号码用7个字节储存,那么1MB内大约可存143 000个号码。若每个号码使用32位整数来存,1MB内能存约250 000个号码。那么10^7个数据可分(10^7/2.5x10^5=40)约40次排序完成排序操作。在内存中采用40趟快速排序。(还是耗时间,而且麻烦)
3.位图法(bitmap):使用一个长10^7位长的字符串来表示每个数。比如集合{0,2,5}就可表示为[101001](即存在该数该位位1否则为0)。然后按顺序输出该数即可。
(p.s:按照该方法内存约为1.25MB,如果要严格限制为1MB,那么①可采用方法二的思想,将一趟遍历其拆分为两趟②将数据中稀疏位去除。)
Exercises:
1.如果不缺内存,使用一个具有库的语言实现排序算法
#include <iostream>
#include <algorithm>
int main()
{
return 0;
}
int Partition(int *array, int left, int right)
{
int priot = array[left];
int first = left;
int last = right;
while(first < last)
{
while(first < last && array[last] >= priot)
{
last--;
}
Swap(&array[first], &array[last]);
while(first < last && array[first] <= priot)
{
first++;
}
Swap(&array[first], &array[last]);
}
return first;
}
void QuickSort(int *array, int first, int last)
{
if(array == NULL)
{
return;
}
if(first < last)
{
int priot = Partition(array, first, last);
QuickSort(array, first, priot - 1);
QuickSort(array, priot + 1, last);
}
}
2.如何使用位逻辑运算来实现位向量
#include <cstdio>
#define BITSTEPWORD 32
#define SHIFT 5
#define MASK 0x1F
#define N 100000000
int array[1 + N / BITSTEPWORD];
void set(int i)
{
array[i >> SHIFT] |= (1 << (i & MASK) );
}
void clr(int i)
{
array[i >> SHIFT] &= ~(1 << (i & MASK) );
}
int test(int i)
{
return array[i >> SHIFT] & (1 << (i & MASK) );
}
int main()
{
for (int i = 0; i < 100; ++i)
set(i*2);
for (int i = 0; i < 200; ++i)
printf("%d\n",test(i) ? 1 : 0 );
return 0;
}
具体说明
① i >> SHIFT :将i右移5位,相当于i除以32,因为int为32位,除以32表示在第几个成员中;举个栗子:如果i为34,则结果为1,说明在array[1]中。
② 1 << (i & MASK) :用掩码留下i的低5位再左移1位,相当于除以32所得余数再左移动1位,因为第一位为0,所以都需要移动1位,结果中1所在位表示i在该数组成员中的第几位上;接着上个栗子,i为34,则i & MASK为2,二进制为10,再向左移动一位为100,说明从0开始第2位是1。