自制的快速排序算法抛出栈溢出异常:在分区方法中查找下一个枢轴位置

huangapple go评论66阅读模式
英文:

Home-rolled Quicksort algorithm throwing stack overflow exception: finding next location of pivot in partition method

问题

这是我的快速排序代码,对于正常情况它是有效的,但对于数组中包含相同元素的情况,我的代码出现问题。在这种情况下,我考虑将等于枢轴的元素放在枢轴的左侧。请帮我找出代码中的逻辑错误:

public class Solution {

    public static int partition(int input[], int si, int ei) {
        int pivot = input[si], pivotPos = si, count = 0;
        // 计算小于等于枢轴的元素数量,以便在枢轴左侧留出空间
        for (int i = pivotPos + 1; i < input.length; i++) {
            if (input[i] <= pivot)
                count++;
        }
        // 交换枢轴和元素
        input[si] = input[si + count];
        input[si + count] = pivot;
        pivotPos = si + count;
        // 确保枢轴左侧的元素都小于等于枢轴,右侧的元素都大于枢轴
        int i = si, j = ei, temp;

        while (i < pivotPos && j > pivotPos) {
            if (input[i] <= pivot)
                i++;
            else {
                if (input[j] > pivot)
                    j--;
                else {
                    temp = input[i];
                    input[i] = input[j];
                    input[j] = temp;
                    i++;
                    j--;
                }
            }
        }
        return pivotPos;
    }

    public static void quickSort(int input[], int si, int ei) {
        if (si >= ei)
            return;
        int pivotPos = partition(input, si, ei);
        quickSort(input, si, pivotPos - 1);
        quickSort(input, pivotPos + 1, ei);
    }

    public static void quickSort(int[] input) {
        quickSort(input, 0, input.length - 1);
    }
}

输入测试案例:
4 3 8 4 6 5
期望输出:
3 4 4 5 6 8

我的代码在调用分区函数的地方引发堆栈溢出错误。

英文:

hey this is my quicksort code and its working for normal cases but not for those where the array have same elements and in that case i considered putting elements which are equal to pivot to the left side of pivot.Could anyone please rectify the logical mistake in my code:


public class Solution {
public static int partition(int input[],int si, int ei) {
int pivot = input[si],pivotPos = si,count = 0;
// counting no of elements less than pivot so that  space can be left empty to left of pivot
for(int i = pivotPos+1; i&lt;input.length;i++) {
if(input[i]&lt;=pivot)
count++;
}
//swapping pivot with the element
input[si] = input[si+count];
input[si+count] = pivot;
pivotPos = si+count;
// ensuring all elements to the left of pivot are less and to the right are more
int i = si, j = ei,temp;
while(i&lt;pivotPos &amp;&amp; j&gt;pivotPos) {
if(input[i]&lt;=pivot)
i++;
else  {
if(input[j]&gt;pivot)
j--;
else {
temp = input[i];
input[i] = input[j];
input[j] = temp;
i++;
j--;
}
}
}
return pivotPos;
}
public static void quickSort(int input[], int si, int ei) {
if(si&gt;=ei)
return; 
int pivotPos =  partition(input,si,ei);
quickSort(input,si,pivotPos-1);
quickSort(input,pivotPos+1,ei);
}
public static void quickSort(int[] input) {
/* Your class should be named Solution
* Don&#39;t write main().
* Don&#39;t read input, it is passed as function argument.
* No need to print or return the output.
* Taking input and printing output is handled automatically.
*/
quickSort(input,0,input.length - 1);
}
}

input test case:
4 3 8 4 6 5
expected output:
3 4 4 5 6 8

my code gives stack overflow error from the point where partition function is being called

答案1

得分: 0

我认为我已经修复了你的代码,同时最小程度地更改了你的代码风格。你会注意到,尽管我们实际上不需要它,但我保留了一些你的代码。我将它们留在那里供你对比。

public class QuickSort {

