一个有10亿条记录的文本文件,已按照关键字排好序存储。请设计算法,可以快速的从文件中查找指字关键字的记录。
因为已经排好序了,可以使用 二分查找方法检索。
又因为文件过于庞大,可以将文件File分成1000份子记录集即读入10000次,每次读入10亿/10000条记录;
每次 读入一次 10亿/10000 条记录时,记作,将其关键字保存于Records数组中 ,
当读入一个子记录集时,说明关键字key>=Records[0],故只需将关键字key与Records[i]最后一条记录关键字key‘比较,
若key<=key‘,则key在这个records数组中,使用二分查找法检索,若检索不到,则查找失败,返回false结束循环,检索到了,输出true结束循环。
若key>key‘,说明不在该子记录集,则读入下一个子记录集, 循环上述步骤。
若全部读到文件尾,还未查找到,则输出false;
本题以6千左右记录,每次读入1千,模拟上题;
/*在文件中查找关键字:
* 文件中大概有 6千到七千条记录
* 每次读入1千条记录,将其关键字,存于数组,在其中查找
j为本次读入的记录数; 最后一条记录的数组下标为j-1
* 因为文件中记录是有序的,故,当读一个记录集时, 必然会有 key>=recored[0];
* 只需要判断 key 与recored[j-1]的大小,
* 若key>record[j-1] 说明关键字不在此记录集,进入下一次循环。
* 若key<=record[j-1] 则到此记录集中查找:
* 若查找到,则返回true结束循环,
* 若查找不到,说明 整个文件中均不存在此关键字,返回false结束循环
当读完整个文件时,还未查找到,返回false;
public static int recordNumber=6292;
public static File file=new File("E:"+File.separator+"program"+File.separator+"FilesIO"+File.separator+"Text.txt");
*/
public static boolean findKey(int key)throws IOException{
BufferedReader reader=new BufferedReader(new FileReader(file));
for(int i=0;i<7;i++){
Integer[] record=new Integer[1000];
int j;
String s;
for(j=0;j<1000;j++){
if((s=reader.readLine())!=null){
String[] strarray=s.split(" ");
record[j]=Integer.parseInt(strarray[0]);
}else{
break;
}
}
if(key<=record[j-1]){
return twoDevideFindKey(record,0,j-1,key);
}
}
return false;
}
//二份查找法
public static boolean twoDevideFindKey(Integer[] array,int low,int high,int key){
if(low<=high){
int mid=low+(high-low)/2;
if(array[mid]==key) return true;
if(array[mid]>key){
return twoDevideFindKey(array,low,mid-1,key);
}else{
return twoDevideFindKey(array,mid+1,high,key);
}
}else
return false;
}
-------------------------------------------文件创建,写入
/*
* 创建文件,写入6千左右条记录:
* 每条记录一行,第一个字符为关键字,后面为内容。
* 没有关键字相同的记录;
* 记录按关键字排序
*/
public static void createRecordFile() throws IOException{
if(!file.exists()){
System.out.println("文件不存在,将创建文件");
if(!file.createNewFile()){
System.out.println("文件已存在");
}else{
System.out.println("已创建文件");
}
}
PrintWriter out=new PrintWriter(new FileWriter(file));
SortedSet<Integer> keySet=new TreeSet<Integer>();
for(int i=0;i<10000;i++){
int key=(int) (Math.random()*10000);
if(!keySet.contains(key))
keySet.add(key);
}
recordNumber=keySet.size();
Iterator<Integer> iter=keySet.iterator();
int counter=0;
while(iter.hasNext()){
int key=iter.next();
out.println(key+" "+"example"+counter++);
}
if(out!=null) out.close();
System.out.println("记录数为:"+recordNumber);
}