靜態查找是數據集合穩定不需要添加刪除元素的查找包括:
- 順序查找
- 折半查找
- Fibonacci
- 分塊查找
靜態查找可以用線性表結構組織數據,這樣可以使用順序查找算法,再對關鍵字進行排序就可以使用折半查找或斐波那契查找等算法提高查找效率,平均查找長度:折半查找最小,分塊次之,順序查找最大。順序查找對有序無序表均適用,折半查找適用於有序表,分塊查找要求表中元素是塊與塊之間的記錄按關鍵字有序
動態查找是數據集合需要添加刪除元素的查找包括:
1. 二叉排序樹
2. 平衡二叉樹
3. 散列表
順序查找適合於存儲結構為順序存儲或鏈接存儲的線性表。
元素必須是有序的,如果是無序的則要先進行排序操作。
二分查找即折半查找,屬於有序查找算法。用給定值value與中間結點mid的關鍵字比較,若相等則查找成功;若不相等,再根據value與該中間結點關鍵字的比較結果確定下一步查找的子表
將數組的查找過程繪制成一棵二叉樹排序樹,如果查找的關鍵字不是中間記錄的話,折半查找等於是把靜態有序查找表分成了兩棵子樹,即查找結果只需要找其中的一半數據記錄即可,等於工作量少了一半,然后繼續折半查找,效率高。
時間復雜度為O(log2n);
折半計算mid的公式
mid = (low+high)/2; if(a[mid]==value) return mid; if(a[mid]>value) high = mid-1; if(a[mid]<value) low = mid+1;
改進二分查找算法,將查找點的選擇改進為自適應選擇,差值查找也屬於有序查找。
對於表長較大,而關鍵字分布又比較均勻的查找表來說,插值查找算法的平均性能比折半查找要好的多。反之,數組中如果分布非常不均勻,那么插值查找未必是很合適的選擇。
折半計算mid的公式,等式變換后得到: mid = (low+high)/2 = low + (high-low)/2
mid等於最低下標low加上最高下標high與low的差的一半。將這個 1/2 進行改進,通過類比,改進為下面的計算方案:
mid = low + ((key - a[low])/(a[high] - a[low]))(high - low)這樣就可以大大提高查找的效率。
改進二分查找算法,通過運用黃金比例選擇查找點進行查找,同樣地,斐波那契查找也屬於一種有序查找算法。
斐波那契查找的時間復雜也為O(logn),但就平均性能來說,斐波那契查找要優於折半查找。可惜如果是最壞情況,比如這里key=l,那么始終都處於左側長半區在查找,則查找效率要低於折半查找。
復雜度也為O(log2n)
分塊查找的平均查找長度ASL是折半查找的平均查找長度加順序查找塊內平均查找長度
如果查找的數據集是有序線性表,並且是順序存儲的,查找可以用折半、插值、斐波那契等查找算法來實現,可惜,因為有序,在插入和刪除操作上,就需要耗費大量的時間
若查找表無序,則插入刪除可無需移動大量記錄,但於查找不利。有沒有一種即可以使得插入和刪除效率不錯,又可以比較高效率地實現查找的算法呢?
二叉排序樹(Binary Sort Tree),又稱為二叉查找樹。它或者是一棵空樹,或者是具有下列性質的二叉樹。
若它的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值;
若它的右子樹不空 ,則右子樹上所有結點的值均大於它的根結點的值;
它的左、右子樹也分別為二叉排序樹。
平衡二叉樹(AVL樹)
平衡二叉樹,是一種二叉排序樹,其中每一個節點的左子樹和右子樹的高度差至多等於1。
從平衡二叉的英文名字(AVL樹),你也可以體會到,它是一種高度平衡的二叉排序樹。
高度平衡意思是說,要么它是一棵空樹,要么它的左子樹和右子樹都是平衡二叉樹,且左子樹和右子樹的深度之差的絕對值不超過1。
多路查找樹
我們之前談的樹,都是一個結點可以有多個孩子,但是它自身只存儲一個元素。二叉樹限制更多,結點最多只能有兩個孩子。
一個結點只能存儲一個元素,在元素非常多的時候,就使得要么樹的度非常大(結點擁有子樹的個數的最大值),要么樹的高度非常大,甚至兩者都必須足夠大才行。這就使得內存存取外存次數非常多,這顯然成了時間效率上的瓶頸,這迫使我們要打破每一個結點只存儲一個元素的限制 ,為此引入了多路查找樹的概念。
多路查找樹,其每一個結點的孩子數可以多於兩個,且每一個結點處可以存儲多個元素。由於它是查找樹,所有元素之間存在某種特定的排序關系。
在這里,每一個結點可以存儲多少個元素,以及它的孩子數的多少是非常關鍵的。它的4種特殊形式 : 2-3 樹、2-3-4 樹、B 樹和B+樹。