`
CalvinMnakor
  • 浏览: 52311 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

《编程珠玑》 二分查找在大量数据中的使用(查找一个不在文件中的数据)

阅读更多
     《编程珠玑》第二章提到的问题A:
      给定一个包含32位整数的顺序文件,它至多包含40亿个这样的整数,并且次序是随机的。请查找一个此文件不存在的32位整数。

      当然,主存足够的话,我们可以使用上章提到的位图法,2^32二进制位,如果用bitset那会超过数组大小范围(即0x7fffffff),使用上章提到的int型数据转换,倒是可以实现。但是,如果内存有限,毕竟你无法一下就开辟536870912个B,太浪费资源了,不是吗?
假设,我们只有上百字节的可用内存空间,我们就要使用书中提到的二分查找法,具体原理这里不论述,下面是关键的部分:
	//每次循环将初始文件转化为个数较小的数据文件
    while (true)
    {
		s = k = 0;
		//读原始数据
		ifstream infile(data,ios::in|ios::_Nocreate);
		if (!infile)
		{
			cerr<<"open error!"<<endl;
			exit(1);
		}
		//分成两个较小文件
		ofstream outfile1("file1.text",ios::out);
		ofstream outfile2("file2.text",ios::out);
		if (!outfile1 || !outfile2)
		{
			cerr<<"open error!"<<endl;
			exit(1);
		}
		for (i = 0;i < n;++ i)                              //每次需读入所有数据 共n个
		{ 
			infile>>temp;                                    //read record number
			if (left <= temp && temp <= (left + right)/2)
			{
				s++;       //left range
			    outfile1<<temp<<" ";
			}
			else          //right range
			{
				k++;
				outfile2<<temp<<" ";
			}
		}
	    infile.close();
		outfile1.close();
		outfile2.close();
		//磁盘数据读完结束
		if (s < k)                                 //select the left side
		{
			right = (left + right)/2;
			//生成新的较小原数据文件
			ofstream outfile("temp.text",ios::out);
			ifstream infile("file1.text",ios::in|ios::_Nocreate);
			if (!outfile || !infile)
			{
				cerr<<"open error!"<<endl;
				exit(1);
			}
			for (int i = 0;i < s;++ i)
			{
				infile>>temp;
				outfile<<temp<<" ";
			}
			n = s;
			outfile.close();
			infile.close();
		}
		else
		{
			left = (left + right)/2;                 //select the right side
			//生成新的较小原数据文件
			ofstream outfile("temp.text",ios::out);
			ifstream infile("file2.text",ios::in|ios::_Nocreate);
			if (!outfile || !infile)
			{
				cerr<<"open error!"<<endl;
				exit(1);
			}
			for (int i = 0;i < k;++ i)
			{
				infile>>temp;
				outfile<<temp<<" ";
			}
			n = k;
			outfile.close();
			infile.close();
		}
		data = "temp.text";
		if (n < SIZE)
		{
			break;
		}
    }

上述过程,每次while循环,生成一个个数较小的一半,并作为下次while循环的原始文件,这样,顺序扫描的文件从n,n/2,n/4,n/8 ....方式递减,另外,为了找到足够多的文件,并考虑到内存空间限制,我们在结果文件足够小时(即内存有效空间内,程序中的SIZE),对得到的文件采用排序算法,查找到遗漏的数据,我们这里采用了上章中提到的位图表示法:
	bitset <SIZE*10> bits;
	int p = 0;
	ifstream infile("temp.text",ios::in|ios::_Nocreate);
	cout<<"between "<<left<<"  and  "<<right<<endl;
	for (int i = 0;i < n;++ i)
	{
		infile>>temp;
		bits.set(temp-left);
	}
	infile.close();

	//保存遗漏数据到result文件
	ofstream outfile("result2.text",ios::out);
	if(!outfile)
	{
		cerr<<"open error!"<<endl;
		exit(1);
	}
	for (int i = left;i < right;++ i)
	{
		if (!bits.test(i-left))
		{
			outfile<<i<<" ";
			p++;
		}
	}

实验中,原始数据,我们使用了前面提到的产生方法,在亿计数量级上的数据,我们大概花了5~6小时,有大概花了2~3小时找到了1000多个遗漏数据,运行内存使用控制在300KB内(任务管理器中)。
分享到:
评论
1 楼 evagame 2010-08-02  
自己看书的时候为这个问题困惑过,看了楼主的文章,获得了思路,谢谢了
不过要指出的是
“我们在结果文件足够小时(即内存有效空间内,程序中的SIZE),对得到的文件采用排序算法,查找到遗漏的数据”

这个不是作者在书中这道题答案的本意,作者明确指出,这道题不需要运用排序算法来解决。

算法读取所有记录,将他们分为高位为1,以及高位为0两类放到不同文件里(用低位也可以),这个过程不需要多少工作内存,几十个byte足够。
    
通过这次分拣,他就知道遗漏的数字在哪一堆,不需要排序。因为第32位为1的数字必定有2^31个,算法中必定有个计数器,做完跟2^31比较一下,比它小的话,那么遗漏的数字肯定就在这一堆。
依次类推二分

楼主可以根据这个思想再写个程序 :-)

相关推荐

    编程珠玑源码下载编程珠玑书后源代码

    2. **算法**:包括排序算法(如快速排序、归并排序)、查找算法(二分查找、哈希查找)等,通过实例展示算法设计和优化的重要性。 3. **问题解决策略**:书中提出了解决编程问题的一些通用方法,如预处理、分治法、...

    编程珠玑 算法 数据结构

    通过对《编程珠玑》一书中关于算法和数据结构的学习,我们不仅可以了解到这些基础知识的重要性,还能掌握如何在实际场景中灵活运用它们来解决问题。无论是对于初学者还是有一定经验的程序员来说,《编程珠玑》都是一...

    编程珠玑源码

    例如,书中可能会介绍如何使用二分查找法来高效地在有序数组中查找元素,这是一种时间复杂度为O(log n)的查找策略,比线性查找有了显著的改进。同时,书中也会讨论如何通过动态规划解决复杂问题,比如背包问题或最长...

    编程珠玑 第二版 修订版 epub

    同时,它也深入讲解了排序、搜索等基础算法,如快速排序、二分查找等,并揭示了它们在实际应用中的表现和改进方法。 3. **输入/输出处理**:书中专门探讨了I/O操作的优化,这对于处理大量数据或实时系统来说至关...

    编程珠玑源代码

    2. 算法:源代码中包含排序算法(如冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序)、查找算法(如顺序查找、二分查找、哈希查找)以及图算法(如深度优先搜索、广度优先搜索)。这些算法是解决问题的...

    编程珠玑(PDF带目录)

    同时,《编程珠玑》强调了搜索算法的重要性,如二分查找、广度优先搜索和深度优先搜索等,这些是处理复杂数据时不可或缺的工具。它们能够帮助程序员在庞大的数据集里高效地找到所需信息,极大提升程序的性能和用户...

    《编程珠玑》第2版中文PDF+源代码

    《编程珠玑》是计算机科学领域的一本经典著作,作者是Jon Bentley,他在书中通过一系列有趣的问题和解决方案,深入浅出地探讨了程序设计的艺术和技巧。这本书的第二版中文PDF和源代码的提供,为中国的程序员和计算机...

    编程珠玑~~~~~~一本经典的数据结构和算法书籍

    《编程珠玑》不仅仅停留在理论层面,还提供了大量的实践案例和代码示例,让读者能够在实践中掌握数据结构和算法的应用技巧。 - **案例分析**:书中精选了多个典型问题,如字符串匹配、模式识别、游戏算法等,通过...

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

    此外,还涉及到了查找技术,包括二分查找、哈希表和B树等,这些都是数据存储和检索的基础。 在数据压缩和编码方面,《编程珠玑》也有所涉及,讲述了如何利用熵编码和哈夫曼编码来高效地表示和传输信息。同时,书中...

    编程珠玑中文版

    1. **信息检索**:书中通过分析图书索引系统,介绍了如何有效地进行信息检索,涉及到二分查找、哈希表和B树等数据结构的运用。 2. **排序与查找**:讨论了多种排序算法(如插入排序、快速排序、归并排序)和查找...

    编程珠玑,PDF压缩文件

    书中的每个章节都围绕一个或多个实际问题展开,比如如何有效地查找和排序数据,如何在有限的内存资源下处理大量数据,以及如何评估和改进程序性能。这些问题的选择既有趣味性,又具有实际应用价值,读者可以在解决...

    编程珠玑pdf+源代码

    同时,书中也涉及到了查找算法,如二分查找和哈希表的应用,这些都是面试中常见的问题。 2. **数据结构**:书中强调了正确选择和使用数据结构的重要性。例如,如何根据问题的特性来决定使用链表、数组、树或其他...

    编程珠玑(第二版).pdf

    2. **数据结构与算法**:书中深入讨论了各种数据结构(如数组、链表、树、图)及其应用场景,同时介绍了常见的排序和搜索算法(如快速排序、二分查找),帮助读者掌握高效处理数据的关键技术。 3. **算法效率分析**...

    编程珠玑(美)Jon Bentley

    在搜索问题中,书中探讨了二分查找、回溯法等策略,并阐述了它们在实际应用中的优势和限制。 此外,《编程珠玑》还强调了程序性能优化的重要性。通过对时间和空间复杂度的深入分析,作者教导读者如何在不牺牲代码...

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

    在提供的压缩包文件中,我们能看到中英文两个版本的《编程珠玑第二版》,这为读者提供了双语学习的机会。英文版可以帮助我们理解原汁原味的编程思想,而中文版则有助于我们更好地理解和记忆内容。同时,书中包含的源...

    编程珠玑第二版

    2. 排序与查找:探讨各种排序算法(如快速排序、归并排序)和查找技术(如二分查找)的原理与应用。 3. 数据压缩:如何通过编码技术减少数据占用的空间。 4. 问题解决策略:提供了一套系统的方法来分析和解决问题。 ...

    编程珠玑电子书

    举例来说,快速排序和二分查找是两种极为常见且重要的排序和搜索算法,它们在解决大量数据处理问题时扮演着关键角色。快速排序以其优秀的平均时间复杂度成为排序算法中的佼佼者,而二分查找则在有序数据集中表现出了...

    编程珠玑编程珠玑续(美)本特利(jb51.net).PDF

    例如,快速排序、二分查找等高效算法的实现和优化,以及它们在大数据处理中的应用。 3. **代码修炼**: 本特利提倡编写清晰、简洁且可维护的代码,他认为好的代码应该是自解释的。书中包含了许多关于重构、调试和...

Global site tag (gtag.js) - Google Analytics