Целые числа разделов C ++ при дублировании Pivot

0

Обновлено:

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

Например, такой массив, как:

[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

И и троицы не соседствуют.

Появляется настоящая приятная вещь, на самом деле неважно, смежны ли троицы. Поскольку после тщательного анализа алгоритма быстрой сортировки этот раздел, наконец, сделает массив отсортированным.

Теги:
quicksort
partitioning

2 ответа

1

Попробуйте следующее

#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 
  • 0
    Влад, мне нужно, чтобы результат был 1 3 | 4 4 5 6, это возможно?
  • 0
    @Vindicate Это просто отсортированная последовательность. В этом случае, что означает указание оси?
Показать ещё 5 комментариев
1

Измените одного из ваших операторов на <=, а не на <.

while (v[left] < pivot) ++left;
while (pivot <= v[right]) --right;

Таким образом, каждое число соответствует одному из двух критериев. Либо он меньше, чем точка поворота, и он перемещается влево, или ось вращения меньше или равна ему, и она перемещается вправо. Там нет никакого среднего.

Для обобщенного функтора сравнения вы можете просто поменять параметры и инвертировать результат, чтобы получить тот же эффект:

while ( compare(v[left], pivot) ) ++left;
while ( !compare(v[right], pivot) ) --right;
  • 0
    Привет, Бенджамин, вы правы насчет отсутствия среднего уровня, но если раздел 1 4 3 5 4 6 (на основе разворота 4) приведет к 1 3 4 5 4 6 , потому что правый курсор просто пропустит «второй 4», оставляя 5 в середине 4. Возможно, мой код будет реконструирован для создания раздела, но должен существовать способ сделать этот раздел ... правильно ... спасибо!
  • 0
    Привет Бен, число, равное pivot, не нужно для смежности для быстрого алгоритма сортировки. Спасибо, что указали на смену одного из операторов!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню