快速排序代码解释[关闭]

Posted

技术标签:

【中文标题】快速排序代码解释[关闭]【英文标题】:Quick sort code explanation [closed] 【发布时间】:2012-08-15 18:45:10 【问题描述】:

这是我在实现快速排序算法时遇到的代码。您能解释一下这里的递归是如何工作的吗?

 void quickSort(int arr[], int left, int right)
 
  int i = left, j = right;
  int tmp;
  int pivot = arr[(left + right) / 2];

  /* partition */
  while (i <= j) 
        while (arr[i] < pivot)
              i++;
        while (arr[j] > pivot)
              j--;
        if (i <= j) 
              tmp = arr[i];
              arr[i] = arr[j];
              arr[j] = tmp;
              i++;
              j--;
    

/* recursion */
if (left < j)
    quickSort(arr, left, j);
if (i < right)
        quickSort(arr, i, right);

请注意,这不是家庭作业。

【问题讨论】:

你知道快速排序是如何工作的吗? 如果不是为了作业,请使用std::sort @Topo 是的,您将数组的值与作为数组元素的枢轴进行比较,根据它们是大于还是小于枢轴,您将它们发送到两个数组,然后排序时连接数组。 或多或少,是的。但快速排序的优势之一是您可以就地完成整个事情。所以没有“发送”和连接。 请注意,此实现已被破坏,因为它可能导致 O(n) 的递归深度(这将导致任何大型数组的堆栈溢出)。 【参考方案1】:

不确定“解释递归是如何工作的”是什么意思。但是给你:

您发布的函数需要一个整数数组和两个索引。它不会对整个数组进行排序,而只会对两个索引之间的部分进行排序,而忽略它们之外的任何内容。这意味着如果您传递第一个和最后一个索引,则相同的函数可以对整个数组进行排序,或者如果您传递不是数组第一个元素的索引的left 值和/或@987654322,则可以仅对子数组进行排序@不是最后一个元素的索引的值。

排序算法是众所周知的快速排序。作为枢轴,它使用中心元素(它也可以使用任何其他元素)。它将数组划分为less than (or equal to) pivot 子数组和greater than (or equal to) pivot 子数组,留下一个元素等于两个分区之间的主元。

然后它递归调用自己对两个分区进行排序,但只有在必要时才会这样做(因此递归调用之前的 ifs)。

该实现有效,但在许多方面都不是最佳的,并且可以改进。 以下是一些可能的改进:

    如果数组足够短,则切换到另一种排序算法 选择枢轴值作为三个值的中位数(通常是第一个、最后一个和中间) 最初将一个枢轴值移出数组(将其放在第一个或最后一个位置,并将焦点减少到数组的其余部分)然后更改测试以传递等于枢轴的值以减少涉及他们的交换。您将在最后进行最终交换时将枢轴值放回原处。如果您不遵循建议 2 并选择第一个/最后一个元素而不是本实施中的中间元素,这将特别有用。

【讨论】:

【参考方案2】:

回复较晚,但我只是添加了一些打印件,它可能有助于遇到此问题的人理解代码。

#include<iostream>
using namespace std;

void quickSort(int arr[], int left, int right)
 
  int i = left, j = right;
  int tmp;
  int pivot = arr[abs((left + right) / 2)];
  cout<<"pivot is"<<pivot<<endl;

  /* partition */
  while (i <= j) 
        while (arr[i] < pivot)
              i++;
        while (arr[j] > pivot)
              j--;
        if (i <= j) 
              cout<<"i and j are"<<i<<" "<<j<<"and corresponding array value is"<<arr[i]<<" " <<arr[j]<<endl;
              tmp = arr[i];
              arr[i] = arr[j];
              arr[j] = tmp;
              i++;
              j--;
              cout<<"entering first big while loop"<<endl;
         for(int i=0;i<7;i++)
    cout<<arr[i]<<" "<<endl ;
    

cout<<"recursion"<<endl;

/* recursion */
if (left < j)
    quickSort(arr, left, j);

if (i< right)
        quickSort(arr, i, right);

int main()
    int arr[7]= 2,3,8,7,4,9,1;
        for(int i=0;i<7;i++)
    cout<<arr[i]<<" " ;
    quickSort(arr,0,6);
    cout<<endl;
    for(int i=0;i<7;i++)
    cout<<arr[i]<<" " ;
int wait;
cin>>wait;
return 0;

【讨论】:

【参考方案3】:

这是您的答案——在常见情况下,两个递归调用都将被执行,因为它们上面的条件都为真。但是,在极端情况下,您可以让枢轴元素成为最大(或最小)元素。在这种情况下,您只需进行一次递归调用,这基本上会在从数组中删除枢轴元素后通过选择不同的枢轴来再次尝试该过程。

【讨论】:

实际上,如果其中一个测试失败,因为枢轴是最大值或最小值,另一个递归(如果调用)将处理一个较小的数组(短一个元素)。

以上是关于快速排序代码解释[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

凡人能看懂的冒泡排序和快速排序

C ++快速排序算法崩溃[关闭]

快速排序是一种分而治之的方法吗? [关闭]

将字典快速排序到 OrderedDict [关闭]

java快速排序引起的StackOverflowError异常

快速排序