Пожалуйста, помогите мне разобраться в этом методе "BinarySearchCountAll" в моей книге

В моей книге " Поваренная книга C# 3.0" О'Рейли есть следующий пример, который меня смущает. (Точная транскрипция ниже.)

// Count the number of times an item appears in the sort List<T>.
public static int BinarySearchCountAll<T>(this List<T> myList, T searchValue)
{
   // Search for the first item.
   int center = myList.BinarySearch(searchValue);
   int left = center;
   while (left < 0 && myList[left-1].Equals(searchValue))
   {
     left -= 1;
   }
   int right = center;
   while (right < (myList.Count - 1) && myList[right+1].Equals(searchValue))
   {
     right += 1;
   }    
   return (right - left) + 1;
}

В частности, я запутался, начиная с

int center = myList.BinarySearch(searchValue);
int left = center;
while (left < 0 && myList[left-1].Equals(searchValue))

сниппет. Согласно документации по методу BinarySearch, left это индекс элемента. Так как же состояние

left < 0 && myList[left-1].Equals(searchValue)

в while цикл имеет смысл? Из-за короткого замыкания, если left < 0 тогда правая сторона myList[left-1].Equals(searchValue) оценивается, но myList[left-1] получает доступ к отрицательному индексу! Правильно?

Я прочитал часть о том, что происходит в BinarySearch, если элемент не найден

отрицательное число, которое является побитовым дополнением индекса следующего элемента, который больше элемента, или, если нет большего элемента, побитовым дополнением Count.

и я не могу понять, пытается ли этот метод в моей книге использовать этот факт. Похоже, действительно запутанный способ написания того, что должно быть простым методом, иначе я не правильно его понимаю. Потому что, если я правильно понимаю, что BinarySearch возвращает произвольный первый найденный соответствующий элемент, тогда я не понимаю, почему метод не может быть просто

// Count the number of times an item appears in the sort List<T>.
public static int BinarySearchCountAll<T>(this List<T> myList, T searchValue)
{
   int count = 0,
   int center = myList.BinarySearch(searchValue);
   if ( center < 0 ) return count; 
   for ( int k = center + 1; k < myList.Length - 1 && myList[k] = searchValue; ++k ) 
      ++count;  
   for ( int k = center - 1; k >=0 && myList[k] = searchValue; --k ) 
      ++count;
   return count; 
}

1 ответ

Ты прав

while (left < 0 && myList[left-1].Equals(searchValue)) 

должно быть

while (left > 0 && myList[left-1].Equals(searchValue)) 

вместо. Обратите внимание на симметрию справа: while (right <(myList.Count - 1).... Естественно, что значение должно быть больше, чем слева.

Метод BinarySearchCountAll находит индекс "center", где center = searchValue. Поскольку список отсортирован, он может просто обойти соседние элементы, пока они не станут равными "центру". Затем он возвращает количество равных "центральных" элементов

Другие вопросы по тегам