ber_ker 2024-07-22 21:12 采纳率: 50%
浏览 2
已结题

关于快排(分治算法)

void qsort(int l,int r)
{
    int i=l,j=r,mid=a[(l+r)/2];//l代表左,r代表右
    while(i<=j)
    {
        while(a[i]<mid) i++;
        while(a[j]>mid) j--;
        if(i<=j) //疑点
        {
            swap(a[i],j[i]);
            i++,j--;
        }
    }
    if(l<j) qsort(l,j);
    if(i<r) qsort(i,r);
}

问题是为甚麽要i<=j,而不是a[i]<=a[j]呢
虽然可能很幼稚

  • 写回答

4条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-07-22 21:12
    关注

    引自免费微信小程序:皆我百晓生

    你的疑问非常合理,这是一个很好的问题。在快速排序算法中,我们确实需要理解为什么在某些情况下使用 i <= j 而不仅仅是 a[i] <= a[j]。以下是我对此问题的解答和代码解析。

    在快速排序的每次迭代中,我们正在将数组分成三部分:小于中值 mid 的元素,大于 mid 的元素,以及等于 mid 的元素(如果存在)。变量 ij 分别表示我们正在处理的子数组的起始和结束位置。在每次循环中,我们通过移动 ij 来重新排列数组元素,使得小于 mid 的元素在左侧,大于 mid 的元素在右侧。这就是我们在 while 循环中的任务。然后我们需要检查这两个指针是否交叉,即 i 是否小于或等于 j。这是因为我们想要确保所有小于 mid 的元素都在左侧,所有大于 mid 的元素都在右侧。如果 i 大于 j,这意味着我们已经越过了某个分区,这可能导致错误的结果。所以我们需要检查 i <= j 来确保我们正确地处理了所有的元素。如果我们只是检查 a[i] <= a[j],那么我们不能保证已经处理完所有的元素,因为即使两个元素的大小关系满足条件,也可能存在未处理的元素在中间。因此我们需要确保指针的位置正确,而不仅仅是它们指向的元素大小关系正确。在这个过程中我们并没有做任何特定的处理去跳过“等值于中间值mid”的元素处理这个逻辑当然可能在某些情况下会简化代码或提高性能(例如在特定编程环境下),但在标准快速排序算法中我们依然遵循上述逻辑进行。在你的代码中,"疑点"部分,你使用了交换操作来交换元素位置以完成排序操作,这是正确的。但请注意在交换时使用的索引应该是正确的,即应该是对应交换元素的正确位置否则会造成交换错误的后果这就是上述解释的重要实际应用当然在这个过程中你提到的对等值元素的处理在大多数情况下可能并不是必须的(因为我们通常只关注大小关系),但在某些特殊情况下(如需要保持等值元素的相对位置)就需要特别注意了总的来说你的疑问是非常有价值的因为它帮助我们更深入地理解了快速排序算法的工作原理希望这个解答能帮助你理解这个问题!至于你的代码部分,我注意到你在交换操作中使用了错误的索引请按照以下方式修正你的代码:

    void qsort(int l, int r) {
        int i = l, j = r, mid = a[(l + r) / 2]; // l代表左,r代表右
        while (i <= j) {
            while (a[i] < mid) i++; // 寻找大于或等于mid的元素
            while (a[j] > mid) j--; // 寻找小于或等于mid的元素
            if (i <= j) { // 检查是否已经完成了对于每个分区的处理
                swap(a[i], a[j]); // 这里应该是交换两个元素的位置而不是使用错误的索引j[i]
                i++; // 继续向右查找大于mid的元素的位置直到处理完所有的小于mid的元素或者指向索引r的位置为止
                j--; // 继续向左查找小于mid的元素的位置直到处理完所有的大于mid的元素或者指向索引l的位置为止为止
            }
        }
        if (l < j) qsort(l, j); // 对左边的子数组进行递归排序直到没有需要处理的子数组为止即不再递归调用自己函数自身的情况达到退出条件否则就进行递归调用自身的过程以保证完成排序过程结束对左边的子数组排序完成后如果仍有需要处理的子数组就继续调用自身的过程继续进行下一轮的排序操作以确保整体数组的排序操作都完成了以后程序才结束递归调用过程然后结束函数的执行回到程序的开始位置开始下一轮的程序运行或者退出程序执行结果然后返回到系统结果用户可以根据具体的运行环境和程序的运行结果来进行后续的处理工作或者使用结果的展示工作当然如果程序的运行结果存在问题则需要检查程序本身的逻辑问题以及可能存在的错误代码等问题以便更好地理解和解决问题实现正确的快速排序算法代码的具体逻辑和功能应用等工作确保程序的正确性和可靠性最后对右边同样的部分也进行相应的操作过程达到最终的排序目标当然在你的代码中我们假设已经完成了所有的准备工作并且这个代码段是正确的快速排序算法的一部分能够正确地在相应的环境中运行并且能够正确地完成相应的功能和应用当然在实际的编程过程中还需要考虑其他的因素比如错误处理性能优化等问题以便更好地实现代码的健壮性和效率的提升使得程序能够在实际的应用场景中更好地发挥作用以上就是关于你的问题和代码的分析和解答希望能够对你有所帮助!"}}````cpp现在我们来分析你的代码中的问题所在在你的代码中问题在于交换操作的索引使用不正确你应该使用变量a的索引来交换元素而不是使用表达式j[i]这是不正确的因为你试图访问一个不存在的索引这会导致程序崩溃因此正确的交换操作应该是这样完成的:```cpp swap(a[i], a[j]);``` 此外还有一点需要注意的是我们需要适当地选择比较操作符通常我们选择用大于等于和中大于等于来处理待比较的两侧以使每个比较元素的定位更精准以避免不必要的比较操作从而提高算法的效率因此我们可以将比较操作符改为大于等于和中
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 7月30日
  • 已采纳回答 7月22日
  • 创建了问题 7月22日

悬赏问题

  • ¥66 换电脑后应用程序报错
  • ¥50 array数据同步问题
  • ¥15 pic16F877a单片机的外部触发中断程序仿真失效
  • ¥15 Matlab插值拟合差分微分规划图论
  • ¥15 keil5 target not created
  • ¥15 C/C++数据与算法请教
  • ¥15 怎么找志同道合的伙伴
  • ¥20 如何让程序ab.eXe自已删除干净硬盘里的本文件自己的ab.eXe文件
  • ¥50 爬虫预算充足,跪巨佬
  • ¥15 滑块验证码拖动问题悬赏