C语言数组奇偶位分序排序 oddSort函数无输出问题排查
改造选择排序实现奇偶位分别排序问题排查
问题背景
- 作业需求:改造选择排序算法,对数组所有奇数位置元素做升序排序,所有偶数位置元素做降序排序
- 故障现象:编写
oddSort函数后接入测试数组运行,程序无任何输出;逻辑相近的evenSort推测存在同类问题 - 前置验证:开发者已单独测试
swap、findLastOdd函数,认为二者可正常工作
现有问题代码
oddSort 实现
void oddSort(int arrSize, int arr[]){ int i; int lastOdd; int currentMin; lastOdd = findLastOdd(arrSize); for(i=0; i<lastOdd; i+=2){ if(i=0){ currentMin = arr[i]; } else if (arr[i] < currentMin){ swap(&arr[i], ¤tMin); } } }
测试入口main函数
int main(){ int arrayOne[10] = {246, 101, 223, 228, 1, 249, 99, 111, 191, 126}; int i; oddSort(10, arrayOne); for(i=0; i<10; i++){ printf("%d ", arrayOne[i]); } return 0; }
其余工具函数实现
int findLastOdd(int someNumber){//to give the oddSort function a stopping point if(someNumber % 2 == 0){ return someNumber - 1; } else{ return someNumber; } } int findLastEven(int someNumber){//to give the evenSort function a starting point if(someNumber % 2 == 0){ return someNumber; } else{ return someNumber - 1; } } void swap (int* a, int* b){// swaps two array elements using pointers int temp; temp = *a; *b = *a; *b = temp; }
问题定位
- 核心故障原因:条件判断误写为赋值,触发死循环
oddSort循环内的判断if(i=0)是赋值操作而非相等比较(相等比较应写为i==0),每次进入判断都会将i重置为0,导致for循环的i+=2永远无法让i增长到退出循环的阈值,程序卡死在循环中,无法执行后续打印逻辑,因此没有任何输出。 - swap函数逻辑错误,无法完成元素交换
当前swap实现仅对*b赋值,从未修改*a的值,执行后两个指针指向的内存值不会完成交换,属于未排查出的隐藏bug。 - oddSort不符合选择排序的实现逻辑
标准选择排序每轮遍历需要定位未排序区间的最值下标,再和当前轮次的起始位置元素交换。当前逻辑仅记录currentMin的值,没有记录最小值对应的数组下标,遍历范围也没有覆盖所有未排序元素,就算修复死循环问题也无法得到正确排序结果。 - findLastEven逻辑和需求不匹配
若按日常习惯从1开始计数位置,奇数位置对应数组下标0、2、4...(偶数下标),偶数位置对应数组下标1、3、5...(奇数下标)。当前findLastEven返回的是<=传入值的最大偶数,无法定位到最后一个偶数位置的下标,会漏掉排序元素。 - 注意:正式开发前需要先和题目确认位置计数规则,是从0开始计数还是从1开始计数,避免遍历下标错位。
修复参考
1. 修复swap函数
void swap (int* a, int* b){ int temp; temp = *a; *a = *b; *b = temp; }
2. 修复后的oddSort(按1计数奇数位置升序,选择排序实现)
void oddSort(int arrSize, int arr[]){ int i, j; // 数组最大下标为arrSize-1,传入找最后一个奇数位置的下标 int lastOdd = findLastOdd(arrSize - 1); for(i=0; i<=lastOdd; i+=2){ int minIdx = i; // 遍历i之后所有奇数位元素,找最小值下标 for(j=i+2; j<=lastOdd; j+=2){ if(arr[j] < arr[minIdx]){ minIdx = j; } } // 将最小值交换到当前已排序位置 if(minIdx != i){ swap(&arr[i], &arr[minIdx]); } } }
3. 修复findLastEven逻辑
int findLastEven(int someNumber){ // 返回<=传入值的最大奇数,对应1计数的最后一个偶数位置下标 if(someNumber % 2 == 1){ return someNumber; } else{ return someNumber - 1; } }
4. evenSort参考实现(按1计数偶数位置降序)
void evenSort(int arrSize, int arr[]){ int i, j; int lastEven = findLastEven(arrSize - 1); for(i=1; i<=lastEven; i+=2){ int maxIdx = i; // 遍历i之后所有偶数位元素,找最大值下标 for(j=i+2; j<=lastEven; j+=2){ if(arr[j] > arr[maxIdx]){ maxIdx = j; } } if(maxIdx != i){ swap(&arr[i], &arr[maxIdx]); } } }
调用时先后执行
oddSort(10, arrayOne)和evenSort(10, arrayOne)即可得到符合要求的排序结果。
内容的提问来源于stack exchange,提问作者David Mdzinarishvili
相关产品推荐
相关产品推荐

