[英]Quicksort visualization?
我是编程新手,并且希望使用三分位数分割法和3的临界值对quicksort算法进行可视化表示。
我希望看到整个迭代过程,因为Java算法对我来说很难理解。
例如,尝试对该数组应用quicksort:[2、6、3、1、6、5、2、4、8]
使用三位数中位规则,枢轴是最左边,最中心和最右边元素的中位数。 所以2、6和8的中值为6。
下一步是分区:选择枢轴后,将所有小于枢轴的元素移至左侧,将所有元素移至右侧。 完成此操作后,您可以在左侧和右侧分别进行排序。
分区之前:
[2,6,3,1,6,5,2,4,8]
在左侧划分<6
,在右侧划分>=6
:
[2,3,1,5,2,4] [6,6,8]
要左右排序,请在两侧重复相同的步骤。
我让您发现分区过程的非常细节(真正的划分过程以不同的顺序离开了元素)。
要记住的问题:
分区后,在任一侧必须至少保留一个元素,否则该过程将永远循环(更糟糕的是,剩下的唯一元素可能是枢轴);
理想情况下,分区将数组拆分为大小大致相等的两个子数组; 但是大小也会变得非常不相等,从而使算法变慢得多; 三分位数启发式算法不能完全避免该现象;
该算法以递归方式编写(排序函数自行调用)。 在对两个子数组进行排序时,请从最小的数组开始,以便最小化嵌套调用的数量。 这个很重要;
对于小型数组而言,此过程是多余的,这就是为什么建议切换到更简单的方法的原因,在这种情况下,建议使用StraightInsertion或StraightSelection。
您可以将整个排序过程描绘成一个二叉树,其中一个节点保存一个数组,并区分枢轴,并让两个儿子保存子数组。
所以2,6,8的中值为6。
下一步是将数组划分为左半部分(包含小于6的元素)和右半部分(包含等于或大于6的元素)。然后在每半部分上调用quicksort。
以下Java程序实现了快速排序,在排序前后显示每个子数组。 它还显示中位数的选择。
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);
}
}
对于输入案例{ 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
您可以在核桃木上看到交互式的可视化效果并进行操作。 它使用Dijkstra分区(小于,等于,大于枢轴)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.