如何获得quicksort分区以产生正确和预期的输出?

时间:2015-02-08 07:41:51

标签: java arrays algorithm sorting quicksort

这涉及来自https://stackoverflow.com/help/on-topic的“软件算法”,在这种情况下是快速排序算法

这是来自https://www.hackerrank.com/challenges/quicksort1

的练习编码问题(非竞赛)

基本上你应该列入一个清单,比如说

4 5 3 7 2

并围绕第一个元素进行分区,在本例中为4.预期输出为

3 2 4 5 7

然而,我得到的输出是

2 3 4 7 5 

以下是我进行分区的代码(基于https://courses.cs.washington.edu/courses/cse373/13wi/lectures/02-27/20-sorting3-merge-quick.pdf幻灯片16中的学习友好版本)

static void partition(int[] ar) {
       int toPartitionAround = ar[0];
       swap(ar, 0, ar.length - 1);
       int index = partition(ar, 0, ar.length - 2, toPartitionAround);
       swap(ar, index, ar.length - 1);
       printArray(ar);
   }   
   static int partition(int[] ar, int left, int right, int toAround) {
       while(left <= right) {
           while(ar[left] < toAround) {
               left ++;
           }
           while(ar[right] > toAround) {
               right --;
           }
           if(left <= right) {
               swap(ar, left, right);
               left ++;
               right --;
           }
       }
       return left;
   } 

   static void swap(int[] arrayNums, int index1, int index2) {
       int temp = arrayNums[index1];
       arrayNums[index1] = arrayNums[index2];
       arrayNums[index2] = temp;
   }

我可以对此进行修改以匹配预期的输出吗?我在技术上仍然得到一个可能正确的输出,因为我的输出确实遵循枢轴左侧的属性元素小于枢轴,并且枢轴右侧的元素大于枢轴?

我所做的是分配枢轴,将其移动到阵列的后面,然后围绕枢轴分割阵列的其余部分(从索引0到长度 - 2)。通过此输入,在通过阵列(3和5)时发生了一次交换。然后,当我从分区的结果中获取索引时,我将数据交换为该结果,这意味着我交换了4和5.

我是否遵循类似的流程来获得预期的输出?我看不出要替换什么。

2 个答案:

答案 0 :(得分:0)

在阅读了@ greybeard和@ Smac89的评论之后,我意识到我需要一种稳定的快速输入形式,稳定,因为在&#34;保留输入集的原始顺序,其中比较算法不区分两个或多个项目&#34;(https://softwareengineering.stackexchange.com/questions/247440/what-does-it-mean-for-a-sorting-algorithm-to-be-stable

对我而言,稳定的排序对于此次运行并不合理,因为比较算法确实区分了3和2,但是很好。有人可以澄清一下吗?

我提出的维护亲属的解决方案是创建两个ArrayLists,一个用于保存小于或等于pivot的值,另一个用于保存大于pivot的值。这样就保留了相对定位。(2将在3之后,就像在原始列表中一样)。然后我将两个ArrayLists中的值与枢轴一起移回原始的pivot。

如果有人遇到麻烦,这是我的代码解决方案

 static void partition(int[] ar) {
      List<Integer> smallerValues = new ArrayList<Integer>();
      List<Integer> biggerValues = new ArrayList<Integer>();
      int toPartitionAround = ar[0];
      for(int c=1;c<ar.length;c++) {
          if(ar[c] <= toPartitionAround) {
              smallerValues.add(ar[c]);
          } else {
              biggerValues.add(ar[c]);
          }
      }
      for(int c=0;c<smallerValues.size();c++) {
          ar[c] = smallerValues.get(c);
      }
      ar[smallerValues.size()] = toPartitionAround;
      for(int m=0;m<biggerValues.size();m++) {
          ar[m + smallerValues.size() + 1] = biggerValues.get(m);
      }
      printArray(ar); 
   }

答案 1 :(得分:0)

这有点令人困惑,不是吗。我所做的就是创建2个单独的列表,一个用于存储低于pivot的元素,另一个用于存储高于pivot的元素。然后,您只需打印出值。这是保留元素顺序的方法,您可以进行“就地”排序。但它也会消耗内存。