(Translated by https://www.hiragana.jp/)
二分搜尋演算法 - 维基百科,自由的百科全书

ふんさがせひろ演算えんざんほう

搜索そうさく算法さんぽう

这是ほん页的いち历史版本はんぽんゆかりTang891228とめげん | 贡献ざい2019ねん11月28にち (よん) 09:33 地區ちく處理しょり编辑。这可能かのうとうぜん版本はんぽん存在そんざい巨大きょだいてき异。

ざい计算つくえ科学かがくなか二分にぶん查找算法さんぽう英語えいごbinary search algorithm),也称折半せっぱん搜索そうさく算法さんぽう英語えいごhalf-interval search algorithm[1]对数搜索そうさく算法さんぽう英語えいごlogarithmic search algorithm[2]いち种在ゆうじょすうちゅう查找ぼういち特定とくてい元素げんそてき搜索そうさく算法さんぽう搜索そうさく过程从数组的ちゅう元素げんそ开始,如果ちゅう元素げんそただしこうよう查找てき元素げんそ,则搜索そうさく过程结束;如果ぼう一特定元素大于或者小于中间元素,则在すう组大于或しょう于中间元素的すてき一半いっぱんちゅう查找,而且跟开始一样从中间元素开始比较。如果ざいぼう一步骤数组为空,则代表だいひょう找不いた。这种搜索そうさく算法さんぽうごと一次比较都使搜索范围缩小一半。

ふんさがせひろ演算えんざんほう
がい
類別るいべつ搜索そうさく算法さんぽう
資料しりょう結構けっこうかず
复杂
平均へいきん時間じかん複雜ふくざつ
さい坏时间复杂度
さい优时间复杂度
空間くうかん複雜ふくざつ迭代:
递归:
(无调用しょうじょ
さいけいかいYes
あい关变量的りょうてきてい

二分查找算法在情况下的复杂度是对数时间,进行つぎ操作そうさざい此处すう组的元素げんそ数量すうりょうこれだいO记号これ对数)。二分查找算法使用常数空间,无论对任なん大小だいしょうてき输入すうすえ算法さんぽう使用しようてきそら间都いち样的。じょ输入すうすえ数量すうりょう很少,いや则二分查找算法比线性搜索更快,ただしすう组必须事さきはいじょつきかん特定とくていてき、为了快速かいそく搜索そうさく而设计的すうすえ结构さら有效ゆうこう哈希ひょう),二分查找算法应用面更广。

二分查找算法有许多中变种。分散ぶんさん层叠えいfractional casacading以提ますざい个数组中对同いち个数值的搜索そうさく分散ぶんさん层叠有效ゆうこうてきかい决了计算几何がくかず其他领域てき许多搜索そうさく问题。指数しすう搜索そうさくえいExponential Searchはた二分查找算法拓宽到无边界的列表。また搜索そうさくB树数すえ结构就是もと二分にぶん查找算法さんぽうてき

演算えんざんほう

二分搜索只对有序数组有效。二分搜索先比较数组中位元素和目标值。如果标值与中位ちゅうい元素げんそ相等そうとう,则返かい其在すう组中てき位置いち;如果标值しょう于中元素げんそ,则搜索そうさく继续ざい前半ぜんはん部分ぶぶんてきすう组中进行。如果标值だい于中元素げんそ,则搜索そうさく继续ざいすう组上部分ぶぶん进行。よし此,算法さんぽう每次まいじ排除はいじょ掉至しょう一半的待查数组。

きゅういち包含ほうがん たい值元素的すてき陣列じんれつ ある記錄きろく 使つかい ,以及目標もくひょう かえゆうしたれつようらいさがせひろ ざい ちゅう位置いちてきほどしき[3]

  1. れい ため  ため 
  2. 如果 のりさがせひろ失敗しっぱいつげおわり
  3. れい 中間なかま元素げんそため 。(具体ぐたい实现ちゅう,为防止ぼうし算術さんじゅつ溢出一般いっぱんさいよう 代替だいたい。)
  4. 如果 れい ため なみかいいた驟二。
  5. 如果 れい ため なみかいいた驟二。
  6. とう さがせひろ結束けっそくかいでん 

這個たたみだい驟會持續じぞく透過とうか兩個りゃんこ變數へんすうつい搜索そうさくてきあたりかいゆう些實ぎわ應用おうようかいざい演算えんざん法的ほうてき最後さいごにゅう相等そうとう比較ひかくゆずる比較ひかく迴圈さらかいただし平均へいきん而言かい一層いっそうたたみだい[4]

