带函数指针参数的C语言插入排序实现错误排查
排查带比较函数指针的插入排序错误
结合你的测试场景(输入"rtsFi",预期"First",实际"iFstr"),且已验证比较函数正确性的前提下,问题大概率出在插入排序的元素移动逻辑上,以下是核心排查方向:
1. 检查是否保存待插入元素到临时变量
这是这类问题最常见的错误:直接操作原数组中的当前元素时,移动前面的元素会覆盖它,导致最后插入的是被篡改后的值。
错误示例(会覆盖待插入元素):
void insertion_sort(void *arr, int elem_size, int len, int (*cmp)(const void*, const void*)) { for (int i = 1; i < len; i++) { char *curr = (char*)arr + i * elem_size; int j = i - 1; // 移动元素时,curr指向的位置会被前面的元素覆盖 while (j >= 0 && cmp((char*)arr + j*elem_size, curr) > 0) { memcpy((char*)arr + (j+1)*elem_size, (char*)arr + j*elem_size, elem_size); j--; } // 这里的curr已经被覆盖,插入的不是原始值 memcpy((char*)arr + (j+1)*elem_size, curr, elem_size); } }
正确做法是先把待插入元素存到临时缓冲区,再移动元素:
void insertion_sort(void *arr, int elem_size, int len, int (*cmp)(const void*, const void*)) { char temp[elem_size]; // 临时存储待插入元素 for (int i = 1; i < len; i++) { // 先保存当前元素,避免被覆盖 memcpy(temp, (char*)arr + i * elem_size, elem_size); int j = i - 1; // 用临时变量和前面的已排序元素比较 while (j >= 0 && cmp((char*)arr + j*elem_size, temp) > 0) { memcpy((char*)arr + (j+1)*elem_size, (char*)arr + j*elem_size, elem_size); j--; } // 把临时变量插入正确位置 memcpy((char*)arr + (j+1)*elem_size, temp, elem_size); } }
2. 核对比较函数的调用参数顺序
如果你的compare_ignore_case_asc定义为:当a(忽略大小写)小于b时返回负数,相等返回0,大于返回正数。那循环里的判断逻辑必须是:cmp(已排序元素, 待插入元素) > 0
意思是"已排序元素比待插入元素大,需要后移"。如果参数写反(比如cmp(temp, (char*)arr+j*elem_size) < 0),会导致排序逻辑反向,出现不符合预期的结果。
3. 确认数组长度是否正确
如果是字符串排序,要确保排序的是有效字符长度(即strlen(arr)),而不是sizeof(arr)(后者会包含字符串末尾的\0,\0的ASCII值远小于字母,会被排到最前面,导致结果混乱)。
4. 手动模拟排序过程验证
拿你的测试数组{'r','t','s','F','i'},用正确的插入排序逻辑一步步推演:
- 第1步:
t和r比较,t更大,位置不变 →r,t,s,F,i - 第2步:
s和t比较(s更小),t后移;再和r比较(s更大),插入r和t之间 →r,s,t,F,i - 第3步:
F(忽略大小写是f)和t比较(f更小),t后移;和s比较(f更小),s后移;和r比较(f更小),r后移;插入到最前面 →F,r,s,t,i - 第4步:
i(忽略大小写是i)和t比较(i更小),t后移;和s比较(i更小),s后移;和r比较(i更小),r后移;和F比较(i更大),插入到F后面 →F,i,r,s,t→ 即"First"
对比你的代码执行过程,看哪一步和上面的推演不符,就能快速定位错误。
内容的提问来源于stack exchange,提问作者UnknownCoderinos
相关产品推荐
相关产品推荐

