一個有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;dom
本題以6千左右記錄,每次讀入1千,模擬上題;ide
/*在文件中查找關鍵字:
* 文件中大概有 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");排序
*/it
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);
} io
}file
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); }