だい致匹はい

以上いじょうほどじょただ適用てきよう完全かんぜんひきはい,也就ひろいち目標もくひょう值的位置いちいんためゆうじょ陣列じんれつてき順序じゅんじょせいはた二分搜索算法擴展到能適用大致匹配並不是很重要。舉例らいせつ,二分搜索算法可以用來計算一個賦值的はいめいあるしょう它更しょうてき元素げんそてき數量すうりょう)、ぜんしたいち最小さいしょう元素げんそ)、後繼こうけいしたいち最大さいだい元素げんそ)以及最近さいきんさがせひろ兩個りゃんこ值之あいだてき元素げんそすう目的もくてき範圍はんい查詢えいRange query (data structures)以藉よし兩個りゃんこはいめい查詢またたたえ秩查詢らい執行しっこう[5]

  • はいめい查詢使用しよう調整ちょうせいばんてきふん搜索そうさくらい執行しっこう。藉由ざい成功せいこうてき搜索そうさくかいでん ,以及ざい失敗しっぱいてき搜索そうさくかいでん ,就會而代かいでんりょうおこり目標もくひょう值小てき元素げんそすうもく[5]
  • ぜん趨和後繼こうけい查詢以藉よしはいめい查詢らい執行しっこう。一旦知道目標值的排名,其前趨就かい於其はいめい位置いちてき元素げんそ,あるものはいめい位置いちてきじょういち元素げんそいんため它是しょう目標もくひょう值的最大さいだい元素げんそ)。其後繼こうけい陣列じんれつちゅうてきしたいち元素げんそある陣列じんれつちゅうてきぜん趨的いち元素げんそ[6]目標もくひょう值的最近さいきん可能かのうぜん趨或後繼こうけいけつ於何しゃ較為接近せっきん
  • 範圍はんい查詢也是直接ちょくせつりょうとうてき。一旦知道兩個值的排名,しょう於第一個值且小於第二個值的元素數量就會是兩者排名的差。這個值可以根據こんきょ範圍はんいてき端點たんてんさんざい範圍はんい內,ある陣列じんれつ包含ほうがん其端てんてき對應たいおうかぎらい增加ぞうかある減少げんしょう1[7]

复杂分析ぶんせき

时间复杂
折半せっぱん搜索そうさく每次まいじ搜索そうさく区域くいき减少一半いっぱん,时间复杂 。(n代表だいひょう集合しゅうごう中元ちゅうげん素的すてき个数)
そら间复杂度
 。虽以递归形式けいしきてい义,ただしこれ递归あらためうつし为循环。

应用

じょ直接ちょくせつざい一个数组中查找元素外,可用かようざい插入そうにゅうはいじょなか

しめせれいだい

C 版本はんぽん- 递归

int binary_search(const int arr[], int start, int end, int khey) {
	if (start > end)
		return -1;

	int mid = start + (end - start) / 2;    //直接ちょくせつ平均へいきん可能かのうかい溢位,所以ゆえんよう此算ほう
	if (arr[mid] > khey)
		return binary_search(arr, start, mid - 1, khey);
	else if (arr[mid] < khey)
		return binary_search(arr, mid + 1, end, khey);
	else
	    return mid;        //最後さいごけんはか相等そうとういんため多數たすうさがせひろ狀況じょうきょうだい於要就小於
}

C 版本はんぽん- while 循环

int binary_search(const int arr[], int start, int end, int key) {
    int ret = -1;       // 搜索そうさくいたかずすえかえしかい-1
    
	int mid;
	while (start <= end) {
		mid = start + (end - start) / 2; //直接ちょくせつ平均へいきん可能かのうかい溢位,所以ゆえんよう此算ほう
		if (arr[mid] < key)
			start = mid + 1;
		else if (arr[mid] > key)
			end = mid - 1;
		else {            // 最後さいごけんはか相等そうとういんため多數たすうさがせひろ狀況じょうきょうだい於要就小於
			ret = mid;  
            break;
        }
	}
	
	return ret;     // 单一出口でぐち
}

javascript 版本はんぽん

var arr = [1, 3, 5, 7, 9, 10, 11, 12, 14, 15, 19, 20];
function binarySearch (arr, val) {
    var low = 0,
        high = arr.length - 1;
    while (low <= high) {
        var mid = parseInt( (low + high) / 2 );
        if (val == arr[mid]) {
            return mid;
        }else if (val > arr[mid]) {
            low = mid + 1;
        }else if (val < arr[mid]) {
            high = mid - 1;
        }
    }
    return -1;
};  
console.log( binarySearch(arr, 4) );

