算法作业:快速排序代码中的if语句为何被跳过?
问题分析与修正:快速排序代码中条件块被跳过的原因及目标逻辑调整
1. 条件块被跳过的直接原因
你写的if (right < i)条件完全写反了。初始状态下:
i = left = 0right = s_lower.size() - 1,针对你的测试用例,s_lower的元素是[-1,2,-3,4],所以right=3
此时right < i即3 < 0,显然不成立,因此这个if块直接被跳过。正确的逻辑应该是用while (right > i)作为循环条件(划分过程需要持续到指针相遇),而非单次判断的if。
2. 代码逻辑的核心问题
除了条件写反,你的代码整体既偏离了“负数在前、零居中、正数在后”的目标,也不符合快速排序的正确实现逻辑:
- 把原数组从中间切开分成两个子数组的操作,和目标需求无关,也不是快速排序的标准划分方式
- 快速排序需要递归处理子数组,但你的代码没有任何递归逻辑,仅做了一次无效划分
- 完全没有针对“负、零、正”三分区的处理逻辑,而是在尝试实现普通单枢轴快速排序,且逻辑混乱
3. 修正方案
修正当前快速排序的条件问题
将被跳过的部分替换为正确的划分逻辑:
// 修正后的快速排序划分逻辑 while (right > i) { // 从右往左找第一个小于等于枢轴的元素 while (right > i && s_lower[right] > pivot) { right--; } // 从左往右找第一个大于等于枢轴的元素 while (right > i && s_lower[i] < pivot) { i++; } if (right > i) { swap(s_lower[i], s_lower[right]); i++; right--; } } swap(s_lower[left], s_lower[right]);
调整后指针会正常移动并交换元素,不会再跳过核心逻辑块。
针对“负、零、正”三分区的最优实现(推荐)
如果你的目标是将数组按“负数在前、零居中、正数在后”排列,无需用普通快速排序,三指针法更高效且逻辑清晰:
#include <iostream> #include <vector> #include <algorithm> using namespace std; void partitionNegZeroPos(vector<double>& u) { int left = 0; int mid = 0; int right = u.size() - 1; while (mid <= right) { if (u[mid] < 0) { swap(u[left], u[mid]); left++; mid++; } else if (u[mid] == 0) { mid++; } else { // 处理正数 swap(u[mid], u[right]); right--; } } } int main() { vector<double> unsorted = {-1, 2, -3, 0, 5, 6, -7, 0, 9}; partitionNegZeroPos(unsorted); for (double num : unsorted) { cout << num << " "; } return 0; }
该方法时间复杂度为O(n),空间复杂度为O(1),完全匹配你的需求。
4. 其他问题说明
- 函数开头的
if (u[0] < u[u.size() - 1])判断毫无意义,会导致若数组首元素大于尾元素时,整个函数直接不执行 - 快速排序必须通过递归处理划分后的子数组才能完成排序,你当前的代码仅做了一次划分,无法完成完整排序
内容的提问来源于stack exchange,提问作者Alexander Reams
相关产品推荐
相关产品推荐

