使用第一个元素作为枢轴快速排序

时间:2014-09-01 15:08:18

标签: java algorithm pivot quicksort divide-and-conquer

我通过选择第一个元素作为枢轴来实现快速排序。它适用于一般测试用例,但考虑到数组反向排序的情况,例如5 4 3 2 1.我理解它在哪里引发运行时错误。但我无法正确修复它。第一个元素的实现是否正确?请提出修改建议。

 public static void quicksort(int low,int high)
  {

   if(low<high) 
   {
    int temp=0;
    int pivot=a[low];                     
    int large_index=low+1;
    int small_index=high;

    while(large_index<=small_index)
    {
      while(a[small_index]>pivot)
      small_index--;

      while(a[large_index]<pivot) 
      large_index++; 

      if(large_index<=small_index)
       {
       temp = a[large_index];
       a[large_index]= a[small_index];
       a[small_index]= temp;
       large_index++;
       small_index--;
      }
     }

     temp = a[small_index];
     a[small_index]= a[low];
     a[low]= temp;


    quicksort(low,small_index-1);
    quicksort(small_index+1,high);
   }

   }

3 个答案:

答案 0 :(得分:2)

存在多个缺陷:

  

a)在循环外不必要的交换

     

temp = a [small_index]; a [small_index] = a [low]; a [low] = temp;

     

b)large_index的初始化不正确。

     

c)调用递归函数而不检查值   small_index和large_index。

我已经纠正了它们,

现在该功能将如下所示:

if (low < high) {
            int temp = 0;
            int pivot = a[low];
            int large_index = low;
            int small_index = high;

            while (large_index <= small_index) {
                while (a[small_index] > pivot)
                    small_index--;

                while (a[large_index] < pivot)
                    large_index++;

                if (large_index <= small_index) {
                    temp = a[large_index];
                    a[large_index] = a[small_index];
                    a[small_index] = temp;
                    large_index++;
                    small_index--;
                }
            }

            if(low < small_index)
            {
                quicksort(low, small_index);
            }
            if(large_index < high)
            {
                quicksort(large_index, high);
            }
        }

现在,观察你的代码中的变量:(除非输入没有排序,否则你的代码将在任何给定输入的最后一次迭代中失败)

考虑输入2,1

1st iteration:

pivot = 2
large_index = 1;
small_index = 1;


while1:
1<=1 -> true
    while2: 1>2 false.
    while3: 1<2 true. -> large_index++
                2nd time in while loop large_index =2 which is > the size of a.
  

导致IndexArrayOutOfBounds。

这表明您对 large_index的初始化错误。

应该是: large_index = low ;而不是低+ 1;

希望这有帮助。

答案 1 :(得分:0)

以上循环继续在high上方,当large_index已经从枢轴上方开始时,它发生的枢轴大于位于其后面的每个元素:

while(a[large_index]<pivot) 
large_index++; 

当然可能还有其他错误。

答案 2 :(得分:0)

经过一些尝试,我能够制作Quicksort功能,现在工作正常。 @BatScream我仍然在我的代码中使用了small_index = low + 1。所以这不是我猜的错误。原始的快速排序算法遵循这种机制。如需参考,请观看Princeton教授Robert Sedgewick关于QuickSort的讲座。请注意编辑的快速排序算法是否存在缺陷。

public static void quicksort(int low,int high)
 {

   if(low<high) 
   {
    int temp=0;
    int pivot=a[low];                     
    int large_index=low+1;
    int small_index=high;

    while(large_index<small_index)
  {

     while(a[large_index]<pivot) {
     if(large_index==high) 
     break;
     large_index++; 
   } 

    while(a[small_index]>pivot) 
   {
     if(small_index==low) 
     break;
     small_index--; 
   }

   if(large_index<small_index) {
     temp = a[large_index];
     a[large_index]= a[small_index];
     a[small_index]= temp;
     large_index++;
     small_index--; 
    }
  }   

    if(a[small_index]<pivot) {                               
       temp = a[small_index];
       a[small_index]= a[low];
       a[low]= temp;
  }

     if(low<small_index)                                    //Recursively sort the left half.
    {
     quicksort(low,small_index-1);
    }

    if(high>small_index)                                    //Recursively sort the right half.
   {
    quicksort(small_index+1,high);
    }
  }

  }