2014-01-17 4 views
0

только быстрый (хахаха) вопрос относительно моего наивного алгоритма быстрой сортировки:Что случилось с моей реализацией quicksort?

#include <iostream> 

template <class T> 
void quicksort2(T array[] , int start, int end){ 
    int i = start; 
    int j = end; 
    int temp; 
    int pivot = (end - start)/2; 

    // Partioning 
    while(i <= j){ 

    while(array[i] < array[pivot]){ 
     i++; 
    } 
    while(array[j] > array[pivot]){ 
     j--; 
    } 

    if(i <= j){ 
     temp = array[i]; 
     array[i] = array[j]; 
     array[j] = temp; 
     i++; 
     j--; 
    } 
    } 

    // Sorting partions 
    if(start <= j){ 
    quicksort2(array , start , j); 
    } 
    if(end >= i){ 
    quicksort2(array , i , end); 
    } 
} 

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

Немного предупреждения перед запуском кода, иногда он замерзает мою машину, когда я запускаю код в тестовом массиве.

В любом случае, спасибо за помощь! Кроме того, это не для домашних заданий (Какой класс с алгоритмами сортировки требует, чтобы вы изучили быструю сортировку сразу с места в карьер?)

+1

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

+0

Вы используете окна? –

+3

Ваше использование 'temp' является своего рода опасным. 'temp' является' int', но 'array [i];' in 'temp = array [i];' is 'T'. Я бы предложил использовать ['std :: swap'] (http://en.cppreference.com/w/cpp/algorithm/swap), каким бы глупым это ни казалось. Я написал это вручную 10 раз, 9 хороших и 1 неправильно. Неприятная ошибка. 'std :: swap (array [i], array [j])' должен делать трюк и уже шаблонизирован. – luk32

ответ

1

Я отвечу на ваш вопрос вопросом.

Как вы обрабатываете случай, когда ваш метод вызывается, когда start == end?

Каждый из вас делит ваш подраздел на ось, поэтому каждый рекурсивный прогон имеет 1/2 длины последнего времени. Итак, вы начинаете с сортировки первой половины, затем первой 1/4, затем первой 1/8. В конце концов, вы вызовете метод с start = end = 0. Это делает 0 - 0/2 осью, которая равна 0.

Запустите этот случай через свой код, и вы увидите, что вы не обрабатывая случай, когда ваш метод пытается сортировать одну запись с собой. Он застрянет в бесконечном рекурсивном цикле, пока он не сработает с ...

Переполнение стека.

+2

Кроме того, вы вычисляете неправильный расчет. Если ваши начальные и конечные значения равны 2 и 4, то 4 - 2 = 2/2 = 1. Таким образом, ваш индекс поворота находится за пределами диапазона начала, конца. –

+0

Также внутренние петли не проверяются для перехода (когда 'i' пересекает' j'), и поэтому вы можете двигаться дальше. – wmorrison365

+0

@LeeLouviere Ahhh, что расчеты поворота не были тем, что я имел в виду для этого. Я предполагал, что это будет (слева + справа)/2. Спасибо, что поймал это. После исправления этого и реализации кода для рассмотрения описанного вами случая, код теперь работает отлично. Благодаря тонну! –

0

Возможно, вам захочется взглянуть на ваше использование '='. Я считаю, что вы можете использовать> = и < = при сравнении с точкой опоры, но при выполнении свопа это не обязательно.

Тогда кикер - это рекурсивный вызов - вы определенно не хотите использовать = там, я думаю, что это причина бесконечной рекурсии, которая в конечном итоге потерпит крах, поскольку j никогда не может быть меньше начала. Поэтому в основном каждый сравнивается с a =, удаляет его и каждый сравнивает без a =, добавляет один.

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