資料結構和演算法之——二分查詢下
最簡單的二分查詢情況下,我們假設陣列中沒有重複元素,因此很容易實現。如果陣列中存在重複元素,二分查詢就沒有想象中那麼容易了。
1. 查詢第一個值等於給定值的元素?
如果資料中存在相同的元素,但我們要查詢第一個值等於給定值的元素,如果直接用最簡單的二分查詢,顯然是不滿足的。
看下面的例子,有 3 個等於 8 的元素,簡單二分查詢會返回 7,但第一個值等於 8 的元素應該是 a[5]。
其實,只要我們在簡單二分查詢的基礎上再多加上一點限制即可。
當我們發現 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 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;
}
2. 查詢最後一個值等於給定值的元素?
這個問題和上面要查詢第一個值等於給定值的問題思路一樣,只不過是查詢的方向改變了。
當我們發現 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;
}
3. 查詢第一個大於等於給定值的元素?
當我們發現 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 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;
}
4. 查詢最後一個小於等於給定值的元素?
當我們發現 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 (data[mid] <= value)
{
if (mid == end || a[mid + 1] > a[mid]) return mid;
else left = mid + 1;
}
else
{
right = mid - 1;
}
}
return -1;
}
5. 如何快速定位 IP 對應的省份?
當我們要查詢 202.102.133.13 這個 IP 地址的歸屬地時,我們就在地址庫中搜尋,發現這個 IP 位於 [202.102.133.0, 202.102.133.255] 這個範圍內,我們就可以找到對應的歸屬地——山東東營。
[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 地址的區間。
獲取更多精彩,請關注「seniusen」!
相關文章
- 資料結構和演算法之——二分查詢上資料結構演算法
- 資料結構與演算法-二分查詢資料結構演算法
- 【資料結構與演算法】—— 二分查詢資料結構演算法
- 資料結構與演算法整理總結---二分查詢資料結構演算法
- 演算法與資料結構——二分查詢插入點演算法資料結構
- 資料結構和演算法面試題系列—二分查詢演算法詳解資料結構演算法面試題
- iOS標準庫中常用資料結構和演算法之查詢iOS資料結構演算法
- [資料結構] 二分查詢 (四種寫法)資料結構
- 【Java資料結構與演算法】簡單排序、二分查詢和異或運算Java資料結構演算法排序
- 資料結構與演算法:查詢演算法資料結構演算法
- 【資料結構基礎應用】【查詢和排序演算法】資料結構排序演算法
- 6-1 二分查詢 (20分) PTA 資料結構資料結構
- 如何找東西?查詢演算法之順序查詢和二分查詢詳解演算法
- 查詢演算法__二分查詢演算法
- 從零開始學資料結構和演算法 (五) 分治法 (二分查詢、快速排序、歸併排序)資料結構演算法排序
- 重學資料結構和演算法(三)之遞迴、二分、字串匹配資料結構演算法遞迴字串匹配
- 查詢演算法之二分查詢演算法
- 資料結構和演算法之-列表資料結構演算法
- 演算法與資料結構之並查集演算法資料結構並查集
- 23.資料結構 查詢資料結構
- 資料結構與演算法-二叉查詢樹資料結構演算法
- 資料結構與演算法 第五章 查詢資料結構演算法
- 資料結構與演算法——查詢演算法-斐波那契(黃金分割法)查詢資料結構演算法
- 演算法->二分查詢演算法
- 【演算法】二分查詢演算法
- 資料結構和演算法之——跳錶資料結構演算法
- 重學資料結構(八、查詢)資料結構
- 『資料結構與演算法』二叉查詢樹(BST)資料結構演算法
- 資料結構與演算法知識點總結(5)查詢樹資料結構演算法
- 資料結構之查詢(順序、折半、分塊查詢,B樹、B+樹)資料結構
- 二分查詢【折半查詢】演算法 PHP 版演算法PHP
- 資料結構實驗之查詢七:線性之雜湊表資料結構
- 資料結構之並查集資料結構並查集
- 資料結構與演算法-二叉查詢樹平衡(DSW)資料結構演算法
- 資料結構與演算法-二叉查詢樹平衡(AVL)資料結構演算法
- 【資料結構與演算法】手撕二叉查詢樹資料結構演算法
- LeetCode演算法—二分查詢LeetCode演算法
- 資料結構之PHP二分搜尋樹資料結構PHP