[英]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.