快速排序不适用于排序数组
Quicksort doesn't work with sorted array
我正在做一个比较Bubblesort和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 Sortt: " << (t2 - t1)/CLK_TCK << " secn";
完整代码:
#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 << "nLengtht: " << length << 'n';
read();
t1 = clock();
bubbleSort();
t2 = clock();
cout << "Bubble Sortt: " << (t2 - t1)/CLK_TCK << " secn";
read();
quickSortDSC(0, length - 1); //Here is the problem!
t1 = clock();
quickSortASC(0, length - 1);
t2 = clock();
cout << "Quick Sortt: " << (t2 - t1)/CLK_TCK << " secn";
if(length == max_length)
break;
switch (length)
{
case 1000 :
length = 10000;
break;
case 10000 :
length = 50000;
break;
case 50000 :
length = 100000;
break;
}
}
return 0;
}
通过选择数组的第一个元素作为透视,当数组已经排序时,您可以达到快速排序的最坏情况行为。 所以你会得到 O(n2( 行为(更糟糕的是,O(n( 堆栈空间,这可能会给你一个堆栈溢出(。
为避免这种情况,请选择其他枢轴。 通常人们会选择中间元素作为枢轴:
int pivot_element = list[(left+right)/2];
或随机元素:
int pivot_element = list[left + random()%(right+1-left)];
例如..假设 {3, 6, 4, 7} 是这种情况。 无论您选择单透视还是双透视快速排序,如果您总是将第一个元素作为透视,那么对于排序数组,您很有可能遇到堆栈溢出或 O(n2(。
因此,在每个递归循环中随机化枢轴是防止在最坏的情况下进入 O(n2( 或无限循环。
下面的例子将很好地解释最坏的情况。
Package algo.sorting.rev;
import java.util.Arrays;
public class 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;
}
}
相关文章:
- 显示错误输出的简单数组排序程序
- C 使用单个函数对具有多种值类型的数组排序
- 2D数组排序,空格打乱顺序
- C 2D数组排序
- C++数组排序 - 将"bbba"和"0001"视为不正确排序的问题
- 数组排序功能
- CString 数组排序
- 简单的数组排序/检查 划分和征服版本
- C++ 中的多维数组排序
- 选择在++中对并行数组排序
- C++:二维指针数组排序:选择排序不适用于某些实例
- C++字符串数组排序
- C++中的指针数组排序算法
- 在VC++6中使用向量进行数组排序时出错,而在VC++2012中没有错误
- 将索引数组排序为主数组
- 数组排序、数组输入、数组输出
- C++数组排序,内存错误
- 在嵌入式系统上将数组排序功能从c++移植到c
- 基于其他int数组排序
- 多维数组排序c++奇怪行为