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

C语言自定义结构体数组快速排序分区函数索引异常及外部无效问题

问题分析与修复方案

咱们一步步拆解你遇到的两个问题:

1. 初始partition函数的索引异常问题

你的第一个版本代码里,核心问题是临时数组tempArr的索引使用错误,触发了内存越界的未定义行为(比如bigger莫名变为0)。

问题细节:

  • tempArr的大小是right+1 - left,它的有效索引范围是0到right-left(数组索引从0开始)。
  • 但你直接用smaller(初始为left)和bigger(初始为right)作为tempArr的索引,这会直接越界!比如当left=2、right=5时,tempArr长度为4,索引只能到3,但bigger初始是5,访问tempArr[5]会踩内存,导致变量值被篡改等奇怪问题。

修复后的初始版本代码:

我们需要把tempArr的索引改为从0开始计数,最后拷贝回原数组时再偏移left:

int partition(Student studentsArray[], int left, int right) { 
    int arrLen = right - left + 1;
    Student tempArr[arrLen]; 
    int smaller = 0; // 从tempArr的0索引开始
    int bigger = arrLen - 1; // tempArr的最后一个有效索引
    for(int i = left; i < right; i++) { 
        if(stringComperator(studentsArray[i].name, studentsArray[right].name) > 0) { 
            tempArr[bigger] = studentsArray[i]; 
            bigger--; 
        } else { 
            tempArr[smaller] = studentsArray[i]; 
            smaller++; 
        } 
    } 
    tempArr[smaller] = studentsArray[right]; 
    // 把tempArr内容拷贝回原数组的[left, right]区间
    for(int i = 0; i < arrLen; i++) { 
        studentsArray[left + i] = tempArr[i]; 
    } 
    return left + smaller; // 返回原数组中的基准位置
}

2. 更新后代码外部数组未变化的问题

你的第二个版本有两个关键错误,直接导致外部数组看不到修改:

  • 循环的j起始值错误,应该从left开始而非0,否则会错误修改数组前left个无关元素。
  • 最后一步交换的是数组元素和局部变量pivot,而非原数组中的基准元素(studentsArray[right]),局部变量的修改不会影响外部数组。

修复后的swap版本代码:

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

int partition(Student studentsArray[], int left, int right) { 
    Student pivot = studentsArray[right]; 
    int i = left; 
    // j从left开始遍历到right-1,只处理当前区间内的元素
    for(int j = left; j < right; j++) { 
        if(stringComperator(studentsArray[j].name, pivot.name) < 0) { 
            swap(&studentsArray[i], &studentsArray[j]); 
            i++; 
        } 
    } 
    // 把原数组中的基准元素(right位置)和i位置交换,完成分割
    swap(&studentsArray[i], &studentsArray[right]); 
    return i; 
}

为什么之前外部数组没变化?

你之前写的swap(&studentsArray[i],&pivot);是把数组元素和局部变量pivot交换,pivot只是studentsArray[right]的拷贝,这个操作只会修改局部变量的值,原数组的right位置元素完全没动。改成交换&studentsArray[i]和&studentsArray[right]后,才真正把基准元素放到了正确的分割位置,外部数组也能同步看到修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 09:48:11