Python3 版本はんぽん while 循环

def binary_search(arr, left, right, hkey):
    while left <= right:
        mid = left + (right - left) // 2
        if arr[mid] == hkey:
            return mid
        elif arr[mid] < hkey:
            left = mid + 1
        elif arr[mid] > hkey:
            right = mid - 1
    return -1

Python3 版本はんぽん 递归

def binary_search(arr, start, end, hkey):
	if start > end:
		return -1
	mid = start + (end - start) / 2
	if arr[mid] > hkey:
		return binary_search(arr, start, mid - 1, hkey)
	if arr[mid] < hkey:
		return binary_search(arr, mid + 1, end, hkey)
	return mid


C# 版本はんぽん

static int binary_search(int[] arr, int start, int end, int khey)
{
    int mid;
    while (start <= end)
    {
        mid = (start + end) / 2;
        if (arr[mid] < khey)
            start = mid + 1;
        else if (arr[mid] > khey)
            end = mid - 1;
        else
            return mid; 
    }
    return -1;
}

Swift 版本はんぽん

import Foundation
/// 二分にぶん搜索そうさく完全かんぜんひきはい
///
/// - Parameters:
///   - arr: ゆうじょすう
///   - start: おこりはじめ位置いち
///   - end: 结束てん
///   - khey: とくてん标值
/// - Returns: かえしかい查找结果
func binarySearch(arr: [Int], start: Int, end: Int, khey: Int) -> Int? {
    if start > end {
        return nil
    }
    let mid = start + (end - start) / 2
    if arr[mid] > khey {
        return binarySearch(arr: arr, start: start, end: mid - 1, khey: khey)
    } else if arr[mid] < khey {
        return binarySearch(arr: arr, start: mid + 1, end: end, khey: khey)
    } else {
        return mid
    }
}

golang 递归版本はんぽん

func binary_search(arr []int, low, high, hkey int) int {
	if low > high {
		return -1
	}
	mid := low + (high-low)/2

	if arr[mid] > hkey {
		return binary_search(arr, low, mid-1, hkey)
	} else if arr[mid] < hkey {
		return binary_search(arr, mid+1, high, hkey)
	}

	return mid
}

golang 递归版本はんぽん

func binarySearch(arr []int, low, high, hkey int) int {
	for low <= high {
		mid := low + (high-low)/2
		if arr[mid] == hkey {
			return mid
		} else if hkey < arr[mid] {
			high = mid - 1
		} else if hkey > arr[mid] {
			low = mid + 1
		}
	}
	return -1
}

Java 递归

public static int binarySearch(int[] arr, int start, int end, int hkey){
    if (start > end)
        return -1;

    int mid = start + (end - start)/2;    //防止ぼうし溢位
    if (arr[mid] > hkey)
        return binarySearch(arr, start, mid - 1, hkey);
    if (arr[mid] < hkey)
        return binarySearch(arr, mid + 1, end, hkey);
    return mid;  

}

Java while 循环

public static int binarySearch(int[] arr, int start, int end, int hkey){
    int result = -1;

    while (start <= end){
        int mid = start + (end - start)/2;    //防止ぼうし溢位
        if (arr[mid] > hkey)
            end = mid - 1;
        else if (arr[mid] < hkey)
            start = mid + 1;
        else {
            result = mid ;  
            break;
        }
    }

    return result;

}

历史

ざい1946ねん约翰·莫奇利きりざい尔学いん讲座えいMoore School Lecturesうえだいいち提出ていしゅつふん搜索そうさくてき概念がいねん[8]1957ねんかど·がわとくえいWilliam Wesley Peterson发表りょうだい一个应用插值搜索的算法[8][9]ざい此时,まい个发ひょうてき二分搜索算法只对长度为2てき幂减いちてきすう组有よう[10]ちょくいた1960ねんとくさとかつ·とおる·莱默发表りょう一个对于所有长度的数组都适用的算法[11]。1962ねん,赫尔曼·はく滕布鲁赫发表りょういち个用ALGOL 60うつしてきふん搜索そうさくはた判断はんだん相等そうとうてき骤放いた算法さんぽう末尾まつび。虽然しょう平均へいきん迭代次数じすう增加ぞうかいちただし每次まいじ迭代ちゅうてき较次すう减少りょう1[12]ひとしふん搜索そうさく则是ふみたんふつ大學だいがくてきA. K.钱德ひしげざい1971ねん发明てき[8]。1986ねんはく纳德·查泽尔れつおくあま达斯·よしともみ引入りょう分散ぶんさん层叠らいかい计算几何ちゅう大量たいりょう存在そんざいてき搜索そうさく问题[13][14][15]

