2010-05-29 60 views
0

如果二分查找需要先手动排序数组,那么为什么下面的代码有效?Array.BinarySearch找不到使用IComparable的项目

string[] strings = new[] { "z", "a", "y", "e", "v", "u" }; 
int pos = Array.BinarySearch(strings, "Y", StringComparer.OrdinalIgnoreCase);   
Console.WriteLine(pos); 

为什么此代码返回-1?

public class Person : IComparable<Person> { 

    public string Name { get; set; } 
    public int Age { get; set; } 


    public int CompareTo(Person other) { 
     return this.Age.CompareTo(other.Age) + this.Name.CompareTo(other.Name); 
    } 
} 
var people = new[] { 

       new Person { Age=5,Name="Tom"}, 
       new Person { Age=1,Name="Tom"}, 
       new Person { Age=2,Name="Tom"}, 
       new Person { Age=1,Name="John"}, 
       new Person { Age=1,Name="Bob"}, 
      }; 


      var s = new Person { Age = 1, Name = "Tom" }; 

      // returns -1 
      Console.WriteLine(
       Array.BinarySearch(people, s) 
      ); 
+1

第一部分很有可能工作,因为数组中有偶数个元素。二进制搜索尝试检查“中间”元素。在这种情况下,中间有两个元素,所以它可能选择最左边的元素,它恰好是Y,并返回正确的位置(2)。在Y后放一个字母(Z除外),你会得到一个负面结果。 – R0MANARMY 2010-05-29 04:26:51

回答

2

如果违反the pre-condition(“数组的元素必须已经在增加值,根据比较器定义的排序顺序进行排序;否则,结果可能是不正确”),您会导致不确定的行为,有时会包括,“嘿,它看起来很有效。”在免费和许多其他编程错误后使用也是如此。

我并不感到惊讶,它对输入有效,因为“y”和“e”都是相同的中间元素。它使用较低的中间,“y”,它匹配。如果你尝试:

string[] strings = new[] { "z", "a", "y", "e", "e", "v", "u" }; 

你会发现这是行不通的。请注意,有几个元素。目标在中间之前,而应该在之后。