【算法分析】查找算法:二分查找、順序查找


08年9月入學,12年7月畢業,結束了我在軟件學院愉快豐富的大學生活。此系列是對四年專業課程學習的回顧,索引參見:http://blog.csdn.net/xiaowei_cqu/article/details/7747205


查找算法


查找算法是在存在的序列(list) 中查找特定的目標(target),要求序列中每個記錄必須與一個關鍵詞(key)關聯才能進行查找。
  查找算法通常需要兩個輸入: 1、被查找的序列 2、要查找的關鍵詞 查找算法的輸出參數和返回值: 1、返回類型為 Error_code 的值用以表示是否查找成功 2、如果查找成功,返回 success, 輸出參數 position 定位到目標所在位置 3、如果查找失敗,返回 not present,輸出參數可能是未定義或不同於已有位置的任何值

順序查找算法


順序查找算法的思路很簡單:從表的第一個元素開始一個一個向下查找,如果有和目標一致的元素,查找成功;如果到最后一個元素仍沒有目標元素,則查找失敗。

【實驗說明】

題目:編寫一個程序,對順序表{3,6,2,10,1,8,5,7,4,9},采用順序查找關鍵字5的過程。要求輸出:
1)原順序表;2)查找到關鍵字的位置;3)進行比較的次數。
1.首先要編寫類表List。需要滿足最基本的操作插入insert(),獲取retrieve(),以及得到大小size()。
2.我們觀察題目要求,表中雖然存儲的是簡單的整數,但如果我們使用List<int>對象顯然無法記錄比較次數,所以我們自己寫一個類Key通過其內部int類型的數據成員來記錄存於表中的值,並模仿int基本的邏輯操作,即編寫重載邏輯運算符,同時增加一個靜態數據成員comparisons用於記錄其比較操作的次數。
3.准備工作做好之后開始編寫順序查找算法。算法的思路很簡單,也較易實現,從表中第一個元素開始比較,發現目標則返回元素所在表中位置;若遍歷之后沒有目標,則查找失敗,返回-1表示表中沒有目標元素。
4.按題目要求編寫最后的輸出函數。

【相關代碼】

函數 sequential_search
int sequential_search(const List<int> &the_list,  const Key &target)
/*Post: If an entry in the_list is equal to target, then return the position
of this entry.
Otherwise return -1
*/
{
int position;
int s=the_list.size();
for(position=0;position<s;position++){
int data;
the_list.retrieve(position,data);
if(data==target){
return position;
}
}
return -1;
}

二分查找算法


二分查找前提是表是按遞增或遞減順序的規范表。此次實驗中我們使用的是遞增表。
二分查找從表中間開始查找目標元素。如果找到一致元素,則查找成功。如果中間元素比目標元素小,則仍用二分查找方法查找表的后半部分(表是遞增排列的),反之中間元素比目標元素大,則查找表的前半部分。

【實驗說明】

題目:編寫一個程序,對有序表{1,2,3,4,5,6,7,8,9,10},采用二分查找關鍵字9的過程。要求輸出:
1)原順序表;2)查找到關鍵字的位置;3)進行比較的次數。
1.二分查找算法的前提是表必須是有序的,如題目中是遞增方式排列的表。實現表的有序一方面是用戶規范輸入,另一方面我們也可以編寫有序的類來方便用戶的輸入。
所以從List中派生類Oredered_list,重新編寫函數Error_code insert(int position,const Record &data),使插入的位置不滿足表的有序條件時,不能插入。
同時編寫插入的重載函數 Error_code insert(const Record &data),可以直接插入到合適的位置,方便用戶輸入。
2.仍使用題目1中的Key來表示目標
3.實現二分查找算法。通過書中的學習,我們直接使用添加相等判斷的二分查找算法。即每次從表的中間元素開始比較,如果得到目標則返回元素所在表中位置;如果中間元素小於目標元素,則對右半部分繼續二分查找;反之對前半部分表進行二分查找。若最后都沒有目標元素,返回-1用以表示表中沒有目標元素。
4.仍使用題目1編寫的輸出函數將結果輸出。
/*注意這里因為Ordered_list是從List中派生而來,所以雖然print_out函數中第一個參數類型是List<int>,仍可以使用,而不用編寫重載函數*/

【相關代碼】

函數 binary_search
int binary_search(const Ordered_list<int> &the_list,const Key &target)/*Post: If an entry in the_list is equal to target, then return the position        of this entry. Otherwise return -1 */{int position;int data;int bottom=0,top=the_list.size()-1;while(bottom<=top){position=(bottom+top)>>1; the_list.retrieve(position,data);if(data==target)return position;if(data<target)bottom=position+1;else top=position-1;}return -1;}

【過程記錄】

實驗截圖:


【結果分析】


A.實現順序查找算法

1.順序查找算法思路很簡單,就是一種遍歷的思想,一個個查找目標元素,實現也很簡單。
2.對於有n個元素的表適用順序查找。比較次數:不成功:比較n次。成功查找:最好的情況為1次,即第一個元素即為目標元素;最差的情況為n次;平均比較次數(n+1)/2次。
所以當表很大時,順序查找的代價是很大的。
3.順序查找算法不會有重復的比較出現,即一旦找到即成功,但同時這種代價是當表中有重復的目標元素時(比如有多個目標元素)我們只能得到第一個元素的位置。

B.實現二分查找算法

1.二分查找法思路:遞增排列的表,首先從中間元素開始查找,如果元素比目標元素小,則查找后半部分表,反之查找前半部分表,並重復這一過程。這樣每次查找中我們都把表的長度減半。
2.二分查找在實現中有量bottom和top,每次減半的過程體現在bottom和top的改變上,在代碼的實現上可以使用單純的循環或者用函數遞歸的思想。
遞歸思想更容易理解,但編寫之后我們發現函數是尾遞歸,尾遞歸通常可以用簡單的循環實現,循環在操作來說沒有了函數調用的過程,更節省時間和空間。
3.編碼中小小地方的改動可能對程序有很大的改觀。
如上述兩種二分查找binary_search_1(不比較等於的情況)binary_search_2(添加等於情況)



實驗代碼下載:http://download.csdn.net/detail/xiaowei_cqu/4437702

(轉載請注明作者和出處:http://blog.csdn.net/xiaowei_cqu 未經允許請勿用於商業用途)




注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com