2016-06-10 4 views
3

При использовании алгоритмов STL в C++ я нашел много методов, таких как std::merge, std::inplace_merge, std::set_union, std::upper_bound, std::lower-bound и т. Д. Принимает только отсортированные данные в качестве входных данных.Почему для большинства алгоритмов STL требуется сортировка данных в качестве входных данных?

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

+1

Это потому, что это потребует проверки сортировки последовательности и изменения сложности алгоритмов, таких как 'std :: lower_bound', от O (log n) до O (n). Также нет ничего, что мешало бы вам сортировать заранее, если вы не уверены. – milleniumbug

+2

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

ответ

7

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

Для алгоритмов, в которых «имеет смысл» сортировать данные, разработчик должен знать, будет ли это так или нет, и может легко сортировать входные данные, если это необходимо. Алгоны могли проверить, сначала ли сортируются данные, но это будет тратить время, когда это не нужно. Например, upper_bound может быть O (logN) на предварительно отсортированном входе, тогда как проверка сортировки будет O (N). Имейте в виду также, что в целом у algos негде хранить статус: «Я проверил один раз, и данные были отсортированы» (и как они могли знать, как долго это пройдет, не понимая, какие потоки существуют, как они используют блокировки и т. Д.), , поэтому они должны были бы сделать это для каждого звонка по данным.

Кроме того, некоторые из указанных вами алгоритмов - например, std::merge - может использоваться на InputIterators, что означает, что вы можете обрабатывать ввод, который может быть прочитан только один раз, например, с клавиатуры, где он мгновенно предоставляется, но не сохраняется автоматически, где бы вы ни пересматривали, поэтому, имея дополнительный проход, чтобы проверить, значения someones typing уже отсортированы непрактично.

+0

* Для алгоритмов, в которых «имеет смысл» сортировать данные, разработчик должен знать, будет ли это так или нет, и может легко отсортировать вход, если это необходимо. * Это неверно. В этом случае данные ** должны быть сначала отсортированы по форме **, и разработчику не требуется сортировать данные для самой цели использования алгоритма. Потому что, если данные не сортируются, сортировка будет стоить по крайней мере O (nLogn). При сортировке данных, а затем с использованием 'lower-bound' будет стоить O (nLogn) вместо O (n), если непосредственно используются несортированные данные. – sameerkn

+0

@sameerkn: * "не требуется сортировать данные для самой цели использования алгоритма [, b], если данные не сортируются, а сортировка будет стоить по крайней мере O (nLogn)." * - ваши рассуждения просто неправильно. Обычно принято принимать удар, чтобы что-то сорвать один раз, чтобы вы могли применять его к нему несколько раз подряд (например, сортировка 'vector', а затем повторение' lower_bound', что намного быстрее, чем повторение 'std: : set '' lower_bound's, так как он больше похож на кеш). –

+0

* «Сортируя данные, а затем используя нижнюю границу, будет стоить O (nLogn) вместо O (n), если непосредственно используются несортированные данные». * - риск, связанный с этим, заключается в том, что реализация saner algo но не мог полагаться на отсортированный вход, пропустил бы один проход, чтобы проверить элементы вне порядка, прежде чем начинать сортировку O (NlogN). Другими словами, в моем ответе основное внимание уделялось наилучшей производительности, ухудшающейся, по крайней мере, до O (N); это, безусловно, может быть хуже - по крайней мере, O (NlogN) - если фактический ввод не отсортирован. –

0

Эти алгоритмы говорят:

Если вы сортировали данные, мы будем выполнять некоторые действия для вас, достаточно эффективно.

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

Как и вы не ожидаете, что sort для вставки элементов для вас, вы не должны ожидать, что эти алгоритмы будут сортировать элементы для вас.