lower_bound()函數(shù)和upper_bound()函數(shù)生巡,以及二分查找

參考C++ Refference:
http://www.cplusplus.com/reference/algorithm/lower_bound/
本文前面是函數(shù)原型盒揉, 后面是怎么用

lower_bound():

默認版本

template <class ForwardIterator, class T>
 ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last,
                               const T& val);

自定義比較函數(shù)版

template <class ForwardIterator, class T, class Compare>
ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last,
                               const T& val, Compare comp);

第一個first參數(shù)是一段連續(xù)空間的首地址摹迷,last是連續(xù)空間末端的地址,val是要查找的值。調(diào)用lower_bound()的前提是這段連續(xù)的空間里的元素是有序(遞增)的胎许。
然后lower_bound()的返回值是第一個大于等于val的值的地址奈辰,用這個地址減去first栏妖,得到的就是第一個大于等于val的值的下標

在自定義版本里有一個comp參數(shù),它的用處在于奖恰,當你要查找的不是基本數(shù)據(jù)類型吊趾,而是自己定義的struct時就需要自己定義一下,怎么比較兩個struct的大小瑟啃。

用法示例

默認版本

#include <iostream>
#include <algorithm>
using namespace std;
int main(int argc, char *argv[]){
    int a[] = {1, 3, 5, 7, 9};
    cout << (lower_bound(a, a + 5, 1) - a) << endl;
    // 第一個大于等于1的元素是1论泛,下標是0
    cout << (lower_bound(a, a + 5, 2) - a) << endl;
    // 第一個大于等于2的元素是3,下標是1
    cout << (lower_bound(a, a + 5, 8) - a) << endl;
    // 第一個大于等于8的元素是9蛹屿,下標是4
    cout << (lower_bound(a, a + 5, 100) - a) << endl;
    // 最大的元素也不比100大屁奏,故返回值是last,再減a也就是5
}

自定義版本

#include <iostream>
#include <algorithm>
using namespace std;
struct point{
    point(){

    }
    point(int _x, int _y){
        x = _x;
        y = _y;
    }
    int x;
    int y;
};

bool cmp(point a, point b){
    return a.x < b.x;
}
int main(int argc, char *argv[]){
    point a[5];

    a[0].x = 1;
    a[0].y = 100;

    a[1].x = 100;
    a[1].y = 1;

    a[2].x = 30;
    a[2].y = 50;

    a[3].x = 25;
    a[3].y = 120;

    a[4].x = 301;
    a[4].y = 103;
    // 隨便賦值
    sort(a, a + 5, cmp);
    // 先排序
    for (int i = 0; i < 5; i++){
        printf("a[%d].x = %d, a[%d].y = %d\n", i, a[i].x, i, a[i].y);
    }
    // 輸出會發(fā)現(xiàn)他們按照x從小到大排序了
    cout << (lower_bound(a, a + 5, point(1, 1000), cmp) - a) << endl;
    // 第一個x值大于1的元素是(1, 100)這個元素错负,它的下標為0
    cout << (lower_bound(a, a + 5, point(101, 1000), cmp) - a) << endl;
    // 第一個x值大于101的元素是(301, 103)這個元素坟瓢,它的下標為4
    cout << (lower_bound(a, a + 5, point(1000, 1000), cmp) - a) << endl;
    // 因為找不到所以返回a + 5,再減a就是5
    
}

upper_bound()

用法跟lower_bound()一樣犹撒,只不過它返回的是第一個大于x的值的地址折联, 而lower_bound()是返回第一個大于等于x的值的地址,> 和 >= 是二者的區(qū)別

示例

#include <iostream>
#include <algorithm>
using namespace std;
int main(int argc, char *argv[]){
    int a[] = {1, 3, 5, 7, 9};
    cout << (upper_bound(a, a + 5, 1) - a) << endl;
    // 第一個大于1的元素是3油航,下標是1
    cout << (upper_bound(a, a + 5, 2) - a) << endl;
    // 第一個大于2的元素是3崭庸,下標是1
    cout << (upper_bound(a, a + 5, 7) - a) << endl;
    // 第一個大于7的元素是9,下標是4
    cout << (upper_bound(a, a + 5, 100) - a) << endl;
    // 最大的元素也不比100大谊囚,故返回值是last怕享,再減a也就是5
}

如果要求第一個小于x的數(shù),或者第一個小于等于x的數(shù)怎么辦呢镰踏?

還是用上面兩個函數(shù)就可以了

查找第一個小于等于x的數(shù)(注:這里的意思為小于x的數(shù)里最大的那個)

算法:upper_bound()的返回值 - 1函筋,就是要查找的地址

比如數(shù)組是int a[] = {1, 3, 5, 7, 9}要查找的數(shù)x是3
用upper_bound()找到的是第一個大于3的數(shù)對吧,它的返回值是5的地址奠伪,把返回結(jié)果再減1就好了跌帐,就是3的地址了。第一個小于等于3的元素是3绊率,沒錯吧谨敛!

