Быстрая сортировка

Разговоры на любые темы: вы можете обсудить здесь какой-либо сайт, найти единомышленников или просто пообщаться...
SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Быстрая сортировка

Сообщение SLIM » 11.01.2011 (Вт) 22:16

Вчера стал копаться в данном алгоритме. Сразу пошел в
Вики
и
Algollist
А также почитал Н. Вирта

Сел писать. Наткнулся на несколько вопросов (раньше я писал уже этот алгоритм, но по-моему я половину "скопипастил").
Нашел здесь сишный код.
Код: Выделить всё
template<class T>
void quickSortR(T* a, long N) {
// На входе - массив a[], a[N] - его последний элемент.

  long i = 0, j = N;            // поставить указатели на исходные места
  T temp, p;

  p = a[ N>>1 ];                // центральный элемент

  // процедура разделения
  do {
    while ( a[i] < p ) i++;
    while ( a[j] > p ) j--;

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

  // рекурсивные вызовы, если есть, что сортировать
  if ( j > 0 ) quickSortR(a, j);
  if ( N > i ) quickSortR(a+i, N-i);
}



Начал сравнивать со своим. Не пошло.
Стал отлаживать и сравнивать по шагам. И тут удивился. То что описано в той же вики на самом деле реализовано не так.
Код, приведенный на algollist не соответствует приведенному выше рисунку и описанному алгоритму.

Тестировал на массиве
Код: Выделить всё
1 7 4 0 9 4 8 8 2 4
(разделитель - пробел)

Теперь по алгоритму
1. Выбираем опорный элемент - выбирается элемент под индексом 4, значение 9
2. Начиная со первого элемента приращаем счетчика индекса, двигаясь вправо, пока не найдем значение, большее опорного (9). Приходим к тому же опорному элементу - индекс равен 4.
3. Начиная с последнего элемента двигаемся влево, пока не найдем элемент меньше опорного. Находим элемент с индексом 9, значение 4
4. Обмениваем элементы если индекс слева меньше либо равен индексу справа опорного элемента.

Ок, получили массив

Код: Выделить всё
1 7 4 0 4 4 8 8 2 9


5. Далее в указанных источниках написано что двигаемся дальше по тем же правилам. Приводим в соответствие индексы слева и справа прибавляя и отнимая единицу соответственно. Проверяем, если индекс слева меньше индекса справа - можно продолжать. Опять прибавляем в цикле к левому индексу по единице. Здесь первое несоответствие (которое хоть как-то учтено в вики, но нет на алголлисте) - индекс переходит барьер (индекс 4) и принимает элемент под индексом 9, значение = 9.
6. Двигаемся влево по правому индексу. Находим индекс 8, значение = 2.
7. Проверяем меньше либо равно ли левый индекс правому? Не, не равен, поэтому не обмениваем.

Здесь уже много вопросов. Почем массив не делится на две части как предписано алгоритму? Здесь есть свой нюанс, который указан в вики
Следует учесть, что если какая-либо граница (l или r) дошла до опорного элемента, то при обмене значение m изменяется на r-й или l-й элемент соответственно.

а также
Если r = l — найдена середина массива — операция разделения закончена, оба индекса указывают на опорный элемент.


Но в коде все иначе. Не важно куда мы ушли от барьера.

Ладно. Далее. Алгоритм говорит что нужно таким же образом отсортировать левую и правую часть разделенного массива.
Но тут опять код иной. Здесь сортируется массив с 0 по 8-й элемент, а вторая часть естественно не сортируется. Короче дальше получается несколько шагов холостым ходом. Вообще за весь алгоритм правая часть сортируется всего два раза.


У Н. Вирта есть есть ответ почему делает именно так. И написано это оправдано. Но описание алгоритма в источниках и код не соответствуют, и не описано почему так.
Я может конечно туплю, но считаю это неверным.
Пишите жизнь на чистовик.....переписать не удастся.....

iGrok
Артефакт VBStreets
Артефакт VBStreets
 
Сообщения: 4272
Зарегистрирован: 10.05.2007 (Чт) 16:11
Откуда: Сетевое сознание

Re: Быстрая сортировка

Сообщение iGrok » 11.01.2011 (Вт) 22:38

А что именно не так-то?
label:
cli
jmp label

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Re: Быстрая сортировка

Сообщение SLIM » 11.01.2011 (Вт) 22:58

iGrok писал(а):А что именно не так-то?

Да не делится он на две части. Не по этому принципу работает алгоритм
Пишите жизнь на чистовик.....переписать не удастся.....

iGrok
Артефакт VBStreets
Артефакт VBStreets
 
Сообщения: 4272
Зарегистрирован: 10.05.2007 (Чт) 16:11
Откуда: Сетевое сознание

Re: Быстрая сортировка

Сообщение iGrok » 11.01.2011 (Вт) 23:12

Ну, он на две части не делится только потому, что выбран "кривой" опорник. Это "самый плохой случай".

Возьми вот такой массив 1 7 9 4 4 8 0 8 2 4, и проверь всё то же самое на нём.
label:
cli
jmp label

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Re: Быстрая сортировка

Сообщение SLIM » 11.01.2011 (Вт) 23:36

Не, я говорю что описывается не то что делается. Вот в чем дело.
Код приведен тот, который оптимизирован например у Вирта, но там объясняется почему. А здесь просто так взяли и модифицировали.
Пишите жизнь на чистовик.....переписать не удастся.....

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Re: Быстрая сортировка

Сообщение SLIM » 12.01.2011 (Ср) 0:17

Ну и да. Если берется худший случай, то работа идет не по алгоритму да?

У меня вот несколько вопросов еще вдогонку. Я часто что-то ищу в интернете но не могу найти первоисточник. Например ту же работу Ричард Хоара. Нападаю на какие-то левые статьи, но саму работу найти не могу. Подскажите как вообще такое можно найти?
Пишите жизнь на чистовик.....переписать не удастся.....

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Re: Быстрая сортировка

Сообщение SLIM » 12.01.2011 (Ср) 0:20

Вот где описано что делает этот алгоритм (код который я привел). Это верное описание.
Пишите жизнь на чистовик.....переписать не удастся.....

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Re: Быстрая сортировка

Сообщение SLIM » 15.01.2011 (Сб) 15:16

Кто может сказать минимальные максимальные значения количества перестановок и сравнений по алгоритму. Не могу найти
Пишите жизнь на чистовик.....переписать не удастся.....

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Быстрая сортировка

Сообщение Хакер » 15.01.2011 (Сб) 15:41

Чё, вики читать уже западло? Там прямо три пункта: «лучший случай», «средний случай», «худший случай» с указанием числа перестановок.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Re: Быстрая сортировка

Сообщение SLIM » 15.01.2011 (Сб) 15:46

Читал конечно.
Да как-то не совпадает. Пробовал сортировать массив, который уже был упорядочен - первый раз по возрастанию, второй раз по убыванию.
Расчетно не сходится. Вот мне и нужно знать, что принимается за сравнение именно в программе.

UPD::Просто вот здесь как-то иначе написано. Чему верить то?
Пишите жизнь на чистовик.....переписать не удастся.....

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Re: Быстрая сортировка

Сообщение SLIM » 15.01.2011 (Сб) 17:23

Вот, переписал код по Вирту
Код: Выделить всё
void QuickSort_2(int* piArray, int iLeftIndex, int iRightIndex, int* piResultChecks, int* piResultMoves)
{

   int i = iLeftIndex;
   int j = iRightIndex;
   int temp, p;


  p = piArray[ (iLeftIndex+ iRightIndex)/2];

  do
  {

   while ( piArray[i] < p )
   {
      (*piResultChecks)++;
      i++;
   }
   (*piResultChecks)++;


   while ( piArray[j] > p )
   {
      (*piResultChecks)++;
      j--;
   }
   (*piResultChecks)++;


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

      (*piResultMoves) = (*piResultMoves) + 2;
    }

  } while ( i<=j );


  if ( j > iLeftIndex )
     QuickSort_2(piArray, j, iLeftIndex, piResultChecks, piResultMoves);

  if ( iRightIndex > i )
     QuickSort_2(piArray, i, iRightIndex, piResultChecks, piResultMoves);
}


