我正在做一个比较Bubblesort和Quicksort算法的项目。一切正常,直到我想对已经使用Quicksort方法排序的数据进行排序。它在大型阵列(50k,100k)上崩溃。
在我的情况下,我首先按降序对数据进行排序,然后尝试按升序排序然后崩溃。
read(); // just creates an array with random integers
quickSortDSC(0, length - 1); //Here is the problem! (works if commented)
t1 = clock();
quickSortASC(0, length - 1);
t2 = clock();
cout << "Quick Sort\t: " << (t2 - t1)/CLK_TCK << " sec\n";
完整代码:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <ctime>
using namespace std;
long length = 1000;
const long max_length = 100000;
int list[max_length];
void read()
{
ifstream fin("random.dat", ios::binary);
for (long i = 0; i < length; i++)
{
fin.read((char*)&list[i], sizeof(int));
}
fin.close();
}
void bubbleSort()
{
int temp;
for(long i = 0; i < length; i++)
{
for(long j = 0; j < length-i-1; j++)
{
if (list[j] > list[j+1])
{
temp = list[j];
list[j] = list[j+1];
list[j+1] = temp;
}
}
}
}
long partitionASC(long left, long right)
{
int pivot_element = list[left];
int lb = left, ub = right;
int temp;
while (left < right)
{
while(list[left] <= pivot_element)
left++;
while(list[right] > pivot_element)
right--;
if (left < right)
{
temp = list[left];
list[left] = list[right];
list[right] = temp;
}
}
list[lb] = list[right];
list[right] = pivot_element;
return right;
}
long partitionDSC(long left, long right)
{
int pivot_element = list[left];
int lb = left, ub = right;
int temp;
while (left < right)
{
while(list[left] >= pivot_element)
left++;
while(list[right] < pivot_element)
right--;
if (left < right)
{
temp = list[left];
list[left] = list[right];
list[right] = temp;
}
}
list[lb] = list[right];
list[right] = pivot_element;
return right;
}
//ascending order
void quickSortASC(long left, long right)
{
long pivot;
if (left < right)
{
pivot = partitionASC(left, right);
quickSortASC(left, pivot-1);
quickSortASC(pivot+1, right);
}
}
//descending order
void quickSortDSC(long left, long right)
{
long pivot;
if (left < right)
{
pivot = partitionDSC(left, right);
quickSortDSC(left, pivot-1);
quickSortDSC(pivot+1, right);
}
}
int main()
{
double t1, t2;
for (length = 1000; length <= max_length; )
{
cout << "\nLength\t: " << length << '\n';
read();
t1 = clock();
bubbleSort();
t2 = clock();
cout << "Bubble Sort\t: " << (t2 - t1)/CLK_TCK << " sec\n";
read();
quickSortDSC(0, length - 1); //Here is the problem!
t1 = clock();
quickSortASC(0, length - 1);
t2 = clock();
cout << "Quick Sort\t: " << (t2 - t1)/CLK_TCK << " sec\n";
if(length == max_length)
break;
switch (length)
{
case 1000 :
length = 10000;
break;
case 10000 :
length = 50000;
break;
case 50000 :
length = 100000;
break;
}
}
return 0;
}
答案 0 :(得分:2)
通过选择数组的第一个元素作为数据透视表,当数组已经排序时,您会遇到快速排序最坏情况的行为。所以你得到O(n 2 )行为(更糟糕的是,O(n)堆栈空间,这可能会给你一个堆栈溢出)。
为避免这种情况,请选择其他枢轴。通常会选择中间元素作为轴:
int pivot_element = list[(left+right)/2];
或随机元素:
int pivot_element = list[left + random()%(right+1-left)];
答案 1 :(得分:0)
例如。假设情况为{3,6,4,7}。 无论您选择“单枢轴”还是“双枢轴” QuickSort,如果始终将第一个元素作为枢轴,那么对于排序后的数组,很有可能会面临堆栈溢出或O(n2)。
因此,在每个递归循环中将枢轴/秒随机化可以防止在最坏的情况下进入O(n2)或无限循环。
下面的例子将很好地解释最坏的情况。
package algo.sorting.rev;
import java.util.Arrays;
公共类DualPivotQuickSort {
public static void main(String[] args) {
int[] input = new int[] { 8, 6, 2, 4, 17, 3, 10, 19, 21, 13, 9, 19, 14, 13, 7, 17 };
quicksort(input, 0, input.length - 1);
System.out.println(Arrays.toString(input));
}
/**
* 3 segments are as below.
*
* | item < pivotL | pivotL <= item <= pivotR | item > pivotR |
*
* |pivotLPos . . . j-1|j . . . k|k+1 . . . pivotRPos|
*
*
* @param a
* @param pivotLPos
* @param pivotRPos
*/
private static void quicksort(int [] a, int pivotLPos, int pivotRPos){
int size = pivotRPos - pivotLPos + 1;
if(size < 3)
return;
int pivotL = a[pivotLPos];
int pivotR = a[pivotRPos];
if(pivotL > pivotR)
swapContent(a, pivotLPos, pivotRPos);
int i = pivotLPos + 1;
int j = pivotRPos - 1;
int k = pivotRPos;
while(i <= j){
while(i < pivotRPos && a[i] < pivotL)
i++;
while(j >= pivotLPos && a[j] >= pivotL){
if(a[j] <= pivotR)
j--;
else{
// adding to segment3
swapContent(a, j, k);
j--;
k--;
}
}
if(i < j){
swapContent(a, i, j);
i++;
if(a[j] > pivotR){
// adding to segment3
swapContent(a, j, k);
k--;
}
j--;
}
}
swapContent(a, j, pivotLPos);
if(size > 3){
if(j - pivotLPos >= 3)
quicksort(a, pivotLPos, j-1); // recursion on seg1
if(k - j >= 3)
quicksort(a, j, k); // recursion on seg2
if(j - pivotRPos >= 3)
quicksort(a, k+1, pivotRPos); // recursion on seg3
}
}
private static void swapContent(int [] a, int pos1, int pos2){
int b = a[pos1];
int c = a[pos2];
b ^= c;
c ^= b;
b ^= c;
a[pos1] = b;
a[pos2] = c;
}
}