二分查找又稱折半查找,只對
有序的數組有效。
優勢是比較次數少,查找速度快,平均性能好,佔用系統內存較少;
缺點是要求待查表爲有序表,且插入刪除困難。
所以,折半查找方法
適用於不常常變更而查找頻繁的有序列表。
1、算法思想
首先,將表中間位置記錄的值與查找值比較,若是二者相等,則查找成功;不然利用中間位置將表分紅前、後兩個子表,若是中間位置的值大於查找值,則進一步查找前一子表,不然進一步查找後一子表。
重複以上過程,直到找到知足條件的記錄,使查找成功,或直到子表不存在爲止,此時查找不成功。
具體作法以下:
(1) 將數組的第一個位置設置爲下邊界(0)。
(2) 將數組最後一個元素所在的位置設置爲上邊界(數組的長度減 1)。
(3) 若下邊界等於或小於上邊界,則作以下操做:
a. 將中點設置爲floor((上邊界+下邊界)/2)。
b. 若是中點的元素小於查詢的值,則將下邊界設置爲中點元素所在下標加1。
c. 若是中點的元素大於查詢的值,則將上邊界設置爲中點元素所在下標減1。
d. 不然中點元素即爲要查找的數據,能夠進行返回。
2、PHP的二分查找算法實現
一、非遞歸方式
// 數組爲升序排序
function binarySearch($arr, $search) {
$start = 0;
$end = count($arr) - 1;
while ($start <= $end) {
$mid = floor(($start + $end) / 2);
// echo "當前的中點:" . $mid; // 用於顯示每次從新計算後獲得的中點
if ($search == $arr[$mid]) {
return $mid;
} elseif ($search < $arr[$mid]) { // 所查值小於中間值,則在$mid左邊的值中查找
$end = $mid - 1;
} else { // 所查值大於中間值,則在$mid右邊的值中查找
$start = $mid + 1;
}
}
return -1; // 查找失敗
}
二、遞歸方式
function binSearch($arr, $start, $end, $search) {
if ($start <= $end) {
$mid = floor(($start + $end) / 2);
if ($search == $arr[$mid]) {
return $mid;
} elseif ($search < $arr[$mid]) {
return binSearch($arr, $start, $mid - 1, $search);
} else {
return binSearch($arr, $mid + 1, $end, $search);
}
}
return -1;
}
3、計算連續重複次數
function countDuplicate($arr, $search) {
$count = 0;
$position = binarySearch($arr, $search);
if ($position > -1) {
$count++;
for ($i = $position - 1; $i > 0; $i--) {
if ($arr[$i] == $search) {
$count++;
} else {
break;
}
}
for ($i = $position + 1; $i < count($arr); $i++) {
if ($arr[$i] == $search) {
$count++;
} else {
break;
}
}
}
return $count;
}
// 測試
$arr = array(1, 2, 4, 4, 4, 39, 4, 4, 4, 4, 78, 33, 69);
$cnt = countDuplicate($arr, 4);
echo $cnt; // 4
咱們能夠看到,示例中數組有3個連續的4和4個連續的4,而結果爲4。
這是由於這個函數一開始調用 binSearch( ) 函數來查找指定的值。若是在數組中能找到這個值,這個函數就經過兩個循環來統計這個值連續重複出現的次數。
第一個循環向下遍歷數組,統計找到的值出現的次數,當下一個值與要查找的值不匹配時則中止計數。
第二個循環向上遍歷數組,統計找到的值出現的次數,當下一個值與要查找的值不匹配時則中止計數。