2015-03-19 2 views
2

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

int partition (int low,int high) 
{ 
int j=low,i=low+1; 
int PivotItem=arr[low]; 
    for(int i=0,j=0;i<n;i++) 
{ 
    if(arr[i]==PivotItem) 
    subarray[j]=arr[i]; 
} 
for(i=low+1;i<=high;i++) 
{ 
    if(arr[i]<PivotItem) 
    { 
     j++; 
     swap(arr[i],arr[j]); 
    } 
} 
swap(arr[low],arr[j]); 
int PivotPoint=j; 
return PivotPoint; 
} 
void quick_sort(int low,int high) 
{ 
if(low==high) 
    return ; 
int PivotPoint=partition(low,high); 
quick_sort(low,PivotPoint-1); 
quick_sort(PivotPoint+1,high); 
} 
+0

Вы ориентируетесь на определенную языковую платформу? В Java 'Collections.sort()' фактически действительно объединяется сортировка, чтобы избежать ненужного копирования данных. В C++ у вас есть отдельные 'sort' (merge) и' qsort' (быстрая сортировка). Кроме того, что вы подразумеваете под «копией предметов»? Если у вас есть список номеров, в которых задействованы дубликаты, вы не можете сказать, что они являются копиями. Это просто дубликаты, которые хранят часть данных. – ha9u63ar

+0

Вы имеете в виду много повторяющихся предметов или предметов, повторяющихся много раз? –

+0

@YvesDaoust: Я имею в виду, например, у нас есть 11113333333222299999999000000031115553333. – sarina

ответ

2

Я предполагаю, что вы имели в виду тот факт, что быстрая сортировка сравнивает элементы на основе <= (или <, а затем результат симметричен к следующему объяснению) компаратора, и если мы посмотрим на случай, когда все элементы являются то же самое, что и с осью x, вы получаете худшую сложность худшего сортирования, так как вы разбиваете массив на две очень не четные части, один из которых имеет размер n-1, а другой пуст.


Быстрое исправление для решения этой проблемы будет использовать быстрой сортировки только < и > - разбить данные на две подрешетки, и вместо особой оси, удерживая массив, который содержит все элементы, равные оси поворота, затем рекурсия на элементах, которые строго больше, чем точка поворота, и элементы, которые строго меньше, чем точка поворота, и объединяют три массива.

Иллюстрация:

legend: X=pivot, S = smaller than pivot, L = larger than pivot 
array = |SLLLSLXLSLXSSLLXLLLSSXSSLLLSSXSSLLLXSSL| 
Choose pivot - X 
Create L array of only strictly smaller elements: |SSSSSSSSSSSSSSS| 
Create R array of only strictly larger elements: |LLLLLLLLLLLLLLLLLL| 
Create "pivot array" |XXXXXX| 

Now, recurse on L, recurse on R, and combine: 
|SSSSSSSSSSSSSSS XXXXXX LLLLLLLLLLLLLLLLLL| 
+0

Я поставил свой код в свой вопрос. Как реализовать свое решение в моем коде? – sarina

+0

@sarina Вам нужно сделать 'partition' удержанием подмассива всех элементов, равных оси (или диапазону элементов), и когда вы закончите, рекурсия будет идти от' l' до начала этого подмассива, а из конец этого подмассива до 'r'. Пожалуйста, спросите, что вы не понимаете конкретно, и я попытаюсь уточнить. – amit

+0

Я сделал subarray в разделе функции. Вы имеете в виду это? После этого, что я делаю? – sarina

3

Существует специальная модификация QuickSort известна как dutch flag sort algorithm. Он использует трехсторонний раздел для предметов меньших, равных и больших, чем значение элемента поворота.

+0

В дополнение к этому, трехсторонний раздел может быть реализован с двойными опорными точками. – greybeard

+0

@greybeard Вы имеете в виду http://iaroslavski.narod.ru/quicksort/DualPivotQuicksort.pdf? Определенно, этот алгоритм имеет выигрыш для многих случаев повторных пунктов (но, похоже, он полностью не решает проблему) – MBo

+0

Это был бы наиболее примечательный URL-адрес самой цитируемой статьи. Это справедливый удар при сортировке общего назначения с равномерным временем доступа. _Некоторые повторные ключи будут казаться более легкими, чем _many key repetitions_. – greybeard

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