最簡單的二分查找狀況下,咱們假設數組中沒有重複元素,所以很容易實現。若是數組中存在重複元素,二分查找就沒有想象中那麼容易了。
若是數據中存在相同的元素,但咱們要查找第一個值等於給定值的元素,若是直接用最簡單的二分查找,顯然是不知足的。算法
看下面的例子,有 3 個等於 8 的元素,簡單二分查找會返回 7,但第一個值等於 8 的元素應該是 a[5]。數組
其實,只要咱們在簡單二分查找的基礎上再多加上一點限制便可。數據結構
當咱們發現 a[mid] = val 時,咱們須要繼續確認 a[mid] 左邊還有沒有等於 val 的元素。若 mid 左邊沒有和 a[mid] 相等的元素,則此時 a[mid] 就是咱們要找的第一個值等於給定值的元素。另外,若 mid 到了第一個元素的位置,說明左邊已經沒有元素,此時 a[mid] 也便是咱們要找的元素。不然,咱們就須要繼續向左邊查找。spa
float Binary_Search(float data[], int left, int right, float value) { int begin = left; while (left <= right) { int mid = left + (right - left) / 2; if (value == data[mid]) { if (mid == begin || a[mid - 1] != a[mid]) return mid; else right = mid - 1; } else if (value < data[mid]) { right = mid - 1; } else { left = mid + 1; } } return -1; }
這個問題和上面要查找第一個值等於給定值的問題思路同樣,只不過是查找的方向改變了。code
當咱們發現 a[mid] = val 時,咱們須要繼續確認 a[mid] 右邊還有沒有等於 val 的元素。若 mid 右邊沒有和 a[mid] 相等的元素,則此時 a[mid] 就是咱們要找的最後一個值等於給定值的元素。另外,若 mid 到達了最後一個元素的位置,說明右邊已經沒有元素,此時 a[mid] 也便是咱們要找的元素。不然,咱們就須要繼續向右邊查找。排序
float Binary_Search(float data[], int left, int right, float value) { int end = right; while (left <= right) { int mid = left + (right - left) / 2; if (value == data[mid]) { if (mid == end || a[mid + 1] != a[mid]) return mid; else left = mid + 1; } else if (value < data[mid]) { right = mid - 1; } else { left = mid + 1; } } return -1; }
當咱們發現 a[mid] >= val 時,咱們須要繼續確認 a[mid] 左邊還有沒有大於等於 val 的元素。若 mid 左邊的值小於 a[mid],則此時 a[mid] 就是咱們要找的第一個大於等於給定值的元素。另外,若 mid 到達了第一個元素的位置,說明左邊已經沒有元素,此時 a[mid] 也便是咱們要找的元素。不然,咱們就須要繼續向左邊查找。rem
float Binary_Search(float data[], int left, int right, float value) { int begin = left; while (left <= right) { int mid = left + (right - left) / 2; if (data[mid] >= value) { if (mid == begin || a[mid - 1] < a[mid]) return mid; else right = mid - 1; } else { left = mid + 1; } } return -1; }
當咱們發現 a[mid] <= val 時,咱們須要繼續確認 a[mid] 右邊還有沒有小於等於 val 的元素。若 mid 右邊的值大於 a[mid],則此時 a[mid] 就是咱們要找的最後一個小於等於給定值的元素。另外,若 mid 到達了最後一個元素的位置,說明右邊已經沒有元素,此時 a[mid] 也便是咱們要找的元素。不然,咱們就須要繼續向右邊查找。get
float Binary_Search(float data[], int left, int right, float value) { int end = right; while (left <= right) { int mid = left + (right - left) / 2; if (data[mid] <= value) { if (mid == end || a[mid + 1] > a[mid]) return mid; else left = mid + 1; } else { right = mid - 1; } } return -1; }
當咱們要查找 202.102.133.13 這個 IP 地址的歸屬地時,咱們就在地址庫中搜索,發現這個 IP 位於 [202.102.133.0, 202.102.133.255] 這個範圍內,咱們就能夠找到對應的歸屬地——山東東營。it
[202.102.133.0, 202.102.133.255] 山東東營市 [202.102.135.0, 202.102.136.255] 山東煙臺 [202.102.156.34, 202.102.157.255] 山東青島 [202.102.48.0, 202.102.48.255] 江蘇宿遷 [202.102.49.15, 202.102.51.251] 江蘇泰州 [202.102.56.0, 202.102.56.255] 江蘇連雲港
所以,咱們能夠按照 IP 地址庫的起始地址對全部區間進行排序,而後問題就轉化爲了找到最後一個起始地址小於等於給定 IP 地址的區間。class
獲取更多精彩,請關注「seniusen」!