검색하는 요소의 수를 모르고 인덱스를 허용하는 API를 제공한다고 가정하고 사용자가 범위를 벗어난 경우 null을 반환합니다 (여기서는 getWordFromDictionary 메서드로 구현 됨).), 어떻게 바이너리 검색을 수행하고 클라이언트 프로그램을위한 isWordInDictionary() 메소드를 구현할 수 있습니까?알 수없는 항목 수의 이진 검색
이 솔루션은 효과가 있지만 초기 색인 값이 높은 수준에서 직렬 검색을 수행했습니다. 낮은 값 범위를 통한 검색은 this answer에서 영감을 얻었습니다. 나는 또한 BinarySearch Reflector (C# decompiler)에서 엿보았지만 알려진 길이의 목록이 있으므로 여전히 간격을 메꾸기를 원한다.
private static string[] dictionary;
static void Main(string[] args)
{
dictionary = System.IO.File.ReadAllLines(@"C:\tmp\dictionary.txt");
Console.WriteLine(isWordInDictionary("aardvark", 0));
Console.WriteLine(isWordInDictionary("bee", 0));
Console.WriteLine(isWordInDictionary("zebra", 0));
Console.WriteLine(isWordInDictionaryBinary("aardvark"));
Console.WriteLine(isWordInDictionaryBinary("bee"));
Console.WriteLine(isWordInDictionaryBinary("zebra"));
Console.ReadLine();
}
static bool isWordInDictionaryBinary(string word)
{
// assume the size of the dictionary is unknown
// quick check for empty dictionary
string w = getWordFromDictionary(0);
if (w == null)
return false;
// assume that the length is very big.
int low = 0;
int hi = int.MaxValue;
while (low <= hi)
{
int mid = (low + ((hi - low) >> 1));
w = getWordFromDictionary(mid);
// If the middle element m you select at each step is outside
// the array bounds (you need a way to tell this), then limit
// the search to those elements with indexes small than m.
if (w == null)
{
hi = mid;
continue;
}
int compare = String.Compare(w, word);
if (compare == 0)
return true;
if (compare < 0)
low = mid + 1;
else
hi = mid - 1;
}
// punting on the search above the current value of hi
// to the (still unknown) upper limit
return isWordInDictionary(word, hi);
}
// serial search, works good for small number of items
static bool isWordInDictionary(string word, int startIndex)
{
// assume the size of the dictionary is unknown
int i = startIndex;
while (getWordFromDictionary(i) != null)
{
if (getWordFromDictionary(i).Equals(word, StringComparison.OrdinalIgnoreCase))
return true;
i++;
}
return false;
}
private static string getWordFromDictionary(int index)
{
try
{
return dictionary[index];
}
catch (IndexOutOfRangeException)
{
return null;
}
}
최종 코드는 이렇게 대답
static bool isWordInDictionaryBinary(string word)
{
// assume the size of the dictionary is unknown
// quick check for empty dictionary
string w = getWordFromDictionary(0);
if (w == null)
return false;
// assume that the number of elements is very big
int low = 0;
int hi = int.MaxValue;
while (low <= hi)
{
int mid = (low + ((hi - low) >> 1));
w = getWordFromDictionary(mid);
// treat null the same as finding a string that comes
// after the string you are looking for
if (w == null)
{
hi = mid - 1;
continue;
}
int compare = String.Compare(w, word);
if (compare == 0)
return true;
if (compare < 0)
low = mid + 1;
else
hi = mid - 1;
}
return false;
}
귀하는 정확하게 맞다고 생각합니다. 재미있게, 나는 그것을 밖으로 시도 할 것이다. 내 코드는 데이터를 반환하는 초기 hi 값을 찾으려고 시도했지만 어쨌든 제안 할 필요는 없습니다. – RyanW
사실 null을 우리가 검색하고있는 단어 뒤에 나오는 단어로 취급하는 것이 내 코드를 수정하는 가장 간단한 방법이었습니다. 고맙습니다! – RyanW