Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

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

22K
08 июня 2011 года
ChickenIdol
15 / / 27.03.2007
Никак не пойму.
Есть стандартный алгоритм быстрой сортировки, первая его часть: разбивка массива на две части больше и меньше опорного.
На вики есть (и здесь на форуме тоже) примеры реализации, например:

Код:
void quickSortR(int * a, long N) {
  long i = 0, j = N;
  int temp, p;

  // опорный элемент прописан жестко, просто для примера
  p = a[1];

  do {
    while ( a < p ) i++;
    while ( a[j] > p ) j--;

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

  //рекурсию убрал, вопрос не в ней
}


почему алгоритм на наборе {1,2,3,0}, с опорным элементом с индексом 1, выдает неверный результат? {1, 0, 3, 2}
360
08 июня 2011 года
P*t*
474 / / 15.02.2007
может не j=N, а j=N-1?
и еще i++ j-- нужно заменить на
 
Код:
if (a!=p) i++;
if (a[j]!=p) j--;
22K
09 июня 2011 года
ChickenIdol
15 / / 27.03.2007
Видно всем пофиг)
Тем не менее: думаю ошибку тут
 
Код:
if (i <= j) {
      temp = a; a = a[j]; a[j] = temp;
      i++; j--;
    }

инкремент после каждого свапа недопустим.
С другой стороны, если этого не сделать на наборах, типа {1,2,15,15,2}, с опорным элементом 15 мы попадаем в бесконечный цикл.
360
09 июня 2011 года
P*t*
474 / / 15.02.2007
Цитата: ChickenIdol
Видно всем пофиг)
Тем не менее: думаю ошибку тут



Ну, думайте дальше...

22K
09 июня 2011 года
ChickenIdol
15 / / 27.03.2007
Разобрался. Идея стандартной реализации немного отличается от описания алгоритма в вики:
>>Операция разделения массива: реорганизуем массив таким образом, чтобы все элементы, меньшие или равные опорному элементу, оказались слева от него, а все элементы, большие опорного — справа от него

На деле справа могут оказаться элементы равные опорному, но в конечном счете это не важно. Т.е на месте опорного проводится черта, слева от которой <=, а справа >=
22K
09 июня 2011 года
ChickenIdol
15 / / 27.03.2007
Вынос мозга)
При тестах у меня выходит именно так, как написал.

Если есть элементы равные опорному, происходит swap одного на другой, а затем увеличение счетчиков на единицы,
а дальше штатно. Т.е элементы равные опорному могут быть как слева, так и справа.
По коду например: http://ru.wikibooks.org/wiki/%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%B1%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B9_%D1%81%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B8#C
277
09 июня 2011 года
arrjj
1.7K / / 26.01.2011
Цитата: ChickenIdol

почему алгоритм на наборе {1,2,3,0}, с опорным элементом с индексом 1, выдает неверный результат? {1, 0, 3, 2}



Гг... да не было в коде никакой проблемы. Всё правильно - считаем:
Первый проход:
1 2 3 0
while(массив[x]<2) x++;
while(массив[y]>2) y--;
x=1//2
y=3//0
поменяли их местами
1 0 3 2
x++;y--; x=y=2;
2-й проход
1 0 3 2
while(массив[x]<2) x++;//ниразу
while(массив[y]>2) y--;//ниразу
x++;y--;
выход из цикла, т.к. x>y;

Вот ваш код подфиксеный работает:

Код:
#include <iostream>
#include <stdlib.h>
using namespace std;
void qs(int * a, long N) {
  long i = 0, j = N-1;
  int temp, p;

  // опорный элемент прописан жестко, просто для примера
  p = a[1];

  do {
    while ( a < p ) i++;
    while ( a[j] > p ) j--;

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

    if(i<N-1)
        qs(a+i,N-i);
    if(j>0)
        qs(a,j+1);
}
int main()
{
int sort[14]={1,0,3,2,7,6,0,5,7,1,4,2,3,7};
cout<<"Начальный массив:"<<endl;
for(int x=0;x<14;x+=1)
cout<<sort[x]<<" ";
cout<<endl;
qs(&sort[0],14);
cout<<"Конечный массив:"<<endl;
for(int x=0;x<14;x+=1)
cout<<sort[x]<<" ";
cout<<endl;
return 0;
}

Но лучше как в описании за опорный брать случайный:
 
Код:
...
#include <time.h>
...
  p = a[rand()%N];
...
int main()
{
srand(time(NULL));
...
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог