使用最小元素地址查找函数实现C数组排序时末元素未排序的修正方法
核心问题定位
两个逻辑偏差共同导致排序时最后一个元素完全不参与比较:
findMin遍历边界错误
你传入的end指针始终指向区间内最后一个有效元素,此时通过指针减法计算的size = end - start是两指针的元素间隔数:比如start指向数组首元素、end指向数组最后一个元素时,两者间隔9个位置,实际需要遍历的元素总数是size + 1个。但当前循环条件是x < size,实际只遍历到end-1位置的元素,永远将end指向的最后一个元素排除在比较范围外,这是最后一个元素未被纳入排序的直接原因。sort函数选择排序逻辑冗余错位
当前每轮循环先调用findMin查找整个数组的最小值做前置判断,判断通过后又重新调用一次findMin查找当前未排序区间的最小值完成交换,不仅重复调用函数造成无意义开销,还偏离了选择排序的核心逻辑:每轮仅需在当前未排序区间内找到最小值,直接和区间起始位置的元素交换即可,无需多余的前置判断。
最小改动修正方案
完全保留原有函数的传参约定(end传指向最后一个有效元素的指针),只需两处调整:
- 修改
findMin的循环边界,将遍历条件从x < size改为x <= size,确保end指向的元素被纳入比较范围 - 简化
sort函数的循环逻辑:每轮直接获取当前未排序区间的最小值地址,判断最小值位置是否与当前区间起始位置一致,不一致则直接交换,去掉多余判断和重复函数调用
修正后可运行的完整代码
#include <stdio.h> int *findMin(int *start, int *end) ///function to return the adress of the smallest array element { int *min = start; int x; int size = (end - start); // 修正循环边界:覆盖end指针指向的最后一个元素 for(x = 0; x <= size; x++) { if (*(start + x) < *min) min = (start + x); } return min; } void sort(int *start, int *end) ///funtion to sort the array in ascending order { int x, temp; int size = (end - start); for (x = 0; x < size; x++) { // 单次调用获取当前未排序区间的最小值地址,避免重复计算 int *minPos = findMin(start + x, end); // 仅当最小值不在当前位置时执行交换 if (minPos != start + x) { temp = *minPos; *minPos = *(start + x); *(start + x) = temp; } } } int main() { int arr[10] = {5,11,3,12,17,25,1,9,14,2}; sort(arr, &arr[9]); for(int i = 0; i < 10; i++) printf("%d ", arr[i]); printf("\n"); }
修正后程序输出为:
1 2 3 5 9 11 12 14 17 25,原数组最后一个元素2已正常参与排序流程。
内容的提问来源于stack exchange,提问作者alminacck
相关产品推荐
相关产品推荐

