Quicksort给出细分错误

时间:2019-04-02 08:55:28

标签: c++ sorting segmentation-fault quicksort

我尝试实现Quicksort算法。这是Quicksort本身的代码

void quicksortlast(double* a, int first, int last)
{
     if(first<last)
     {
        int pIndex=partition(a, first, last);
        quicksortlast(a, first, pIndex-1);
        quicksortlast(a, pIndex+1, last); 
     }
}

pIndex变量是元素在正确位置的位置。我选择最后一个数组元素作为分区方案中的枢轴。以下代码应该对数组进行分区:

 int partition(double* a, int first, int last)
 {
     int pivot=last;
     int i=0;
     int j=last-1;
     while(i<j && i<=last && j>=0)
     {
        while(a[i++]<a[pivot])
        {
            if(i>last)
                break;
        }
        while(a[j--]>a[pivot])
        {
            if(j<0)
                break;
        }
        if(i<j && i<=last && j>=0)
        {
            swap(a,i,j);
            i++;
            j--;
        }
    }
    swap(a,j,pivot);
    return j;   
 }

分区功能使用定义为

的交换功能
void swap(double* a, int left, int right)
{
    int temp=a[left];
    a[left]=a[right];
    a[right]=temp;
    return;
}

当然,还有test.cpp函数可以测试算法。

#include <iostream>
#include "qsort.h"
using namespace std;

int main()
{
    int len;
    cin>>len;
    double* a= new double[len];
    for(int i=0;i<len;i++)
        cin>>a[i];
    cout<<"Unsorted array"<<endl;
    print(a,len);
    quicksortlast(a, 0, len-1);
    cout<<"printed array"<<endl;
    print(a, len);
   return 0;
}

第一次调用print函数会打印未排序的数组,但是它给我一个错误消息:

 Segmentation fault(core is dumped). 

我知道可以访问某些内存位置,但是我不知道实际错误在哪里。我们非常感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

您的代码进入无限循环,从而导致stack overflow error。该算法的伪代码可以在维基百科上找到,正确的实现应该是这样的:

#include <stdio.h>

// Example program
#include <iostream>
#include <string>

void swap(double* a, int left, int right)
{
    int temp = a[left];
    a[left] = a[right];
    a[right] = temp;
    return;
}
int partition(double* a, int first, int last)
{
    int pivot = last;
    int i = 0;
    for (int j = 0; j < last - 1; j++) {
        if (a[j] < pivot) {
            swap(a, i, j);
            i++;
        }
    }
    swap(a, i, last);
    return i;
}

void quicksortlast(double* a, int first, int last)
{
    if (first < last)
    {
        int pIndex = partition(a, first, last);
        quicksortlast(a, first, pIndex - 1);
        quicksortlast(a, pIndex + 1, last);
    }
}

using namespace std;
int main()
{
    int len;
    cin >> len;
    double* a = new double[len];
    for (int i = 0; i < len; i++)
        cin >> a[i];
    quicksortlast(a, 0, len - 1);
    return 0;
}

答案 1 :(得分:0)

分区代码需要一些修复。如果应该首先使用代码,则代码使用0。 swap函数从double转换为int并返回,可以使用std :: swap代替。

对于从数组的两端向中间扫描的快速排序,通常将中间用作枢轴,因为这样就不必使用索引检查来避免扫描超出数组的两端,这可能是原因代码出现分段错误。当扫描索引相互交叉时,扫描将停止。返回哪个索引以及该索引代表什么取决于具体的实现。

典型的Hoare分区方案的示例代码。如果使用迭代器代替索引,则不能使用low-1,并且分区函数需要稍作更改,以使用a [i] <枢轴而不是a [++ i] <枢轴来处理初始比较。高+1不是问题,因为这与“结束”迭代器相同。

int Partition(double a[], int low, int high)
{
    double pivot = a[low+(high-low)/2];
    int i = low - 1;
    int j = high + 1;
    while(1)
    {
        while(a[++i] < pivot);
        while(a[--j] > pivot);
        if(i >= j)
            return j;
        std::swap(a[i], a[j]);
    }
}

void QuickSort(double a[], int low, int high)
{
    if (low < high)
    {
        int index = Partition(a, low, high);
        QuickSort(a, low, index);             // not index - 1 for Hoare
        QuickSort(a, index + 1, high);
    }
}

像Hoare这样的示例分区方案,它使用后递增和后递减

int partition(double a[], int first, int last)
{
    double pivot = a[first+(last-first)/2]; // use middle for pivot
    while(first <= last) {
        while (a[first] < pivot)
            first++;
        while (a[last] > pivot)
            last--;
        if(first > last)
            break;
        std::swap(a[first],a[last]);
        first++;
        last--;
    }
    return first;       // index to 1st element of right part
}

void quicksort(double a[], int first, int last)
{
     if(first >= last)          // style change
        return;
    int index=partition(a, first, last);
    // index to 1st element of right part
    quicksort(a, first, index-1); 
    quicksort(a, index, last);  // not index+1 for this implementation 
}