C 如何在我的实现快速排序中防止堆栈溢出?

C 如何在我的实现快速排序中防止堆栈溢出?,c,quicksort,C,Quicksort,我的快速排序有问题。当我尝试按降序对数字数组排序时,我的指针没有穿过数组,堆栈溢出。也许问题不在指针上,但我看不出这个问题的解决方案 我的代码: #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <time.h> #include <stdbool.h> #include <assert.h> int Icmp(void* x

我的快速排序有问题。当我尝试按降序对数字数组排序时,我的指针没有穿过数组,堆栈溢出。也许问题不在指针上,但我看不出这个问题的解决方案

我的代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h> 
#include <time.h>
#include <stdbool.h>
#include <assert.h>
int Icmp(void* x, void* y);
bool SpecTest(int (*cmp)(const void*, const void*), int (*dcmp)(const void*, const void*));
int Dcmp(void* x, void* y);
void Quick_Sort(const void* ptr, int low, int high, size_t size, int (*cmp)(const void*, const void*));

int main(void)
{
    int (*cmp)(void* x, void* y) = Icmp;
    int (*dcp)(void* x, void* y) = Dcmp;
    assert(SpecTest(cmp, dcp));
    return 0;
}

bool SpecTest(int (*cmp)(const void*, const void*), int (*dcmp)(const void*, const void*))
{
    typedef struct testArr {
        int* arr;
        size_t size;
    }testArr;
    testArr s3;//Back sorted array struct
    s3.size = 100;
    if ((s3.arr = (int*)malloc(sizeof(int) * s3.size)) == NULL) {
        return false;
    }
    for (int i = 0; i < s3.size; i++) {
        s3.arr[i] = s3.size - i;
    }
    my_qsort(s3.arr, s3.size, sizeof(s3.arr[0]), cmp);
    return checksortInt(s3.arr, s3.size, cmp);
}
int Icmp(void* x, void* y)
{
    return (*(int*)x > * (int*)y) - (*(int*)x < *(int*)y);
}

int Dcmp(void* x, void* y)
{
    return (*(double*)x > * (double*)y) - (*(double*)x < *(double*)y);
}

void Swapper(void* x, void* y, size_t size)
{
    for (size_t i = 0; i < size; i++) {
        char tmp = ((char*)x)[i];
        ((char*)x)[i] = ((char*)y)[i];
        ((char*)y)[i] = tmp;
    }
}

bool checksortInt(int* parray, size_t size)
{
    for (size_t i = 0; i < size - 1; i++)
        if (parray[i] > parray[i + 1])
            return false;
    return true;
}

void my_qsort(const void* ptr, size_t count, size_t size, int (*cmp)(const void*, const void*))
{
    Quick_Sort(ptr, 0, count - 1, size, cmp);
}