    public static int partition(int input[], int si, int ei) {
        int pivot = input[si], pivotPos = si, count = 0;
        // 计算小于 pivot 的元素数量,以便在 pivot 左侧留出空间

        for (int i = pivotPos + 1; i < input.length; i++) {
            if (input[i] <= pivot) {
                count++;
            }
        }
        // 上面的 count 不是我们需要的信息
        // 我们需要知道在 si 和 ei(包括)之间有多少个元素小于 pivot 的值

        // 修正的逻辑在这里:
        int smallerThanPivotCount = 0;
        for (int i = si; i <= ei; i++) { // 请注意,我们的逻辑包括 ei
            if (input[i] < pivot)
                smallerThanPivotCount++;
        }

        // 交换 pivot 与元素
        input[si] = input[si + smallerThanPivotCount];
        input[si + smallerThanPivotCount] = pivot;
        pivotPos = si + smallerThanPivotCount;

        // 接下来
        // 确保 pivot 左侧的所有元素都小于 pivot,右侧的所有元素都大于 pivot
        int i = si, j = ei, temp;

        while (i < pivotPos && j > pivotPos) {
            if (input[i] <= pivot)
                i++;
            else {
                if (input[j] >= pivot)
                    j--;
                else {
                    temp = input[i];
                    input[i] = input[j];
                    input[j] = temp;
                    i++;
                    j--;
                }
            }
        }
        return pivotPos;
    }

    public static void quickSort(int input[], int si, int ei) {
        if (si >= ei)
            return;
        int pivotPos = partition(input, si, ei);
        quickSort(input, si, pivotPos - 1);
        quickSort(input, pivotPos + 1, ei);
    }

    public static void quickSort(int[] input) {
        /* 你的类应该命名为 Solution
         * 不要写 main()。
         * 不要读取输入,它作为函数参数传递。
         * 无需打印或返回输出。
         * 输入和输出处理都是自动完成的。
         */
        quickSort(input, 0, input.length - 1);
    }
}

我认为你的问题只是没有正确地计算向前移动 pivot 所需的空格数量。我已经编写了代码。我不能百分之百保证它是正确的,但它通过了我的一小部分单元测试,包括你自己的示例数组。我建议你自己检查它以理解逻辑。然后清理掉多余的部分,使它成为你自己的代码。祝好运。

英文:

I think I have fixed your code while making minimal changes to your code style. You'll notice that I left some of your code in even though it isn't what we actually need to do. I left that in for your comparison.

public class QuickSort {
public static int partition(int input[],int si, int ei) {
int pivot = input[si],pivotPos = si,count = 0;
// counting no of elements less than pivot so that  space can be left empty to left of pivot
for(int i = pivotPos+1; i&lt;input.length;i++) {
if(input[i]&lt;=pivot) {
count++;
}
}
// the above var count is not the info we need
// we need to know how many elements between si and ei (inclusive)
// are less than the value of pivot
// corrected logic here:
int smallerThanPivotCount = 0;
for (int i = si; i &lt;= ei; i++) { // note that our logic includes ei
if (input[i] &lt; pivot)
smallerThanPivotCount++;
}
//swapping pivot with the element
input[si] = input[si + smallerThanPivotCount];
input[si + smallerThanPivotCount] = pivot;
pivotPos = si + smallerThanPivotCount;
// next we are
// ensuring all elements to the left of pivot are less and to the right are more
int i = si, j = ei,temp;
while(i&lt;pivotPos &amp;&amp; j&gt;pivotPos) {
if(input[i]&lt;=pivot)
i++;
else  {
if(input[j]&gt;=pivot)
j--;
else {
temp = input[i];
input[i] = input[j];
input[j] = temp;
i++;
j--;
}
}
}
return pivotPos;
}
public static void quickSort(int input[], int si, int ei) {
if(si&gt;=ei)
return;
int pivotPos =  partition(input,si,ei);
quickSort(input,si,pivotPos - 1);
quickSort(input,pivotPos+1,ei);
}
public static void quickSort(int[] input) {
/* Your class should be named Solution
* Don&#39;t write main().
* Don&#39;t read input, it is passed as function argument.
* No need to print or return the output.
* Taking input and printing output is handled automatically.
*/
quickSort(input,0,input.length - 1);
}
}

I think your problem was just that you didn't correctly count the number of spaces forward you needed to shift the pivot. I have written code. I don't guarantee you 100% that it is correct, but it does pass my short list of unit tests, including your own example array. I suggest examining it yourself to understand the logic. Then clean up the extra stuff and make it your own. Cheers.

huangapple
  • 本文由 发表于 2023年5月24日 17:45:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76322171.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定