实现ちゅうてき问题

つきかん二分查找的基本思想相对简单,ただし细节以令じんなん以招 ... — 高德こうとく[2]

とう乔恩·ほんとくはた二分搜索问题布置给专业编程课的学生时,ひゃくふん90てき学生がくせいざいはな费数しょう时后还是无法给出せい确的解答かいとうしゅ要因よういん为这些错误程じょざいめん对边かい值的时候无法运行,あるかえしかい错误结果。[16]1988ねん开展てきいち研究けんきゅう显示,20ほん教科きょうか书里ただゆう5ほんせい确实现了ふん搜索そうさく[17]仅如此,ほんとく自己じこ1986ねん出版しゅっぱんてき《编程たま玑》一书中的二分搜索算法存在整数溢出的问题,十多年来无人发现。Java语言てき库所实现てき二分搜索算法中同样的溢出问题存在了九年多才被修复。[18]

参考さんこう

  1. ^ Willams, Jr., Louis F. A modification to the half-interval search (binary search) method. Proceedings of the 14th ACM Southeast Conference: 95–101. 1975. doi:10.1145/503561.503582. 
  2. ^ 2.0 2.1 Knuth 1998,§6.2.1 ("Searching an ordered table"), subsection "Binary search".
  3. ^ Knuth 1998,§6.2.1 ("Searching an ordered table"), subsection "Algorithm B".
  4. ^ Bottenbruch, Hermann. Structure and Use of ALGOL 60. Journal of the ACM. 1962, 9 (2): 161–211.  Procedure is described at p. 214 (§43), titled "Program for Binary Search".
  5. ^ 5.0 5.1 Sedgewick & Wayne 2011,§3.1, subsection "Rank and selection".
  6. ^ Goldman & Goldman 2008だい461–463ぺーじ.
  7. ^ Sedgewick & Wayne 2011,§3.1, subsection "Range queries".
  8. ^ 8.0 8.1 8.2 Knuth 1998,§6.2.1 ("Searching an ordered table"), subsection "History and bibliography".
  9. ^ Peterson, William Wesley. Addressing for random-access storage. IBM Journal of Research and Development. 1957, 1 (2): 130–146. doi:10.1147/rd.12.0130. 
  10. ^ "2n−1". OEIS A000225 互联网档あんてきそんそん档日8 June 2016.. Retrieved 7 May 2016.
  11. ^ Lehmer, Derrick. Teaching combinatorial tricks to a computer. Proceedings of Symposia in Applied Mathematics 10. 1960: 180–181. doi:10.1090/psapm/010.  さんすう|journal=あずかばん{{cite conference}}ひきはいけん议改よう{{cite journal}}ある|book-title=) (帮助)
  12. ^ Bottenbruch, Hermann. Structure and use of ALGOL 60. Journal of the ACM. 1 April 1962, 9 (2): 161–221. ISSN 0004-5411. doi:10.1145/321119.321120.  Procedure is described at p. 214 (§43), titled "Program for Binary Search".
  13. ^ Chazelle, Bernard; Liu, Ding. Lower bounds for intersection searching and fractional cascading in higher dimension. 33rd ACM Symposium on Theory of Computing. ACM: 322–329. 6 July 2001 [30 June 2018]. ISBN 978-1-58113-349-3. doi:10.1145/380752.380818. 
  14. ^ Chazelle, Bernard; Guibas, Leonidas J. Fractional cascading: I. A data structuring technique (PDF). Algorithmica. 1986, 1 (1-4): 133–162. CiteSeerX 10.1.1.117.8349 . doi:10.1007/BF01840440. 
  15. ^ Chazelle, Bernard; Guibas, Leonidas J., Fractional cascading: II. Applications (PDF), Algorithmica, 1986, 1 (1-4): 163–191, doi:10.1007/BF01840441 
  16. ^ Bentley 2000,§4.1 ("The Challenge of Binary Search").
  17. ^ Pattis, Richard E. Textbook errors in binary searching. SIGCSE Bulletin. 1988, 20: 190–194. doi:10.1145/52965.53012. 
  18. ^ Bloch, Joshua. Extra, extra – read all about it: nearly all binary searches and mergesorts are broken. Google Research Blog. 2 June 2006 [21 April 2016]. (原始げんし内容ないようそん档于1 April 2016).  やめゆるがせりゃく未知みちさんすう|df= (帮助)

外部がいぶ链接