Обновлено:
Первоначально я должен был найти алгоритм разбиения на массив, как часть алгоритма быстрой сортировки.
Например, такой массив, как:
[5, 3, 2, 4, 3, 1]
основанный на стержне 3,
[меньше 3 || 3, 3, больше 3]
Наконец, выясните, что нет необходимости получать раздел выше, результат ниже также сделает быструю сортировку:
[меньше 3 || 3, больше или равно 3]
что означает, что 3 не должны быть рядом друг с другом.
И мой код ниже (
int partition(std::vector<int>& v, int pivot)
{
int left = 0;
int right = v.size()-1;
while (left != right)
{
while (v[left] < pivot) ++left;
while (pivot < v[right]) --right;
swap(v[left], v[right]);
}
return left;
}
Бен отмечает, что я должен обновить один критерий равным, так что один критерий "<", а другой - "> =", это сделает условие законченным.
Однако разделение
5, 3, 2, 4, 3, 1
основанный на стержне 3, будет
<3 || 3, 4, 3, 5
И и троицы не соседствуют.
Появляется настоящая приятная вещь, на самом деле неважно, смежны ли троицы. Поскольку после тщательного анализа алгоритма быстрой сортировки этот раздел, наконец, сделает массив отсортированным.
Попробуйте следующее
#include <iostream>
#include <vector>
#include <utility>
std::vector<int>::size_type partition( std::vector<int> &v, int pivot )
{
std::vector<int>::size_type i = 0, j = v.size();
while ( i != j )
{
while ( i != j && v[i] < pivot ) i++;
while ( i != j && !( v[--j] < pivot ) );
if ( i != j ) std::swap( v[i++], v[j] );
}
return i;
}
int main()
{
std::vector<int> v = { 1, 4, 3, 5, 4, 6 };
std::vector<int>::size_type n = partition( v, 4 );
for ( std::vector<int>::size_type i = 0; i < n; i++ )
{
std::cout << v[i] << ' ';
}
std::cout << std::endl;
for ( std::vector<int>::size_type i = n; i < v.size(); i++ )
{
std::cout << v[i] << ' ';
}
std::cout << std::endl;
return 0;
}
Выход
1 3
4 5 4 6
Измените одного из ваших операторов на <=
, а не на <
.
while (v[left] < pivot) ++left;
while (pivot <= v[right]) --right;
Таким образом, каждое число соответствует одному из двух критериев. Либо он меньше, чем точка поворота, и он перемещается влево, или ось вращения меньше или равна ему, и она перемещается вправо. Там нет никакого среднего.
Для обобщенного функтора сравнения вы можете просто поменять параметры и инвертировать результат, чтобы получить тот же эффект:
while ( compare(v[left], pivot) ) ++left;
while ( !compare(v[right], pivot) ) --right;
1 4 3 5 4 6
(на основе разворота 4) приведет к 1 3 4 5 4 6
, потому что правый курсор просто пропустит «второй 4», оставляя 5 в середине 4. Возможно, мой код будет реконструирован для создания раздела, но должен существовать способ сделать этот раздел ... правильно ... спасибо!