线性搜索和二分搜索有啥区别?

Posted

技术标签:

【中文标题】线性搜索和二分搜索有啥区别?【英文标题】:What is the difference between Linear search and Binary search?线性搜索和二分搜索有什么区别? 【发布时间】:2010-10-16 13:27:17 【问题描述】:

线性搜索和二分搜索有什么区别?

【问题讨论】:

请阅读您的课程材料中的相应部分,希望这些部分是由您的教师选择和准备的。如果做不到这一点,一般的***、c2 或谷歌搜索可以回答这些问题。网上也有大量做得好的课程/讲义。 【参考方案1】:

linear search 向下查看列表,一次一个项目,没有跳跃。在复杂性方面,这是一个O(n) 搜索 - 搜索列表所花费的时间以与列表相同的速度变大。

binary search 是当您从排序列表的中间开始时,查看它是否大于或小于您要查找的值,这决定了该值是在排序列表的前半部分还是后半部分列表。跳到子列表的一半,然后再次比较等等。这几乎是人类通常在字典中查找单词的方式(尽管我们使用更好的启发式,显然 - 如果你正在寻找“猫”,你不会从“M”开始)。就复杂性而言,这是一个 O(log n) 搜索 - 搜索操作的数量比列表增长得更慢,因为每次操作都会将“搜索空间”减半。

例如,假设您在 A-Z 字母列表中查找 U(索引 0-25;我们正在查找索引 20 处的值)。

线性搜索会问:

list[0] == 'U'?没有。list[1] == 'U'?没有。list[2] == 'U'?没有。list[3] == 'U'?没有。list[4] == 'U'?没有。list[5] == 'U'?没有。 ... list[20] == 'U'?是的。完成了。

二分查找会问:

比较list[12]('M')和'U':更小,看更远。 (范围=13-25) 比较 list[19] ('T') 和 'U':更小,看得更远。 (范围=20-25) 比较list[22] ('W') 和'U':更大,看早些。 (范围=20-21) 比较 list[20] ('U') 和 'U':找到了!完成。

比较两者:

二分查找需要对输入数据进行排序;线性搜索不 二分搜索需要排序比较;线性搜索只需要相等比较 二分查找的复杂度为 O(log n);如前所述,线性搜索的复杂度为 O(n) 二分查找需要随机访问数据;线性搜索只需要顺序访问(这可能非常重要 - 这意味着线性搜索可以流式传输任意大小的数据)

【讨论】:

+1,虽然我不是特别喜欢你的字典类比。更好的类比是“在 1 到 100 场比赛之间猜我的数字”,回答是“你知道了”、“太高了”或“太低了”。 字典类比对我来说似乎很好,尽管它更适合插值搜索。 字典类比对我来说更好......如果我们考虑到数据库中的更低、等于或更大加索引 使用字典方法,关键是排序。因此,重要的是,您必须确保在开始二进制搜索之前对数据进行排序。如果不是,您将在没有找到价值的情况下跳遍海洋:)。如果你不标记已经尝试过的,这可能会变得更糟。所以总是做排序。一些基于 Java 的二进制搜索实现可以在这里找到digizol.com/2013/08/java-binary-search-recursive-testcases.html @lkamal:是的,输入数据排序的要求是我的第一个要点……【参考方案2】:

将其视为在电话簿中查找方式的两种不同方式。线性搜索从头开始,读取每个名称,直到找到所需内容。另一方面,二分搜索是当您打开书本(通常在中间),查看页面顶部的名称,然后确定您要查找的名称是大于还是小于您要查找的名称'正在寻找。如果您要查找的名称更大,那么您将继续以这种方式搜索书的上半部分。

【讨论】:

非常好的类比:用非常少的文字解释它!恭喜! 在 2016 年看这个,迄今为止最有效的答案! 令人难忘的好例子。非常感谢。 解释得很好,只是对简单的荣誉印象深刻!【参考方案3】:

