Самый прямой ответ на ваш вопрос да, это сортировка вставкой. Это очень неэффективный вставка сортировка, но тем не менее insertion сортировать.
Ваш код не имеет убедительного шага, зная, что после определения местоположения элемента сравнения могут остановиться, и операция сдвига в отсортированной последовательности приведет к созданию отверстия для нового элемента. Скорее, вы полагаетесь на свой цикл сравнения, чтобы выполнить этот переход для вас, даже если сравнение больше не требуется, что не очень эффективно.
Возможно, это показалось мне немного запутанным, поэтому я буду разбираться с вашим кодом.
- Ваш потенциальный элемент для каждой итерации
i
изначально a[i]
.
- Вы Перечислите линейно над уже отсортированной частью вашей последовательности, ища, где
a[i]
принадлежит
- После того, как вы нашли место (если он уже не где она принадлежит), нужно поменять местами
a[i]
с элементом a[j]
, который в настоящее время проживает в вашей цели.
- С этого момента, первоначальное значение
a[i]
теперь на месте в последовательности, но ...
- Для оставшейся части отсортированной последовательности, своп-сравнение гарантированно срабатывает, как истинный (подсказка: так зачем это делать?) против любого значения, хранящегося в
a[i]
, потому что ранее сохраненные ранее значения уже были отсортированы. Поэтому a[i]
постоянно заменяется следующим значением в отсортированной последовательности до тех пор, пока в конце концов оно не будет иметь наибольшее значение, которое по определению будет принадлежать.
Таким образом, да, это вставка-сортировка. Он поддерживает отсортированную последовательность в начале целого, которая когда-либо расширяется с каждой первичной итерацией. И для каждой первичной итерации элемент перспективы «вставлен», а задние элементы сдвигаются вниз, чтобы сделать доступное отверстие для этого.
... это количество сравнений или свопов больше/меньше с помощью этого рода-подхода?
Значительно требуется больше сравнений с вашим подходом. Каждой итерации гарантируется линейная сложность O (n), и есть итерации n
. Таким образом, вы гарантировали, чтобы иметь O (N^2) сложность для ваших сравнений, которая является чумой эффективных алгоритмов сортировки. Не только худший случай; гарантировано.
C++ Вставка Сортировать
Тем не менее, считают это
template<typename Iter>
void insertion_sort(Iter first, Iter last)
{
for (Iter it = first; it != last; ++it)
std::rotate(std::upper_bound(first, it, *it), it, std::next(it));
}
Это, вероятно, seems like Greek (не в обиду греки), если вы только начинаете в C++, но не использует два фундаментальных алгоритма, которые делают его неожиданно эффективным: std::upper_bound
и std::rotate
.
std::upper_bound
работает на отсортированной последовательности. Воспользовавшись этим, он может использовать алгоритм двоичного поиска , чтобы найти первый элемент в отсортированной последовательности, который строго превышает значение перспективы (*it
). Поэтому поиск точки вставки для одной перспективы - O (logN), намного лучше, чем линейный поиск O (n).
Как только точка ввода известна, std::rotate
используется для установки элемента на месте с использованием итератора точки вставки.Это эффективно делает это:
0 1 2 3 5 6 4
^^ * these will be rotated right one element
0 1 2 3 5 6
4
0 1 2 3 5 6
4
0 1 2 3 4 5 6
Обратите внимание, что вращение не требует не сравнений.
Очевидно, что это решение шаблона - это не то, что кто-то будет подавать на курс исправления алгоритмов. Но я надеюсь, что это даст вам несколько идей о том, как свертывание сортировки может сводиться к минимуму:
- Использование двоичного поиска в уже отсортированной части последовательности для минимизации сравнений.
- Использование no сравнение при выполнении вращения.
Удачи.
Спасибо, сэр, блестящий ответ и общее полезное объяснение. – Aditya