2011-03-21 2 views
8

Я только что создал пользовательскую функцию поиска для строк на карте. Я разработал какой-то алгоритм линейного поиска (который я узнал позже) и не был удовлетворен скоростью функции. Поэтому я искал более быструю функцию и нашел собственную функцию карты: map :: find.Какой алгоритм стоит найти STL?

Это было невероятно быстрее, чем линейный алгоритм, который я использовал.

В другом примере функция STL найти была также намного быстрее, чем другая линейная функция, которую я использую.

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

Также как узнать алгоритмы, лежащие в основе этих основных функций? Есть ли список или какая-то база данных, чтобы узнать об этом?

Спасибо за все ваши ответы! Я поддержал лучшие ответы и принял ответ Макса Либберта, потому что он был самым подробным.

Paul :)

+0

Не стоит отвечать, но gcc 'find' использует регулярный цикл while в качестве входных итераторов (т. Е.' Istream') и форвардных/двунаправленных итераторов (т. Е. 'List'). Для итераторов с произвольным доступом (т. Е. 'Vector') он использует цикл' for', но он проверяет четыре элемента за раз. Реализация Visual Studio - это просто регулярный цикл 'for', проверяющий один элемент за раз, но он специализирован для поиска строк. –

+0

Я нашел [эти] (http://channel9.msdn.com/shows/Going+Deep/C9-Lectures-Introduction-to-STL-with-Stephan-T-Lavavej/) интро видео на канале9, чтобы быть действительно полезным а также при запуске с STL – MarkB42

ответ

8

Я разработал какой-то алгоритм линейного поиска (который я узнал позже) и не был удовлетворен скоростью функции. Поэтому я искал более быструю функцию и нашел собственную функцию карты: map::find.

Это было невероятно быстрее, чем линейный алгоритм, который я использовал.

std::map предназначен для хранения данных, отсортированных по мере их вставки в контейнер. Это одна из его главных задач. Это также причина того, что вы должны определить какой-то частичный заказ для данных, которые вы ввели в std::map.

Это означает, что каждая вставка занимает немного больше времени, чем вставка в другие контейнеры (вставки в std::list - как только вы имеете точку вставки - например, является O (1), как добавление к std::vector или добавления/добавляя слева до std::deque). Но поиск гарантированно будет использовать двоичный поиск (или, скорее, до navigate the red-black tree behind the std::map (в разделе «Предварительная или разумная оптимизация»)).

В другом примере функция поиска STL была намного быстрее, чем другая линейная функция, которую я использую.

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

В этом нет ничего гипотетического. Сортировка ваших данных требует времени и всегда занимает больше времени, чем больше элементов данных.

std::find способен обрабатывать несортированные данные, поэтому его необходимо реализовать как линейный поиск (сравнить std::binary_search/std::lower_bound). Но std::find разрешено скрывать и разворачивать петли, сравнивать несколько предметов за раз (если элементы небольшие, и особенно если они являются примитивными типами, которые поддаются низкоуровневому разгону бит) и т. Д.

Также как узнать алгоритмы, лежащие в основе этих основных функций? Есть ли список или какая-то база данных, чтобы узнать об этом?

Лично я узнал много алгоритмов, прочитав то, что было доступно в STL и на нескольких других языках. Сначала мне было легче изучить контейнеры.

13

std::map хранит свои элементы в отсортированном порядке (почти всегда в самобалансирующемся бинарном дереве поиска).

std::map::find использует это и использует dichotomic search.

+0

Каким образом? В зависимости от индекса (map [index])? – Paul

+0

@Paul Это хорошее место для начала: https://secure.wikimedia.org/wikipedia/en/wiki/Red-black_tree. Большинство реализаций будут использовать что-то более умное, чем простое дерево RB. –

+0

да, отсортировано по ключевому значению – Inverse

2

Реализация хорошо, зависит от реализации.

Но насколько общие классы сложности идти, вы можете проверить, например, эту страницу с обзором для общих методов STL:

http://www.cplusplus.com/reference/stl/

3

Технически нет таких алгоритмов. Стандарт определяет, насколько хорошо должен выполняться каждый алгоритм, а не как он должен это делать. Каждый компилятор отправляет реализацию стандартной библиотеки.

Это, как говорится, есть свободные реализации STL. Вы можете посмотреть на их код. Например, STL Port.

Также как найти алгоритмы, лежащие в основе этих основных функций? Есть ли список или какая-то база данных, чтобы узнать об этом?

Ну, есть Dictionary of Algorithms and Data Structures, но это немного грязно.

+0

Спасибо, что ответили на эту часть. Я надеюсь, что код не слишком сильно превышает мой уровень, чтобы понять это. ;) – Paul

2

Алгоритмы STL почти всегда быстрее, чем все, что вы могли бы написать, потому что оно делает много оптимизаций под обложками. Кроме того, быстрее использовать итераторы, чем оператор [], при повторении через векторный или другой контейнер с произвольным доступом, поскольку накладные расходы меньше.

Вы должны проверить книги Скотта Мейерса Эффективное C++ Third Edition и Effective STL. (Материал в More Effective C++ содержится в 3-м выпуске Effective C++.)

+0

Я был бы очень удивлен, увидев, что доступ к итератору к вектору будет отличаться от использования оператора []. В обоих случаях должны быть минимальные накладные расходы. Быстрый тест с gcc 4.2.1 показывает, что это так. – KeithB

+2

Разница в производительности между векторными итераторами и оператором [] почти неоценима. –

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