线性搜索的工作原理是查看数据列表中的每个元素,直到找到目标或到达末尾。这导致在给定列表上的 O(n) 性能。 二进制搜索具有必须对数据进行排序的先决条件。我们可以利用这些信息来减少我们需要查看的项目数量以找到我们的目标。我们知道,如果我们查看数据中的一个随机项目(假设是中间项目)并且该项目大于我们的目标,那么该项目右侧的所有项目也将大于我们的目标。这意味着我们只需要查看数据的左侧部分。基本上,每次我们搜索目标并错过,我们可以消除一半的剩余项目。这给了我们一个很好的 O(log n) 时间复杂度。

请记住,排序数据,即使使用最有效的算法,也总是比线性搜索慢(最快的排序算法是 O(n * log n))。因此,您永远不应该仅仅为了稍后执行单个二进制搜索而对数据进行排序。但是,如果您将执行许多搜索(例如至少 O(log n) 次搜索),则可能值得对数据进行排序,以便您可以执行二进制搜索。在这种情况下,您还可以考虑其他数据结构,例如哈希表。

【讨论】:

【参考方案4】:

线性搜索从值列表的开头开始,并按顺序逐一检查您要查找的结果。

二分查找从已排序数组的中间开始,并确定您要查找的值在哪一侧(如果有)。然后以相同的方式再次搜索数组的“一半”,每次将结果分成两半。

【讨论】:

【参考方案5】:

请务必仔细考虑更快的二进制搜索的胜利是否值得保持列表排序的成本(以便能够使用二进制搜索)。 IE。如果您有很多插入/删除操作并且只是偶尔进行搜索,那么二进制搜索总体上可能比线性搜索慢。

【讨论】:

【参考方案6】:

试试这个:选择一个随机的名字“姓氏,名字”,然后在你的电话簿中查找。

第一次:从书的开头开始,读名字直到找到它,否则按字母顺序找到它出现的地方并注意它不在那里。

第二次:在中途点打开书,看页面。问问自己,这个人应该在左边还是右边。无论是哪一个,取那个 1/2 并找到它的中间。重复此过程,直到找到条目所在的页面,然后将相同的过程应用于列,或者像以前一样沿页面上的名称线性搜索。

为这两种方法计时并报告!

[如果你只有一个名字列表,而不是排序的话,还要考虑哪种方法更好......]

【讨论】:

【参考方案7】:

线性搜索也称为顺序搜索,从头开始按顺序查看每个元素,以查看所需元素是否存在于数据结构中。当数据量较小时,这种搜索速度很快。它很容易,但所需的工作与要搜索的数据量成正比。如果所需元素不存在,则将元素数量加倍将使搜索时间加倍。

二分查找对于较大的数组是有效的。在此我们检查中间元素。如果该值大于我们要查找的值,则查看前半部分;否则,查看后半部分。重复此操作,直到找到所需的项目。必须对表进行排序以进行二分查找。它在每次迭代时消除了一半的数据。它是对数的。

如果我们要搜索 1000 个元素,二分搜索大约需要 10 步,线性搜索需要 1000 步。

【讨论】:

@Prabu - 不正确 - 最好的情况是 1,最坏的情况是 1000,平均为 500。【参考方案8】:

二分查找的运行时间为 O(logn),而线性查找的运行时间为 O(n),因此二分查找的性能更好

【讨论】:

【参考方案9】:

线性搜索查找一个列表,一次一个项目,不跳转。在复杂性方面,这是一个 O(n) 搜索 - 搜索列表所花费的时间以与列表相同的速度变大。

二分查找是从已排序列表的中间开始,查看它是否大于或小于您要查找的值,这决定了该值是在列表的前半部分还是后半部分.跳到子列表的一半,然后再次比较等等。这几乎是人类通常在字典中查找单词的方式(尽管我们使用更好的启发式,显然 - 如果你正在寻找“猫”,你不会从“M”开始)。就复杂性而言,这是一个 O(log n) 搜索 - 搜索操作的数量比列表增长得更慢,因为每次操作都将“搜索空间”减半。

【讨论】:

【参考方案10】:

Linear Search 浏览项目,直到找到搜索到的值。

效率:O(n)

示例 Python 代码:

test_list = [1, 3, 9, 11, 15, 19, 29]
test_val1 = 25
test_val2 = 15

