You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言快速排序处理大数组时出现Segmentation Fault求助

C语言快速排序大数组触发Segmentation Fault的问题修复

问题描述

实现的C语言快速排序在处理元素数少于30000的数组时运行正常,但处理更大数组时,在swap(&vet[sup], &vet[(sup-inf+1)/2]);行触发Segmentation Fault,不确定是栈溢出还是指针问题导致。

出错代码

void swap(int* a, int* b){
    int temp = *a;
    *a = *b;
    *b = temp;
} 
int partition(int inf, int sup, int vet[]){
    while (inf<sup){
        while (vet[inf]<=vet[sup] && inf<sup){inf++;}
        while (vet[inf]<=vet[sup] && inf<sup){sup--;}
        if (inf<sup){swap(&vet[inf], &vet[sup]);}
    }
    return inf;
}
void median (int inf, int sup, int vet[]){ //select the median of the first, last and midle value of the vector
    if (vet[inf]>vet[(sup-inf+1)/2])
        swap(&vet[inf], &vet[(sup-inf+1/2)]);
    if (vet[sup]>vet[(sup-inf+1)/2])
        swap(&vet[sup], &vet[(sup-inf+1)/2]);  
    else if (vet[sup]<vet[inf])
        swap(&vet[sup], &vet[inf]);    
}
void quicksort(int inf, int sup, int vet[]){
    if (inf<sup){
        median(inf, sup, vet);    
        int piv=partition(inf, sup, vet);
        quicksort(inf, piv-1, vet);
        quicksort(piv+1, sup, vet);
    }
}

错误分析与修复

1. 中位数索引计算错误(直接触发越界)

median函数的中间元素索引逻辑完全错误:

  • 当前用(sup-inf+1)/2计算的是子数组长度的一半,而非数组的实际索引。正确的中间索引应为inf + (sup - inf) / 2(避免整数溢出的安全写法),需要加上子数组的起始位置inf才能定位到正确元素。
  • 代码存在笔误:swap(&vet[inf], &vet[(sup-inf+1/2)]);中1/2是整数除法,结果为0,导致索引计算彻底失效。

修复后的median函数:

void median(int inf, int sup, int vet[]) {
    int mid = inf + (sup - inf) / 2; // 正确定位子数组的中间元素
    // 将中位数交换到sup位置,作为partition的基准
    if (vet[inf] > vet[mid])
        swap(&vet[inf], &vet[mid]);
    if (vet[sup] > vet[mid])
        swap(&vet[sup], &vet[mid]);
    if (vet[sup] < vet[inf])
        swap(&vet[sup], &vet[inf]);
}

2. 递归深度过大导致栈溢出(大数组场景)

快速排序最坏情况下递归深度为O(n),当数组元素数量过大时,递归调用栈会超出系统默认栈容量(通常为几MB),触发栈溢出。

解决方法:采用尾递归优化,优先递归处理较小的子数组,较大的子数组用循环代替递归,大幅降低递归深度:

void quicksort(int inf, int sup, int vet[]) {
    while (inf < sup) {
        median(inf, sup, vet);
        int piv = partition(inf, sup, vet);
        // 递归处理更小的子数组,减少栈占用
        if (piv - inf < sup - piv) {
            quicksort(inf, piv - 1, vet);
            inf = piv + 1;
        } else {
            quicksort(piv + 1, sup, vet);
            sup = piv - 1;
        }
    }
}

3. Partition函数逻辑错误

原partition的双向扫描条件错误,两个循环均使用vet[inf]<=vet[sup],会导致无法正确划分元素,甚至出现死循环。修复为标准的单边扫描实现:

int partition(int inf, int sup, int vet[]) {
    int pivot = vet[sup]; // 取中位数所在的sup位置为基准
    int i = inf - 1; // 记录小于等于基准的元素的最后位置
    for (int j = inf; j < sup; j++) {
        if (vet[j] <= pivot) {
            i++;
            swap(&vet[i], &vet[j]);
        }
    }
    swap(&vet[i + 1], &vet[sup]); // 将基准放到正确的划分位置
    return i + 1;
}

最终修复后的完整代码

#include <stdio.h>

void swap(int* a, int* b){
    int temp = *a;
    *a = *b;
    *b = temp;
} 

int partition(int inf, int sup, int vet[]) {
    int pivot = vet[sup];
    int i = inf - 1;
    for (int j = inf; j < sup; j++) {
        if (vet[j] <= pivot) {
            i++;
            swap(&vet[i], &vet[j]);
        }
    }
    swap(&vet[i + 1], &vet[sup]);
    return i + 1;
}

void median(int inf, int sup, int vet[]) {
    int mid = inf + (sup - inf) / 2;
    if (vet[inf] > vet[mid])
        swap(&vet[inf], &vet[mid]);
    if (vet[sup] > vet[mid])
        swap(&vet[sup], &vet[mid]);
    if (vet[sup] < vet[inf])
        swap(&vet[sup], &vet[inf]);
}

void quicksort(int inf, int sup, int vet[]) {
    while (inf < sup) {
        median(inf, sup, vet);
        int piv = partition(inf, sup, vet);
        if (piv - inf < sup - piv) {
            quicksort(inf, piv - 1, vet);
            inf = piv + 1;
        } else {
            quicksort(piv + 1, sup, vet);
            sup = piv - 1;
        }
    }
}

// 测试用例
int main() {
    int arr[100000];
    for (int i = 0; i < 100000; i++) {
        arr[i] = 100000 - i;
    }
    quicksort(0, 99999, arr);
    for (int i = 0; i < 10; i++) {
        printf("%d ", arr[i]);
    }
    return 0;
}

内容的提问来源于stack exchange,提问作者Thallysson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 16:09:55