简体   繁体   English

Quicksort可视化?

[英]Quicksort visualization?

I'm fairly new to programming and would like some visual representation of the quicksort algorithm using median-of-three partitioning and a cutoff of 3. 我是编程新手,并且希望使用三分位数分割法和3的临界值对quicksort算法进行可视化表示。

I would like to see the entire iterative process because the Java algorithm is tough to understand for me. 我希望看到整个迭代过程,因为Java算法对我来说很难理解。

For example, try applying quicksort to this array: [2, 6, 3, 1, 6, 5, 2, 4, 8] 例如,尝试对该数组应用quicksort:[2、6、3、1、6、5、2、4、8]

With the median-of-three rule, the pivot is the median of the leftmost, center, and rightmost elements. 使用三位数中位规则,枢轴是最左边,最中心和最右边元素的中位数。 So the median of 2, 6, and 8 is 6. What now? 所以2、6和8的中值为6。

The next step is partitioning: when you have selected a pivot, move all elements smaller than the pivot to the left and all elements larger to the right. 下一步是分区:选择枢轴后,将所有小于枢轴的元素移至左侧,将所有元素移至右侧。 Once this is done, you can separately sort on the left and on the right. 完成此操作后,您可以在左侧和右侧分别进行排序。

Before partitioning: 分区之前:

[2,6,3,1,6,5,2,4,8]

After partitioning <6 on the left, >=6 on the right: 在左侧划分<6 ,在右侧划分>=6

[2,3,1,5,2,4] [6,6,8]

To sort left and right, repeat the same procedure on both sides. 要左右排序,请在两侧重复相同的步骤。

I let you discover the very details of the partitioning procedure (the true one leaves the elements in a different order). 我让您发现分区过程的非常细节(真正的划分过程以不同的顺序离开了元素)。

Issues to remember: 要记住的问题:

  • after partitioning, there must remain at least one element in either side, otherwise the procedure can loop forever (at worse, the only element left can be the pivot); 分区后,在任一侧必须至少保留一个元素,否则该过程将永远循环(更糟糕的是,剩下的唯一元素可能是枢轴);

  • ideally, the partitioning splits the array in two subarrays of roughly equal size; 理想情况下,分区将数组拆分为大小大致相等的两个子数组; but very unequal sizes can also arise, making the algorithm much slower; 但是大小也会变得非常不相等,从而使算法变慢得多; the median-of-three heuristic does not fully avoid that phenomenon; 三分位数启发式算法不能完全避免该现象;

  • the algorithm is written in a recursive way (the sorting function calls itself). 该算法以递归方式编写(排序函数自行调用)。 When sorting the two subarrays, begin with the smallest so that the number of nested calls is minimized. 在对两个子数组进行排序时,请从最小的数组开始,以便最小化嵌套调用的数量。 This is important; 这个很重要;

  • the procedure is overkill for small arrays, this is why it is advisable to switch to a simpler method, like StraightInsertion or StraightSelection in this case. 对于小型数组而言,此过程是多余的,这就是为什么建议切换到更简单的方法的原因,在这种情况下,建议使用StraightInsertion或StraightSelection。

You can sketch the whole sorting process as a binary tree where a node holds an array, with the pivot distinguished, and has two sons holding the subarrays. 您可以将整个排序过程描绘成一个二叉树,其中一个节点保存一个数组,并区分枢轴,并让两个儿子保存子数组。

在此处输入图片说明

So the medium of 2,6,8 is 6. What now? 所以2,6,8的中值为6。

The next step is to partition the array into the left half, containing elements that are less than 6, and the right half, containing elements that are equal to or greater than 6. Then we call quicksort on each half. 下一步是将数组划分为左半部分(包含小于6的元素)和右半部分(包含等于或大于6的元素)。然后在每半部分上调用quicksort。

The following Java program implements quicksort, displaying each subarray before and after sorting. 以下Java程序实现了快速排序,在排序前后显示每个子数组。 It also displays the choice of median. 它还显示中位数的选择。

import java.io.*;

public class Quicksort {
  void swap(int[] data, int i, int j) {
    int t = data[i];
    data[i] = data[j];
    data[j] = t;
  }

  void display(int[] data, int left, int right) {
    for (int i = 0; i < right; ++i) {
      System.out.print(i < left ? "  " : " "+data[i]);
    }
    System.out.println();
  }

  //--- in-place implementation with median-of-three pivot
  int quicksort(int[] data, int left, int right, int callId) {
    int saveCallId = callId;
    System.out.print(callId+". sorting:");
    display(data, left, right);
    if (left+1 >= right) {
      System.out.print("  "+saveCallId+". result:");
      display(data, left, right);
      return callId;
    }
    int ai = left, bi = (left+right)/2, ci = right-1, pos;
    int a = data[ai], b = data[bi], c = data[ci];
    if (a < b) {
      if (c < a) {
        pos = ai;
      } else if (c < b) {
        pos = ci;
      } else {
        pos = bi;
      }
    } else {
      if (c < b) {
        pos = bi;
      } else if (c < a) {
        pos = ci;
      } else {
        pos = ai;
      }
    }
    int pivot = data[pos];
    System.out.println("   median of ["+a+", "+b+", "+c+"] is "+pivot);
    swap(data, right-1, pos);
    int tail = left;
    for (int i = left; i != right-1; ++i) {
      if (data[i] < pivot) {
        swap(data, tail, i);
        ++tail;
      }
    }
    swap(data, right-1, tail);
    callId = quicksort(data, left, tail, ++callId);
    callId = quicksort(data, tail+1, right, ++callId);
    System.out.print("  "+saveCallId+". result:");
    display(data, left, right);
    return callId;
  }

  public static void main(String[] args) {
    int[] data = new int[]{ 2, 6, 3, 1, 6, 5, 2, 4, 8 };
    new Quicksort().quicksort(data, 0, data.length, 0);
  }
}

For the input case { 2, 6, 3, 1, 6, 5, 2, 4, 8 } , the output is: 对于输入案例{ 2, 6, 3, 1, 6, 5, 2, 4, 8 } ,输出为:

0. sorting: 2 6 3 1 6 5 2 4 8
   median of [2, 6, 8] is 6
1. sorting: 2 3 1 5 2 4
   median of [2, 5, 4] is 4
2. sorting: 2 3 1 2
   median of [2, 1, 2] is 2
3. sorting: 1
  3. result: 1
4. sorting:     2 3
   median of [2, 3, 3] is 3
5. sorting:     2
  5. result:     2
6. sorting:        
  6. result:        
  4. result:     2 3
  2. result: 1 2 2 3
7. sorting:           5
  7. result:           5
  1. result: 1 2 2 3 4 5
8. sorting:               6 8
   median of [6, 8, 8] is 8
9. sorting:               6
  9. result:               6
10. sorting:                  
  10. result:                  
  8. result:               6 8
  0. result: 1 2 2 3 4 5 6 6 8

You can see an interactive visualization and play with it at the walnut . 您可以在核桃木上看到交互式的可视化效果并进行操作。 It uses the Dijkstra partitioning (smaller, equal, larger than the pivot). 它使用Dijkstra分区(小于,等于,大于枢轴)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM