2014-10-25 3 views
-1

Я читаю бинарный поиск по массиву чисел, и я считаю, что знаю, как это работает и как его реализовать. Теперь мне нужно знать, как выполнять бинарный поиск в массиве строк? Я знаю, что бинарный поиск требует, чтобы массив был отсортирован уже. предположим, что у меня есть массив строк, уже отсортированный, как мне реализовать бинарный поиск? Я знаю, если бы это был массив чисел, я бы пошел к среднему индексу массива и определил, будет ли требуемый поиск no слева или справа и сделать это рекурсивно. Как я могу это сделать для строк?Бинарный поиск по строкам вместо цифр

+3

Таким же образом. –

+0

Это может быть точно так же. Строки C - это просто большие числа. –

+0

Вы имеете в виду, что у вас есть массив строк? Если это так, это одно и то же. Если вы имеете в виду «поиск значения внутри строки», если вы не сортируете символы в строке, вам будет более или менее нужно искать строку из начала до конца. [Существует алгоритм Boyer-Moore, который довольно популярен для LARGE string ищет, но для небольших строк обычно нечего просто искать прямо через] –

ответ

1

До тех пор, пока понятие типа «оно равно» и «оно меньше» определено для типа, над которым вы работаете, вы можете реализовать алгоритм. Не имеет значения, являются ли значения числами, буквами или пользовательскими объектами. Следующий пример демонстрирует эту концепцию:

template<typename Iterator>                   
Iterator search(Iterator initial, Iterator final, const typename Iterator::value_type& value) {  

    if(value < *initial) { 
    // bail out immediately  
    return final; 
    } 

    while(initial != final) {                   
    auto mid = std::next(initial, std::distance(initial, final)/2);        
    if(*mid == value) {                    
     return mid;                     
    } else if(*mid < value) {                  
     initial = std::next(mid);                  
    } else {                       
     final = std::prev(mid);                  
    }                        
    }                         
    return final;                      
}  

Покуда операций *mid == value и *mid < value определены, можно найти в контейнере любого типа (другое требование является то, что я должен быть в состоянии случайным образом получить доступ к своему итератору).

Это отнюдь не полный ответ, и есть много других деталей, но, надеюсь, вы получите эту идею.

Полный пример программы:

#include <vector> 
#include <list> 
#include <iostream> 

template<typename Iterator> 
Iterator search(Iterator initial, Iterator final, const typename Iterator::value_type& value) { 

    if(value < *initial) { 
    // bail out immediately  
    return final; 
    } 

    while(initial != final) { 
    auto mid = std::next(initial, std::distance(initial, final)/2); 
    if(*mid == value) { 
     return mid; 
    } else if(*mid < value) { 
     initial = std::next(mid); 
    } else { 
     final = std::prev(mid); 
    } 
    } 
    return final; 
} 


int main() { 
    { 
    std::vector<int> v {1, 2, 3, 4, 5}; 
    auto it = search(v.begin(), v.end(), 3); 
    if(it == v.end()) { 
     std::cout << "Not Found!" << std::endl; 
    } else { 
     std::cout << "Found in position: " << std::distance(v.begin(), it) 
       << " (value is : " << *it << ")" << std::endl; 
    } 
    } 

    { 
    std::vector<char> v {'a', 'b', 'c', 'd', 'e'}; 
    auto it = search(v.begin(), v.end(), 'd'); 
    if(it == v.end()) { 
     std::cout << "Not Found!" << std::endl; 
    } else { 
     std::cout << "Found in position: " << std::distance(v.begin(), it) 
       << " (value is : " << *it << ")" << std::endl; 
    } 
    } 

    { 
    std::list<float> v {-1, 0, 1, 2, 3, 4}; 
    auto it = search(v.begin(), v.end(), 0); 
    if(it == v.end()) { 
     std::cout << "Not Found!" << std::endl; 
    } else { 
     std::cout << "Found in position: " << std::distance(v.begin(), it) 
       << " (value is : " << *it << ")" << std::endl; 
    } 
    } 

    { 
    std::vector<char> v {'a', 'b', 'c', 'd', 'e'}; 
    auto it = search(v.begin(), v.end(), 'f'); 
    if(it == v.end()) { 
     std::cout << "Not Found!" << std::endl; 
    } else { 
     std::cout << "Found in position: " << std::distance(v.begin(), it) 
       << " (value is : " << *it << ")" << std::endl; 
    } 
    } 

}                       

Образец Run:

Found in position: 2 (value is : 3) 
Found in position: 3 (value is : d) 
Found in position: 1 (value is : 0) 
Not Found! 
1

Наивный подход состоит в том, чтобы присвоить уникальное значение каждой букве (если вы делаете английский, это легко, всего 26 значений) и сравнивайте значения первой буквы каждой строки. Если буквы совпадают, тогда вы сравниваете вторую букву и так далее.

+1

Можно ли, например, использовать код ASCII для этого? И затем, если следовать этому, используйте либо 'strcmp', либо' std :: string :: operastor <', чтобы на самом деле провести сравнение ... –

+0

@MatsPetersson, что имеет смысл. Спасибо, что освободили это. Http://www.cplusplus.com/reference/string/string/operators/ Я видел, что класс строк имеет реляционные операторы. Не могли бы вы объяснить, как они работают. Предположительно новый ответ – Rajeshwar

1

Если вы используете массив std::string, то все равно, так как вы все сравниваете операторы.

, поэтому вам просто нужно заменить тип массива, и вы можете выполнить поиск как есть для чисел.

0

Точно так же. Если вы используете std::string, у него уже есть operator== и operator <, которые вам нужны только для двоичного поиска. Если у вас есть указатели на символы, вы можете использовать strcmp, где отрицательное значение меньше, а 0 равно.

Смежные вопросы