Наихудший случай считает 23 сравнения и 14 перемещений для 10 элементов
Ни ни в какую формулу я это вписать не могу.
Пишите жизнь на чистовик.....переписать не удастся.....

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Re: Быстрая сортировка

Сообщение SLIM » 15.01.2011 (Сб) 17:46

Ага.
Лучший случай считается лучшим если на каждой итерации можно разделить массив на два равных. Возможно ли это - это вопрос.
Массив из 10 элементов не подходит. Лучше взять из 7.
Тогда если также считать
Код: Выделить всё
  (*piResultChecks)++;
  if (j > iLeftIndex )
     QuickSort_2(piArray, j, iLeftIndex, piResultChecks, piResultMoves);

  (*piResultChecks)++;
  if (iRightIndex > i )
     QuickSort_2(piArray, i, iRightIndex, piResultChecks, piResultMoves);


Т.е. сравнение границ тоже считать за сравнение, то получается 20 сравнений. Что уже похоже на действительность n lg n.

Но правильно ли считать эти дополнительные сравнения? Ведь элементы сами не сравниваются
Пишите жизнь на чистовик.....переписать не удастся.....

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Re: Быстрая сортировка

Сообщение SLIM » 15.01.2011 (Сб) 17:54

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

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Re: Быстрая сортировка

Сообщение SLIM » 15.01.2011 (Сб) 18:12

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

Debugger
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1667
Зарегистрирован: 17.06.2006 (Сб) 15:11

Re: Быстрая сортировка

Сообщение Debugger » 15.01.2011 (Сб) 18:51

Наихудший случай для QSort'a - когда всё время один массив получается пустым.
Посчитай количество сравнений для худших случаев из 3,4,5,6,7 элементов, если НАСТОЛЬКО приспичило.
Построй по ним график.
Тут уже будет сложно не догадаться о формуле.

По одному замеру ты ничего не можешь сказать о верности O(n*n).


Вернуться в Народный треп

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 53

    TopList