void Quick_Sort(const void* ptr, int low, int high, size_t size, int (*cmp)(const void*, const void*))
{
    int i = low;
    int j = high;
    char* pivot = (char*)ptr + low * size;
    while (i <= j)
    {
        while (i < high && (cmp((char*)ptr + i * size, pivot) == -1))
            i++;
        while (j > low && cmp((char*)ptr + j * size, pivot) == 1)
            j--;
        if (i <= j) {
            Swapper((char*)ptr + i * size, (char*)ptr + j * size, size);
            i++;
            j--;
        }
    }
    if (j > low)
        Quick_Sort(ptr, low, j, size, cmp);
    if (i < high)
        Quick_Sort(ptr, i, high, size, cmp);
}
\define\u CRT\u SECURE\u NO\u警告
#包括
#包括
#包括
#包括
#包括
int Icmp(无效*x,无效*y);
bool SpecTest(int(*cmp)(常数无效*,常数无效*),int(*dcmp)(常数无效*,常数无效*);
int Dcmp(无效*x,无效*y);
void快速排序(const void*ptr、int low、int high、size\t size、int(*cmp)(const void*、const void*));
内部主(空)
{
int(*cmp)(无效*x,无效*y)=Icmp;
int(*dcp)(无效*x,无效*y)=Dcmp;
断言(SpecTest(cmp,dcp));
返回0;
}
bool SpecTest(int(*cmp)(常数无效*,常数无效*),int(*dcmp)(常数无效*,常数无效*)
{
typedef结构testArr{
int*arr;
大小;
}testArr;
testArr s3;//反向排序数组结构
s3.尺寸=100;
if((s3.arr=(int*)malloc(sizeof(int)*s3.size))==NULL){
返回false;
}
对于(int i=0;i*(int*)y)-(*(int*)x<*(int*)y);
}
int Dcmp(无效*x,无效*y)
{
返回(*(双*)x>*(双*)y)-(双*)x<*(双*)y);
}
无效交换程序(无效*x,无效*y,大小\u t大小)
{
对于(大小i=0;i阵列[i+1])
返回false;
返回true;
}
无效我的排序(常数无效*ptr,大小计数,大小大小,整数(*cmp)(常数无效*,常数无效*)
{
快速排序(ptr,0,计数-1,大小,cmp);
}
void快速排序(const void*ptr、int low、int high、size\t size、int(*cmp)(const void*、const void*))
{
int i=低;
int j=高;
char*pivot=(char*)ptr+low*大小;
而(i low&&cmp((char*)ptr+j*大小,pivot)==1)
j--;
如果(i低)
快速排序(ptr、low、j、大小、cmp);
如果(i<高)
快速排序(ptr、i、高、大小、cmp);
}
例如:

输入[]:按降序排列的数字数组


输出[]:QuickOut.exe中0x005D1889处未处理的异常:0xC00000FD:堆栈溢出(参数:0x00000001,0x008A2F24)。

如果需要对大型数组进行排序,并且担心最坏情况下的数据模式会导致堆栈溢出,则快速排序可以在较小的分区上递归,并在较大的分区上循环,这将避免堆栈溢出,但最坏情况下的时间复杂度仍然是O(n^2)


输入有多大?这真的不应该溢出堆栈(如果在一些普通PC平台上运行)。您可能有一些错误。Have
Icmp
简单地
返回(*(int*)x>*(int*)y)-(*(int*)x<*(int*)y)。您的
Quick\u Sort
有效——您可能需要解决一些棘手的问题。除此之外,在
for(int i=0;i
--只需将
int
更改为
size\u t
即可解决此问题。您对
Quick\u Sort
的调用必须使用
low=0
high=n-1
。尝试使用已排序的数组运行代码。您会发现缺少一两个退出条件。@SkivHisink我用
int a[]测试了您的代码{9,3,6,1,0,5,7,2,8,4};
和升序排序和降序排序--没有问题。我怀疑您通过传递
参数时出错了。我添加了缺少的函数。您的函数没有对排序数组进行排序。我已经等待了7分钟,但没有发生任何问题(程序工作,但保留此函数)@SkivHisink-我更新了我的答案。我通常使用上面的第二个示例,它不存在I或j超过子数组末端的问题。谢谢,但它没有帮助。我使用数组中数字的随机排列解决了这个问题,但我认为这是欺骗。@SkivHisink-对于排序或反向排序的数组,使用
pivot=(字符*)ptr+((低+高)/2)*size;
将解决这些特定情况下的空间和时间问题。上面的示例处理最坏情况的数据模式,除非故意创建最坏情况的数据模式,否则这些数据模式实际上是罕见的。我更新了我的答案。@SkivHisink-我添加了第三个没有堆栈溢出预防的示例,这更简单。对于原始的p问题是只有100个元素需要排序,我的原始代码没有出现堆栈溢出,所以我仍然不知道问题出在哪里。您可能需要尝试对500万到2000万个元素进行排序,并比较运行时间和/或查看是否存在堆栈溢出问题。
void Quick_Sort(const void* ptr, int low, int high, size_t size, int (*cmp)(const void*, const void*))
{
    int i;
    int j;
    char *pivot;
    while(low < high){
        i = low;
        j = high;
        pivot = (char*)ptr + ((low+high)/2) * size;
        while (i <= j)
        {
            while (cmp((char*)ptr + i * size, pivot) == -1)
                i++;
            while (cmp((char*)ptr + j * size, pivot) ==  1)
                j--;
            if (i <= j) {
                Swapper((char*)ptr + i * size, (char*)ptr + j * size, size);
                i++;
                j--;
            }
        }
        if (j < low)                  // adjust so low <= j <= i <= high
            j = low;
        if (i > high)
            i = high;
        if(j - low <= high - i){
                Quick_Sort(ptr, low, j, size, cmp);
            low = j + 1;
        } else {
            if (i < high)
                Quick_Sort(ptr, i, high, size, cmp);
            high = i - 1;
        }
    }
}
void Quick_Sort(const void* ptr, int low, int high, size_t size, int (*cmp)(const void*, const void*))
{
    int i;
    int j;
    char *pivot;
    while(low < high){
        i = low-1;
        j = high+1;
        pivot = (char*)ptr + ((low+high)/2) * size;
        while (1)
        {
            while (cmp((char*)ptr + ++i * size, pivot) == -1);
            while (cmp((char*)ptr + --j * size, pivot) ==  1);
            if (i >= j)
                break;
            Swapper((char*)ptr + i * size, (char*)ptr + j * size, size);
        }
        if(j - low <= high - j){
            Quick_Sort(ptr, low, j, size, cmp);
            low = j+1;
        } else {
            Quick_Sort(ptr, j+1, high, size, cmp);
            high = j;
        }
    }
}
void Quick_Sort(const void* ptr, int low, int high, size_t size, int (*cmp)(const void*, const void*))
{
    int i;
    int j;
    char *pivot;
    if(low >= high)
        return;
    i = low-1;
    j = high+1;
    pivot = (char*)ptr + ((low+high)/2) * size;
    while (1)
    {
        while (cmp((char*)ptr + ++i * size, pivot) == -1);
        while (cmp((char*)ptr + --j * size, pivot) ==  1);
        if (i >= j)
            break;
        Swapper((char*)ptr + i * size, (char*)ptr + j * size, size);
    }
    Quick_Sort(ptr, low, j, size, cmp);
    Quick_Sort(ptr, j+1, high, size, cmp);
}