问题描述:
输入: 一个最多包含n个正整数的文件,每个数都小于n,其中 n = 10^7.如果在输入文件中
有任何整数重复出现就是致命错误.没有其他数据与该整数相关联.
输出: 按升序排列的输入整数的列表
约束: 最多有(大约) 1MB 的内存空间可以使用,有充足的磁盘空间可以使用,运行时间最多
几分钟,运行时间最多为10s就不需要进一步优化了
问题分析:
显而易见 说到排序大家第一个必然想到 快速排序,
方案一: 快速排序
那不妨让我们先计算下快速排序整个文
件所需要的空间大小,假设数据以 32位int型存放
((10^7) * 32) /(8*1024*1024) = 38.14MB
38.14 / 1 = 39 次
是的 我们至少需要 (39 + 1) 次快速排序,需要将数据分40次读入内存.那么时间复杂度可想
而知.
方案二: 归并排序
有兴趣可以去查一下
方案三: 我理解为 基于hash的排序 下面我详述一下
算法思想:
1 用 "位图"(bitmap) 这种数据结构来进行存储数据.
位图: 该数据结构描述了一个有限定义域内的稠密集合,其中的每一个元素至多出现一次
并且没有其他任何数据与该元素相关联.即使这些条件没有完全满足,也可以用有限定义域
内的键作为一个表项更复杂的表格索引.
2 类似于hash排序的思想,用位图存放所需要的内存大小为
(10^7)/(8*1024*1024) = 1.19MB
将内存空间的需求瞬间缩小到 1.19MB 使一次性读入成为可能
算法代码:
输入: 一个最多包含n个正整数的文件,每个数都小于n,其中 n = 10^7.如果在输入文件中
有任何整数重复出现就是致命错误.没有其他数据与该整数相关联.
输出: 按升序排列的输入整数的列表
约束: 最多有(大约) 1MB 的内存空间可以使用,有充足的磁盘空间可以使用,运行时间最多
几分钟,运行时间最多为10s就不需要进一步优化了
问题分析:
显而易见 说到排序大家第一个必然想到 快速排序,
方案一: 快速排序
那不妨让我们先计算下快速排序整个文
件所需要的空间大小,假设数据以 32位int型存放
((10^7) * 32) /(8*1024*1024) = 38.14MB
38.14 / 1 = 39 次
是的 我们至少需要 (39 + 1) 次快速排序,需要将数据分40次读入内存.那么时间复杂度可想
而知.
方案二: 归并排序
有兴趣可以去查一下
方案三: 我理解为 基于hash的排序 下面我详述一下
算法思想:
1 用 "位图"(bitmap) 这种数据结构来进行存储数据.
位图: 该数据结构描述了一个有限定义域内的稠密集合,其中的每一个元素至多出现一次
并且没有其他任何数据与该元素相关联.即使这些条件没有完全满足,也可以用有限定义域
内的键作为一个表项更复杂的表格索引.
2 类似于hash排序的思想,用位图存放所需要的内存大小为
(10^7)/(8*1024*1024) = 1.19MB
将内存空间的需求瞬间缩小到 1.19MB 使一次性读入成为可能
算法代码:
以下代码仅作思想体现,实际意义并不大
#include <iostream>
#include <cmath>
#define MAX 4
using namespace std;
// 初始化字典数组
int Dic[32] = {0};
void InItDic(){
for(int i = 0;i<32;i++)
Dic[i] = pow(2,i);
}
int main(){
// 申请大小为 312500的数组,当然直接申请这么大的很容易崩溃,不推荐
int array[312500] = {0};
int i;
int Wait[MAX] = {0};
InItDic();
// 生成待排序资料 也可以从硬盘中读取
for(i=0;i<MAX;i++){
Wait[i] = MAX - i - 1;
}
// 进行排序
/*
具体解析:
一个int有32位,即 312500 * 32 = 10^7
将 待排序数/32 计算出应该存储这个位的数字编号
将 待排序数%32 计算出存储在这个数的哪一二进制位
然后将这一位置为1,我在此采用置1的方法是,将表示该位的数
与原数做 按位或 运算
最后按位遍历 得到的就是升序序列
*/
for(i=0;i<MAX;i++)
array[Wait[i]/32] |= Dic[Wait[i]%32];
cout << array[0];
}
// 个人见解 欢迎指正 不胜感激