Консультация № 175573
23.12.2009, 22:46
0.00 руб.
0 7 0
Добрый вечер Уважаемые эксперты. Изучая алгоритм быстрой сортировки у меня возникли проблемы.
Использовал алгоритм с этого сайта Алгоритм быстрой сортировки. А именно - просто алгоритм, начальный, не модернизировал и ничего далее с ним не делал(см.Приложение). Написал программу, которая реализует данный алгоритм, она работает отлично. Но все же сколько всего не перечитывал не смог понять как же он все таки перемещается по массиву. Для того чтобы объяснить приведу часть исследования:
При сортировке данной последовательности -
a[0]=2 a[1]=3 a[2]=4 a[3]=2 a[4]=4 a[5]=2 a[6]=1 a[7]=3 a[8]=1 a[9]=3 a[10]=1
Ход сортировки следующий:
1)2 3 4 2 4 2 1 3 1 3 1
2)1 1 1 2 4 2 4 3 3 3 2
3)1 1 1 2 4 2 4 3 3 3 2
4)1 1 1 2 4 2 4 3 3 3 2
5)1 1 1 2 2 2 3 3 3 4 4
6)1 1 1 2 2 2 3 3 3 4 4
7)1 1 1 2 2 2 3 3 3 4 4
8)1 1 1 2 2 2 3 3 3 4 4
9)1 1 1 2 2 2 3 3 3 4 4
Жирным шрифтом я выделил опорный элементы в данном шаге.
В начале понятно движение - 1 - 2 шаг. А дальше опорный элементы пошли вправо, особенно 4 шаг. Долго сидел, думал над тем, как это происходит если j то передавалась как R и она теперь находится в самом начале. То как выбирается последовательность и опорный элемент аж с позиции под номером 7, если считать с нуля.
Пожалуйста, объясните из чего вытекают данные шаги.



Приложение:
Вызов функции:
q( a, 0, n - 1 );
Функция:
void q(int *a,int L,int R)
{
int i,j,k,temp;
i=L;
j=R;
k = a[(L + R)/2];
while (i<=j)
{
while (a[i]<k) i++;
while (k<a[j]) j--;
if (i<=j)
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
i++;
j--;
}
}
if (L<j) q(a,L,j);
if (i<R) q(a,i,R);
}

Обсуждение

Неизвестный
24.12.2009, 01:12
общий
Мне кажется, что вторая строчка должна выглядеть вот так: 2 1 1 2 1 2 4 3 4 3 3. Здесь режущий элемент остался на своем месте, хотя обычно его сносит в сторону.

Принцип действия qsort: за одну итерацию находится место для 1 элемента. Все слева - меньше или равны, а все справа - больше или равны. Значит, он на своем месте. Потом также применяем эту функцию для левой и правой половины. И для их половин и тд. Эта реализация слишком насилует мозг. Я предпочитаю другую, которая просто проходит слева направо по интервалу.

В любом случае, мы просто режем наш интервал на 3 части, левую и правую надо еще отсортировать. Каждая следующая итерация обрабатывает не весь массив, а только свой интервал. Пишите цифры на листочке и выделяйте интервалы маркерами - так проще понять. И не стоит для сортировки заполнять массив одинаковыми элементами: понять принцип действия это не поможет :)
давно
Профессор
230118
3054
24.12.2009, 01:31
общий
Dimon4ik:
Там же сказано
Выбрать опорный элемент p - середину массива
Разделить массив по этому элементу
Если подмассив слева от p содержит более одного элемента,
вызвать quickSort для него.
Если подмассив справа от p содержит более одного элемента,
вызвать quickSort для него.
На 4 шаге и происходит quickSort для правой части. Режущий элемент после первого хода перемещается на 4 место. На 3 ходе показан результат сортировки левого подмассива, который состоит из 3 единиц. А правый подмассив 4 2 4 3 3 3 2, в котором средний элемент 3.
Неизвестный
24.12.2009, 13:07
общий
Ashotn:
А как программа обращается к правой части, ведь она же уже потеряла индекс среднего опорного элемента для всего массива, так как перезаписала его другими в результате рекурсии?
давно
Профессор
230118
3054
24.12.2009, 13:18
общий
Dimon4ik:
Вот тут он передается через аргумент функции if (i<R) q(a,i,R); В одном из вхождений он перезаписан, но в другом извлекается из стека.
Неизвестный
24.12.2009, 13:32
общий
А! понял! Спасибо. Как же я мог забыть про стек ...
Неизвестный
24.12.2009, 13:35
общий
Evgenijm:
Я скопировал результат работы программы.
И просто выделил там некоторые части.
Но программа сортирует правильно даже очень большие массивы. Так что наверное - правильно
Неизвестный
24.12.2009, 15:56
общий
Dimon4ik:
Она и похожа на правильную. Не уверен только, что она элементы заново не пересчитывает - это было бы неоптимально. Код мне не понравился тем, что там с анализом индексов мучаться приходится при проверке. У меня дома есть более понятный код. Только я его заново востанавливать сейчас не хочу :)
Форма ответа