日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

二分搜索(折半搜索),lower_bound,upper_bound

發(fā)布時(shí)間:2023/12/15 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 二分搜索(折半搜索),lower_bound,upper_bound 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

二分查找

二分查找也稱折半查找(Binary Search),它是一種效率較高的查找方法。但是,折半查找要求線性表必須采用順序存儲(chǔ)結(jié)構(gòu),而且表中元素按關(guān)鍵字有序排列。

查找過(guò)程

首先,假設(shè)表中元素是按升序排列,將表中間位置記錄的關(guān)鍵字與查找關(guān)鍵字比較,如果兩者相等,則查找成功;否則利用中間位置記錄將表分成前、后兩個(gè)子表,如果中間位置記錄的關(guān)鍵字大于查找關(guān)鍵字,則進(jìn)一步查找前一子表,否則進(jìn)一步查找后一子表。重復(fù)以上過(guò)程,直到找到滿足條件的記錄,使查找成功,或直到子表不存在為止,此時(shí)查找不成功。

算法要求

1.必須采用順序存儲(chǔ)結(jié)構(gòu)。
2.必須按關(guān)鍵字大小有序排列。

算法復(fù)雜度

二分查找的基本思想是將n個(gè)元素分成大致相等的兩部分,取a[n/2]與x做比較,如果x=a[n/2],則找到x,算法中止;如果x<a[n/2],則只要在數(shù)組a的左半部分繼續(xù)搜索x,如果x>a[n/2],則只要在數(shù)組a的右半部搜索x.
時(shí)間復(fù)雜度即是while循環(huán)的次數(shù)。
總共有n個(gè)元素,
漸漸跟下去就是n,n/2,n/4,…n/2^k(接下來(lái)操作元素的剩余個(gè)數(shù)),其中k就是循環(huán)的次數(shù)
由于你n/2^k取整后>=1
即令n/2^k=1
可得k=log2n,(是以2為底,n的對(duì)數(shù))
所以時(shí)間復(fù)雜度可以表示O(h)=O(log2n)

二分查找圖示

二分查找模板

①查找精確值,從一個(gè)有序數(shù)組中找到一個(gè)符合要求的精確值(如猜數(shù)游戲)。如查找值為Key的元素下標(biāo),不存在返回-1。

//這里是left<=right。 //考慮這種情況:如果最后剩下A[i]和A[i+1](這也是最容易導(dǎo)致導(dǎo)致死循環(huán)的情況)首先mid = i, //如果A[mid] < key,那么left = mid+1 = i +1,如果是小于號(hào),則A[i + 1]不會(huì)被檢查,導(dǎo)致錯(cuò)誤 int left = 1,right = n; while(left <= right) {//這里left和right代表的是數(shù)組下標(biāo),所有沒(méi)有必要改寫成mid = left + (right - left)/2;//因?yàn)楫?dāng)代表數(shù)組下標(biāo)的時(shí)候,在數(shù)值越界之前,內(nèi)存可能就已經(jīng)越界了//如果left和right代表的是一個(gè)整數(shù),就有必要使用后面一種寫法防止整數(shù)越界int mid = (left + right) / 2;if(A[mid] == key)return mid;else if(A[mid] > key)//這里因?yàn)閙id不可能是答案了,所以搜索范圍都需要將mid排除right = mid - 1;elseleft = mid + 1; } return -1;

②查找大于等于/大于key的第一個(gè)元素。

int left = 1,right = n; while(left < right) {//這里不需要加1。我們考慮如下的情況,最后只剩下A[i],A[i + 1]。//首先mid = i,如果A[mid] > key,那么right = left = i,跳出循環(huán),如果A[mid] < key,left = right = i + 1跳出循環(huán),所有不會(huì)死循環(huán)。int mid = (left + right) / 2;if(A[mid] > key)//如果要求大于等于可以加上等于,也可以是check(A[mid])right = mid;//因?yàn)檎业氖谴笥趉ey的第一個(gè)元素,那么比A[mid]大的元素肯定不是第一個(gè)大于key的元素,因?yàn)锳[mid]已經(jīng)大于key了,所以把mid+1到后面的排除elseleft = mid + 1;//如果A[mid]小于key的話,那么A[mid]以及比A[mid]小的數(shù)都需要排除,因?yàn)樗麄兌夹∮趉ey。不可能是第一個(gè)大于等于key的元素, }

③查找小于等于/小于key的最后一個(gè)元素。

int left = 1, right = n; while(left < right) {//這里mid = (left + right + 1) / 2;//考慮如下一種情況,最后只剩下A[i],A[i + 1],如果不加1,那么mid = i,如果A[mid] < key,執(zhí)行更新操作后,left = mid,right = mid + 1,就會(huì)是死循環(huán)。//加上1后,mid = i + 1,如果A[mid] < key,那么left = right = mid + 1,跳出循環(huán)。如果A[mid] > key,left = mid = i,跳出循環(huán)。int mid = (left + right + 1) / 2;if(A[mid] < key)left = mid;//如果A[mid]小于key,說(shuō)明比A[mid]更小的數(shù)肯定不是小于key的最大的元素了,所以要排除mid之前的所有元素elseright = mid - 1;//如果A[mid]大于key,那么說(shuō)明A[mid]以及比A[mid]還要大的數(shù)都不可能小于key,所以排除A[mid]及其之后的元素。 }

STL二分模板
①lower_bound。找到大于等于某個(gè)數(shù)的第一個(gè)位置。
頭文件:algorithm。
對(duì)象:有序數(shù)組或容器。
示例代碼:

//數(shù)組 #include <algorithm> #include <iostream> using namespace std; int main() {int a[]={1,2,3,4,5,7,8,9,10};printf("%d",lower_bound(a,a+9,6)-a); return 0; }

也可以對(duì)不定長(zhǎng)數(shù)組vector進(jìn)行二分搜索。

#include<iostream> #include<algorithm> #include<vector> using namespace std;int main() {vector<int> A;A.push_back(1); A.push_back(2); A.push_back(3); A.push_back(4); A.push_back(5); A.push_back(7); A.push_back(8); A.push_back(9); int pos = lower_bound(A.begin() , A.end() , 6)-A.begin();//A.begin()代表的是A的迭代器cout << pos << endl;return 0; }

②upper_bound。找到大于某個(gè)數(shù)的位置。
基本用法和lower_bound一樣的。
STL中的這兩個(gè)二分函數(shù),是應(yīng)用比較廣泛的,理解他們的用處之后再去多加以應(yīng)用。
努力加油a啊,(o)/~

總結(jié)

以上是生活随笔為你收集整理的二分搜索(折半搜索),lower_bound,upper_bound的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。