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
相关产品推荐
相关产品推荐