def linear_search(input_array, search_value):
    index = 0
    while (index < len(input_array)) and (input_array[index] < search_value):
        index += 1
    if index >= len(input_array) or input_array[index] != search_value:
        return -1

    return index


print linear_search(test_list, test_val1)
print linear_search(test_list, test_val2)

Binary Search 查找数组的中间元素。检查中间值是否大于或小于搜索值。如果它更小,它会获取数组的左侧并找到该部分的中间元素。如果它更大,则获取数组的正确部分。它循环操作,直到找到搜索到的值。或者如果数组中没有值则结束搜索。

效率:O(logn)

示例 Python 代码:

test_list = [1, 3, 9, 11, 15, 19, 29]
test_val1 = 25
test_val2 = 15

def binary_search(input_array, value):
    low = 0
    high = len(input_array) - 1
    while low <= high:
        mid = (low + high) / 2
        if input_array[mid] == value:
            return mid
        elif input_array[mid] < value:
            low = mid + 1
        else:
            high = mid - 1

    return -1


print binary_search(test_list, test_val1)
print binary_search(test_list, test_val2)

您还可以在此处查看有关线性和二进制搜索的可视化信息:https://www.cs.usfca.edu/~galles/visualization/Search.html

【讨论】:

【参考方案11】:

为了清楚了解,请看一下我的codepen实现https://codepen.io/serdarsenay/pen/XELWqN

最大的区别是在应用二分搜索之前需要对样本进行排序,因此对于大多数“正常大小”(有争议的)样本,使用线性搜索算法搜索会更快。

这里是javascript代码,html和css以及完整的运行示例请参考上面的codepen链接。

var unsortedhaystack = [];
var haystack = [];
function init() 
  unsortedhaystack = document.getElementById("haystack").value.split(' ');

function sortHaystack() 
  var t = timer('sort benchmark');
  haystack = unsortedhaystack.sort();
  t.stop();


var timer = function(name) 
    var start = new Date();
    return 
        stop: function() 
            var end  = new Date();
            var time = end.getTime() - start.getTime();
            console.log('Timer:', name, 'finished in', time, 'ms');
        
    
;

function lineerSearch() 
  init();
  var t = timer('lineerSearch benchmark');
  var input = this.event.target.value;
  for(var i = 0;i<unsortedhaystack.length - 1;i++) 
    if (unsortedhaystack[i] === input) 
      document.getElementById('result').innerHTML = 'result is... "' + unsortedhaystack[i] + '", on index: ' + i + ' of the unsorted array. Found' + ' within ' + i + ' iterations';
      console.log(document.getElementById('result').innerHTML);
      t.stop(); 
      return unsortedhaystack[i]; 
    
  


function binarySearch () 
  init();
  sortHaystack();
  var t = timer('binarySearch benchmark');
  var firstIndex = 0;
  var lastIndex = haystack.length-1;
  var input = this.event.target.value;

  //currently point in the half of the array
  var currentIndex = (haystack.length-1)/2 | 0;
  var iterations = 0;

  while (firstIndex <= lastIndex) 
    currentIndex = (firstIndex + lastIndex)/2 | 0;
    iterations++;
    if (haystack[currentIndex]  < input) 
      firstIndex = currentIndex + 1;
      //console.log(currentIndex + " added, fI:"+firstIndex+", lI: "+lastIndex);
     else if (haystack[currentIndex] > input) 
      lastIndex = currentIndex - 1;
      //console.log(currentIndex + " substracted, fI:"+firstIndex+", lI: "+lastIndex);
     else 
      document.getElementById('result').innerHTML = 'result is... "' + haystack[currentIndex] + '", on index: ' + currentIndex + ' of the sorted array. Found' + ' within ' + iterations + ' iterations';
      console.log(document.getElementById('result').innerHTML);
      t.stop(); 
      return true;
    
  

【讨论】:

以上是关于线性搜索和二分搜索有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的线性搜索比我在 Python3 中的二分搜索运行得更快?

为啥我们不能在跳转搜索中使用二分搜索而不是线性搜索?

二分搜索与线性搜索奇怪的时间

Python算法-冒泡排序、线性和二分搜索

数据结构之PHP二分搜索树

线性和二进制搜索