簡體   English   中英

Quicksort可視化?

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM