在java中实现quicksort时遇到一些问题。我运行这个程序时出现stackoverflow错误,我不确定为什么。如果有人能指出错误,那就太好了。
si是起始指数。 ei是结束指数。
public static void qsort(int[] a, int si, int ei){
//base case
if(ei<=si || si>=ei){}
else{
int pivot = a[si];
int length = ei - si + 1;
int i = si+1; int tmp;
//partition array
for(int j = si+1; j<length; j++){
if(pivot > a[j]){
tmp = a[j];
a[j] = a[i];
a[i] = tmp;
i++;
}
}
//put pivot in right position
a[si] = a[i-1];
a[i-1] = pivot;
//call qsort on right and left sides of pivot
qsort(a, 0, i-2);
qsort(a, i, a.length-1);
}
}
答案 0 :(得分:6)
首先你应该按照Keith的建议修复qsort递归调用的边界,否则你总是一遍又一遍地对整个数组进行排序。你必须调整你的分区循环:j是一个索引,从子数组的开头到它的结尾(包括最后一个元素)。所以你必须从si + 1循环到ei(包括ei)。
所以这是更正后的代码。我运行了一些测试用例,似乎排序很好。
public static void qsort(int[] a, int si, int ei){
//base case
if(ei<=si || si>=ei){}
else{
int pivot = a[si];
int i = si+1; int tmp;
//partition array
for(int j = si+1; j<= ei; j++){
if(pivot > a[j]){
tmp = a[j];
a[j] = a[i];
a[i] = tmp;
i++;
}
}
//put pivot in right position
a[si] = a[i-1];
a[i-1] = pivot;
//call qsort on right and left sides of pivot
qsort(a, si, i-2);
qsort(a, i, ei);
}
}
答案 1 :(得分:1)
int partition(int array[], int too_big_index, int too_small_index)
{
int x = array[too_big_index];
int i = too_big_index;
int j = too_small_index;
int temp;
do
{
while (x <array[j])
{
j --;
}
while (x >array[i])
{
i++;
}
if (i < j)
{
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}while (i < j);
return j; // middle
}
void QuickSort(int num[], int too_big_index, int too_small_index)
{
// too_big_index = beginning of array
// too_small_index = end of array
int middle;
if (too_big_index < too_small_index)
{
middle = partition(num, too_big_index, too_small_index);
QuickSort(num, too_big_index, middle); // sort first section
QuickSort(num, middle+1, too_small_index); // sort second section
}
return;
}
void main()
{
int arr[]={8,7,13,2,5,19,1,40,12,34};
QuickSort(arr,0,9);
for(int i=0;i<10;i++)
System.out.println(arr[i]);
}
答案 2 :(得分:0)
你手上可能有一个无限制的递归错误。我不能确定快速扫描它,但是......
即使你不这样做,你仍然会在这个实现中使用 lot 堆栈。足以导致堆栈溢出。如果用100万个已经分类的项目调用它会发生什么?你将它们分成1和999,999项,然后递归。因此,您需要100万个堆栈帧才能完成这项工作。
有很多方法可以解决这个问题,包括递归两个范围中较小的一个并迭代两个中较大的一个,或者在堆数据结构中自己实现堆栈等等。你可能想做的比但是,深堆栈也意味着你正在超越O(n lg n)排序界限。
P.S。错误在这里:
qsort(a, 0, i-2);
qsort(a, i, a.length-1);
应该是
qsort(a, si, i-2);
qsort(a, i, ei);
答案 3 :(得分:0)
你可以试试这个:
public void sort(int[] A) {
if (A == null || A.length == 0)
return;
quicksort(A, 0, A.length - 1);
}
public void quicksort(int[] A, int left, int right) {
int pivot = A[left + (right - left) / 2];
int i = left;
int j = right;
while (i <= j) {
while (A[i] < pivot) {
i++;
}
while (A[j] > pivot) {
j--;
}
if (i <= j) {
exchange(i, j);
i++;
j--;
}
}
if(left < j)
quicksort(A,left,j);
if(i < right)
quicksort(A,i,right);
}
public void exchange(int i, int j){
int temp=A[i];
A[i]=A[j];
A[j]=temp;
}
public String toString() {
String s = "";
s += "[" + A[0];
for (int i = 1; i < A.length; i++) {
s += ", " + A[i];
}
s += "]";
return s;
}
答案 4 :(得分:0)
import java.util.Arrays;
public class QuickSort {
public static int pivot(int[] a, int lo, int hi){
int mid = (lo+hi)/2;
int pivot = a[lo] + a[hi] + a[mid] - Math.min(Math.min(a[lo], a[hi]), a[mid]) - Math.max(Math.max(a[lo], a[hi]), a[mid]);
if(pivot == a[lo])
return lo;
else if(pivot == a[hi])
return hi;
return mid;
}
public static int partition(int[] a, int lo, int hi){
int k = pivot(a, lo, hi);
//System.out.println(k);
swap(a, lo, k);
//System.out.println(a);
int j = hi + 1;
int i = lo;
while(true){
while(a[lo] < a[--j])
if(j==lo) break;
while(a[++i] < a[lo])
if(i==hi) break;
if(i >= j) break;
swap(a, i, j);
}
swap(a, lo, j);
return j;
}
public static void sort(int[] a, int lo, int hi){
if(hi<=lo) return;
int p = partition(a, lo, hi);
sort(a, lo, p-1);
sort(a, p+1, hi);
}
public static void swap(int[] a, int b, int c){
int swap = a[b];
a[b] = a[c];
a[c] = swap;
}
public static void sort(int[] a){
sort(a, 0, a.length - 1);
System.out.print(Arrays.toString(a));
}
public static void main(String[] args) {
int[] arr = {5,8,6,4,2,9,7,5,9,4,7,6,2,8,7,5,6};
sort(arr);
}
}
试试这个。它肯定会起作用。
答案 5 :(得分:0)
//刚为此实现了测试人员类,它将起作用
public int [] sort(int [] A,int from,int to){
if(from<to){
int pivot=partition(A,from,to);
if(pivot>1)
sort(A,from, pivot-1);
if(pivot+1<to)
sort(A, pivot+1, to);
}
return array;
}
public int partition(int A [],int from,int to){
while(from < to){
int pivot=A[from];
while(A[from]<pivot)
from++;
while(A[to]>pivot)
to--;
if(from<to)
swap(A,to,from);
}
return to;
}
private void swap(int A[], int i, int j){
int temp = A[i];
A[i] = A[j];
A[j] = temp;}
答案 6 :(得分:0)
这应该是相当的。 Code below with this Image makes way more sense.
public void quickSort(long[] a){
int startingIndex = 0;
int endingIndex = a.length - 1;
qsort(a, startingIndex, endingIndex);
}
private void qsort(long[] a, int startingIndex, int endingIndex){
if (startingIndex < endingIndex){
int middleIndex = partition(a, startingIndex, endingIndex);
qsort(a, startingIndex, middleIndex-1);
qsort(a, middleIndex+1, endingIndex);
}
}
private int partition(long[] a, int startingIndex, int endingIndex){
long pivot = a[endingIndex];
int endWall = endingIndex;
int wall = 0;
while (wall < endWall){
if (a[wall] < pivot){
wall++;
}
else {
a[endWall] = a[wall];
a[wall] = a[endWall - 1];
a[endWall - 1] = pivot;
endWall--;
}
}
return wall;
}
享受!
答案 7 :(得分:0)
public class MyQuickSort {
private int array[];
private int length;
public void sort(int[] inputArr) {
if (inputArr == null || inputArr.length == 0) {
return;
}
this.array = inputArr;
length = inputArr.length;
quickSort(0, length - 1);
}
private void quickSort(int lowerIndex, int higherIndex) {
int i = lowerIndex;
int j = higherIndex;
// calculate pivot number, I am taking pivot as middle index number
int pivot = array[lowerIndex+(higherIndex-lowerIndex)/2];
// Divide into two arrays
while (i <= j) {
/**
* In each iteration, we will identify a number from left side which
* is greater then the pivot value, and also we will identify a number
* from right side which is less then the pivot value. Once the search
* is done, then we exchange both numbers.
*/
while (array[i] < pivot) {
i++;
}
while (array[j] > pivot) {
j--;
}
if (i <= j) {
exchangeNumbers(i, j);
//move index to next position on both sides
i++;
j--;
}
}
// call quickSort() method recursively
if (lowerIndex < j)
quickSort(lowerIndex, j);
if (i < higherIndex)
quickSort(i, higherIndex);
}
private void exchangeNumbers(int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
public static void main(String a[]){
MyQuickSort sorter = new MyQuickSort();
int[] input = {24,2,45,20,56,75,2,56,99,53,12};
sorter.sort(input);
for(int i:input){
System.out.print(i);
System.out.print(" ");
}
}
}
答案 8 :(得分:0)
// the partition function
public static int Sort(int arr[], int start, int end)
{
int pivot = arr[end];
int pIndex = start;
for(int i = start; i< end;i++)
{
if(arr[i] <= pivot)
{
int temp = arr[i];
arr[i] = arr[pIndex];
arr[pIndex] = temp;
pIndex++;
}
}
int temp = arr[pIndex];
arr[pIndex] = pivot;
arr[end] = temp;
return pIndex;
}
public static void quickSort(int arr[],int start,int end)
{
if(start>=end)
return;
// finding the pivot element
int pivot = Sort(arr,start,end);
quickSort(arr,start,pivot-1);
quickSort(arr,pivot+1,end);
}
答案 9 :(得分:-1)
Quicksort对恰好按顺序排列的输入稍微敏感,在这种情况下,它可以跳过一些交换。 Mergesort没有任何这样的优化,与Mergesort相比,这也使得Quicksort更快一些。