這是剛好數(shù)組里有x的情況,那如果沒有呢滤否?比如要查找的元素是4脸狸,那upper_bound()的返回值是5的地址,再減1,就是3的地址了炊甲,第一個小于等于
4的元素是3泥彤,沒錯吧!

那如果查的元素比第一個元素還要小呢卿啡,比如-1吟吝,那upper_bound()的返回值是a,再減1就是a的前一個單元了颈娜。所以這里得特判了剑逃,要不然段錯誤了。

查找第一個小于x的數(shù)

算法:lower_bound()的返回值 - 1官辽,就是要查找的地址

還是用上面的數(shù)據(jù)為例子
要查找的元素為7炕贵,lower_bound的返回值為7的地址,再減一就是5的地址野崇,第一個小于7的元素是5,沒錯亩钟。
要查找8呢乓梨,lower_bound()返回的是9的地址,再減一就是7清酥,沒錯扶镀。
查找-1,lower_bound()返回1的地址焰轻,也就是a臭觉,再減一為a的前一個單元,會越界辱志,需要特判蝠筑。

附:自己寫的lower_bound版本

注意:我的下標從1開始,然后一定要注意揩懒,初始l = 1, r = n + 1什乙,也就是說[l, r)是個左閉右開區(qū)間,r是沒有訪問元素的
ll是long long已球,代碼前面有typedef臣镣,競賽寫習慣了

ll lower_bound(ll *a, ll x, ll n){
    ll l = 1, r = n + 1;
    while (l < r){
        ll mid = (l + r) / 2;
        if (x > a[mid]){
            l = mid + 1;
        }
        else if (x < a[mid]){
            r = mid;
        }
        else{
            return mid;
        }
    }
    return l;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市智亮,隨后出現(xiàn)的幾起案子忆某,更是在濱河造成了極大的恐慌,老刑警劉巖阔蛉,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件弃舒,死亡現(xiàn)場離奇詭異,居然都是意外死亡馍忽,警方通過查閱死者的電腦和手機棒坏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進店門燕差,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人坝冕,你說我怎么就攤上這事徒探。” “怎么了喂窟?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵测暗,是天一觀的道長。 經(jīng)常有香客問我磨澡,道長碗啄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任稳摄,我火速辦了婚禮稚字,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘厦酬。我一直安慰自己胆描,他們只是感情好,可當我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布仗阅。 她就那樣靜靜地躺著昌讲,像睡著了一般。 火紅的嫁衣襯著肌膚如雪减噪。 梳的紋絲不亂的頭發(fā)上短绸,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天,我揣著相機與錄音筹裕,去河邊找鬼醋闭。 笑死,一個胖子當著我的面吹牛饶碘,可吹牛的內(nèi)容都是我干的目尖。 我是一名探鬼主播,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼扎运,長吁一口氣:“原來是場噩夢啊……” “哼瑟曲!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起豪治,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤洞拨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后负拟,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體烦衣,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了花吟。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秸歧。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖衅澈,靈堂內(nèi)的尸體忽然破棺而出键菱,到底是詐尸還是另有隱情,我是刑警寧澤今布,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布经备,位于F島的核電站,受9級特大地震影響部默,放射性物質(zhì)發(fā)生泄漏侵蒙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一傅蹂、第九天 我趴在偏房一處隱蔽的房頂上張望纷闺。 院中可真熱鬧,春花似錦份蝴、人聲如沸急但。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至戒努,卻和暖如春请敦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背储玫。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工侍筛, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人撒穷。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓匣椰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親端礼。 傳聞我的和親對象是個殘疾皇子禽笑,可洞房花燭夜當晚...
    茶點故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容

  • ORA-00001: 違反唯一約束條件 (.) 錯誤說明:當在唯一索引所對應(yīng)的列上鍵入重復(fù)值時,會觸發(fā)此異常蛤奥。 O...
    我想起個好名字閱讀 5,256評論 0 9
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,511評論 1 51
  • HTML 5 HTML5概述 因特網(wǎng)上的信息是以網(wǎng)頁的形式展示給用戶的佳镜,因此網(wǎng)頁是網(wǎng)絡(luò)信息傳遞的載體。網(wǎng)頁文件是用...
    阿啊阿吖丁閱讀 3,871評論 0 0
  • 官網(wǎng) 中文版本 好的網(wǎng)站 Content-type: text/htmlBASH Section: User ...
    不排版閱讀 4,370評論 0 5
  • 一切都是錢惹的禍凡桥。 錢是人心靠近之本蟀伸,也是人心背離之源,金錢可以影響人的心情,左右人的運勢啊掏。有錢則奉趨者如林蠢络,沒錢...
    臭小媽媽閱讀 166評論 0 0