编程珠玑 第1章 有限内存排序问题

准确的问题描述:

输入:一个最多包含n个正整数的文件,每个数都小于n,其中n=10^7(one million)。在输入文件中没有任何两个            数相同。

输出:按升序排序的输入整数列表。

约束条件:1M的内存空间,有充足的磁盘空间,运行时最多需要几分钟,运行时间为10秒不需要优化。

问题分析:如果每个数字用32位整数来存储,1M的空间可以存储 250,000个整数,失少需要10^7 / 250,000

                 次排序来完成所有的排序,第一次排序0~249999,第四十次排序 97,5000~999,999。

优点:不必使用中间文件。

缺点:需要读取文件40次。

 

书中通过位图或者位向量来表示集合,例如集合{1,2,3,5,8,13}

可通过如下的位图来表示:0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0

java可以通过逻辑运算来实现位向量操作:具体代码如下:

package org.mino.perl.sort;

/**
 * 位逻辑运算实现位向量
 * @author DingJie
 */
public class BitSet {
	private static final int BITPERWORD = 32;  
	private static final int SHIFT = 5;  
	private static final int MASK = 0x1F;  
	public static final int N = 10000000;
	private static int a[] = new int[1 + N/BITPERWORD];
	
	//设置数组第i位为1  
	public static void set(int i) 
	{  
		a[i>>SHIFT] |= (1<<(i&MASK));  //相应的字节置位,实现对字节的操作
	}  
	  
	//清空数组第i位为0  
	public static void clr(int i)  
	{  
		a[i>>SHIFT] &= ~ (1<<(i&MASK));  
	}  
	//查询数组第i位数字 是否为1
	public static int test(int i)  
	{   
		return a[i>>SHIFT] &(1<<(i&MASK));  
	}  
   
}

 在进行大量数据排序之前需要对随机生成1百万个数据,其方法如下所示:

package org.mino.perl.sort;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Random;

/**
 * 获取随机数
 * @author DingJie
 */
public class RandomNum {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
//		RepeatedRandomNumber();
		try {
			randomNoRepeat(999999,1000000);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static int randInt(int i, int j, Random rand) {
		if (i < j)
			return i + rand.nextInt(j - i + 1);
		return i;
	}

	private static void randomNoRepeat(int m, int n) throws IOException {
		int[] array = new int[n];//最大的数组
		Random rand = new Random(System.currentTimeMillis());
		System.out.println(System.currentTimeMillis());
		for (int i = 0; i < n; i++)
			array[i] = i + 1;    //赋初值,保证不重复
		
		for (int i = 0; i < m; i++) {
			int j = randInt(i, n - 1, rand);//返回从i 到n-1之间的任意随机数
			int temp = array[j];
			array[j] = array[i];
			array[i] = temp;
		}
		FileWriter fw = new FileWriter("D:/randomNoRepeat.txt");
		for (int i = 0; i < m; i++) {
			System.out.println(array[i]);
			fw.write(array[i] + "");
			fw.write("\r\n");
			fw.flush();
		}
		if(fw != null) {
			fw.flush();
			fw.close();
		}
	}
	
	/**
	 * 有重复的随机数
	 */
	private static void RepeatedRandomNumber() {
		// TODO Auto-generated method stub
		long timeBegin = System.currentTimeMillis();
		Random rand = new Random(System.currentTimeMillis());
		int bigNum = 1000000;
		BufferedWriter bw = null;
		try {
			bw = new BufferedWriter(new FileWriter("D:/input.txt"));
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		while((--bigNum) > 0) {
			int randInt = Math.abs(rand.nextInt(1000000));
			String strRand = randInt + "";
			try {
				bw.write(strRand);
				System.out.println(strRand);
				bw.newLine();
				bw.flush();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		long timeEnd = System.currentTimeMillis();
		System.out.println(timeEnd - timeBegin);
	}

}

 这样就可以对百万数据进行排序,可以使用java自带的BitSet

package org.mino.perl.sort;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.BitSet;

public class BitSortWithUtil {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		final int N = 10 ^ 7;
		BitSet bs = new BitSet(N);
		File file = new File("D:/randomNoRepeat.txt");
		FileReader fr = null;
		BufferedReader bf = null;
		int total = 0;
		
		try {
			fr = new FileReader(file);
			bf = new BufferedReader(fr);
			String temp = null;
			while((temp = bf.readLine()) != null) {
				total ++;
				int intTemp = Integer.parseInt(temp.trim());
				bs.set(intTemp);
			}
			 
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(bf != null) {
					bf.close();
				} 
				if(fr != null) {
					fr.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		int count = bs.size();
		int not_count = 0;
		for(int i = 0; i < count; i++) {
			if(bs.get(i)){
//				System.out.println(i);
			} else {
				not_count ++;
				System.out.println(i);
			}
		}
		System.out.println("not :" + not_count);
		System.out.println("total :" + (count-not_count) + " /" + total);
	}


}

 自定义位向量

package org.mino.perl.sort;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

/**
 * 实现位排序
 * @author DingJie
 */
public class BitSort {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		File file = new File("D:/randomNoRepeat.txt");
		FileReader fr = null;
		BufferedReader bf = null;
		int total = 0;
		
		for(int i=0; i < BitSet.N; i++) {
			BitSet.clr(i);
		}
		
		try {
			fr = new FileReader(file);
			bf = new BufferedReader(fr);
			String temp = null;
			while((temp = bf.readLine()) != null) {
				total ++;
				int intTemp = Integer.parseInt(temp.trim());
				BitSet.set(intTemp);
			}
			 
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(bf != null) {
					bf.close();
				} 
				if(fr != null) {
					fr.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		int count = 0;
		for(int i = 0; i < BitSet.N; i++) {
			if(BitSet.test(i) == 1) {
				count ++;
				System.out.println(i);
			}
		}
		System.out.println("total :" + count + " /" + total);
		
		
	}

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值