`

编程珠玑 第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);
		
		
	}

}

 

分享到:
评论

相关推荐

    编程珠玑 第2版(修订版)_编程珠玑修订_资料_

    《编程珠玑 第2版(修订版)》是一本深受程序员喜爱的经典著作,它不仅提供了丰富的编程实践经验,还深入探讨了程序设计的艺术与智慧。这本书的修订版更是在原版基础上进行了更新和完善,旨在帮助程序员提升编程技能,...

    编程珠玑(第二版)答案

    《编程珠玑》分为两个部分:第一部分介绍了基本概念和技术;第二部分则通过具体的案例来深化理解这些技术的应用。 ### 二、关键知识点概述 #### 1. 算法分析 - **时间复杂度**:衡量算法执行时间随输入规模增长而...

    编程珠玑 Programming Pearls 第二版(中文版+源代码)

    《编程珠玑》是计算机科学领域的一本经典之作,作者是Jon Bentley,它以其独特的视角和深入浅出的讲解方式,向读者展示了编程艺术的精髓。这本书的第二版更是深受程序员和计算机科学家们的喜爱,因为它不仅涵盖了...

    编程珠玑 第二版 源代码

    《编程珠玑》第二版是计算机科学领域的一本经典著作,由Jon Bentley撰写,它以其深入浅出的方式探讨了程序设计中的诸多问题和解决方案。这本书不仅涵盖了算法和数据结构,还涉及了软件工程的实践与智慧,对于程序员...

    编程珠玑 第二版 中文版 英文版

    例如,书中探讨了如何设计和实现高效的排序算法,如快速排序、归并排序等,以及如何在有限的内存条件下进行大规模数据处理。此外,还涉及到了查找技术,包括二分查找、哈希表和B树等,这些都是数据存储和检索的基础...

    编程珠玑习题集锦

    《编程珠玑》是计算机科学领域的一本经典之作,作者Jon Bentley通过一系列实际问题的探讨,引导读者理解和掌握编程中的高效解题技巧。书中的问题和解决方案涵盖了算法设计、数据结构优化以及问题解决策略等多个方面...

    编程珠玑源代码

    《编程珠玑源代码》是针对经典书籍《编程珠玑》第二版的源代码集合,主要涵盖C语言和C++编程。这本书以其独特的视角和深入浅出的讲解方式,深受程序员喜爱,尤其对于数据结构、算法和程序设计思维的提升有着重要的...

    《编程珠玑》读书笔记

    #### 三、第一章:开篇Cracking the Oyster - **核心问题**:如何对一个磁盘文件进行排序。 - **思维陷阱**:本章首先提出了一个关于排序的具体问题,但通过这一问题引出了更深层次的概念——在解决问题之前,必须...

    编程珠玑第二版

    本书分为多个部分,第一部分通常聚焦于算法设计和分析的基础,如排序和搜索问题。例如,书中可能会介绍快速排序、归并排序等经典排序算法,以及二分查找、哈希表查找等高效搜索技术。这些知识点不仅在面试中常见,也...

    编程珠玑很经典的IT人都知道

    《编程珠玑》第二版在第一版的基础上进行了更新和扩展,包含了更多现代编程实践的案例和思考,如动态规划、遗传算法等高级问题解决策略。同时,书中也加入了对面向对象编程、数据库设计和并行计算等领域的讨论,使得...

    《编程珠玑》部分源代码Java实现

    在第一章中,可能会有如何使用位图来表示和操作大量数据的示例,例如解决“在一个大整数集合中查找特定元素”的问题。 2. **归并排序(Merge Sort)**:归并排序是一种分治算法,它将大问题分解为小问题进行解决,...

    编程珠玑详解

    作者精心挑选了一系列看似简单却又富有深意的编程问题,例如在有限的内存条件下如何处理大规模数据、如何快速查找与排序等。通过这些问题的探讨,不仅帮助读者掌握基础的数据结构知识,如数组、链表、树和图,还引导...

    编程珠玑 中英文 第2版(含源代码)

    《编程珠玑》是计算机科学领域的一本经典著作,作者是Jon Bentley。这本书以其独特的视角,深入浅出地探讨了程序设计中的一些核心问题,并提供了许多实用的解决方案。第二版中,作者不仅保留了原书的精华,还更新了...

    编程珠玑(Programming Pearls) 第二版-- (大礼包)PDF 中文版+英文版+源码

    《编程珠玑(Programming Pearls)》是计算机科学领域中一本经典的著作,由Jon Bentley编著,第二版进一步丰富和完善了第一版的内容。这本书被誉为程序员的智慧结晶,它不仅仅是一本关于编程技巧的书,更是一本探讨...

    编程珠玑第二版.

    《编程珠玑第二版》是程序设计领域里一本极具影响力的著作。这本书以其深入浅出的讲解和富有洞见的分析,深受程序员和计算机科学爱好者的喜爱。书中涵盖了许多编程实践中的核心问题,如数据结构、算法优化、问题解决...

    编程珠玑第二版中英源打包

    书中的每个章节都围绕一个具体的编程问题展开,这些问题既具有趣味性,又具有实用性,例如,如何快速排序大量数据,如何在有限的内存中处理大规模的数据,如何优化查找和插入操作等。这些问题的解决不仅需要扎实的...

Global site tag (gtag.js) - Google Analytics