簡體   English   中英

在quicksort java中的無限循環

[英]infinite loop in quicksort java

我嘗試實現一個快速排序算法,但是當我運行我的代碼時,它給了我一個無限循環,我不明白,我在代碼中的分區方法中犯了錯誤:

public static int partition(int[] a, int p, int r)
{
    int x = a[p];
    int i = p;
    int j = r + 1;
    while(true)
    {
        while(a[i] < x) 
        {
            i++;
            if (i == r) break;
        }
        while(x > a[j]) 
        {
            j--;
            if (j == p) break;
        }
        if (i >= j) break;

        int tmp = a[i];
        a[i] = a[j];
        tmp = a[i];
    }

    int exch = a[p];
    a[p] = a[j];
    exch = a[p];

    return j;
}

此代碼的輸入數據:

private static int[] array;
private static Scanner sc = new Scanner(System.in);
public static void main(String[] args){
    int n, m;
    n = sc.nextInt();
    array = new int[n+1];
    int i,j;
    for (i = 0; i != array.length-1; i++)
        array[i] = sc.nextInt();


    for (j = 0; j !=array.length-1; i++)
        System.out.print(array[j]);
    quickSort(array,0,array.length);

}

嘗試

a[j] = exch;

代替

exch = a[p];

和相同的bug - 感謝@Namer和@Zhuinden - 在你的代碼中:

int tmp = a[i];
a[i] = a[j];
tmp = a[i];

感謝@DeepanshuBedi, Java中的Quicksort - Tutorial描述了算法。 它有

i++;
j--;

在循環中交換之后。

此外,該函數預計是遞歸的:

if (low < j)
  quicksort(low, j);
if (i < high)
  quicksort(i, high); 

而不是你的第二次交換。

我建議你從那個頁面復制代碼 - 你的代碼並不像我那樣快速。

您正在實施Quicksort算法Cormen算法版本 他的版本是這樣的(沒有提到版權信息,這可以通過簡單的谷歌搜索找到):

在此輸入圖像描述

你的版本幾乎全部錯過了。 例如,在前兩行:

int x = a[p]; //Should be a[r]
int i = p; //Should be p-1

再次檢查算法的每一步,並且只有在您真正理解算法如何重新編寫正確的函數之后。

你的quicksort函數也應該是遞歸的,我希望你知道這意味着什么

提示:有兩個函數,一個是遞歸的( quickSort ),另一個只有一個for循環( partition )。


編輯:我從書中拿了錯誤的快速排序算法,對不起。 正確的,你正在使用的那個,如下:

在此輸入圖像描述

您仍在使用一些非常基本的錯誤來實現它。 以下是最明顯的一些:

  • 您正在使用while循環而不是do-until (do-while in Java)循環,這是非常不同的

  • 你正在混合這兩種算法,交換(當我的第一條評論指出錯誤時)兩次在Hoare-Partition中只進行一次的值。

  • 你不需要if (i >= j) break; if (i == r) break; 循環結束條件,因為,對於算法的構造,它們永遠不會發生(如果你使用a[i] < x作為斷開條件或者a[i] >= x作為允許條件)。 這表明您沒有完全理解算法的工作原理。

  • int i = p; //Should be p-1 int i = p; //Should be p-1還是錯的。

再次,檢查算法的每一步並糾正它,你就在路上! :)

更新:我已嘗試使用上面的更正的Hoare分區和輸入int[] a = {13,19,9,5,12,8,7,4,11,2,6,21}; 每次交換之后(順便說一下這是(a)書中問題的答案):

[6, 19, 9, 5, 12, 8, 7, 4, 11, 2, 13, 21]
[6, 13, 9, 5, 12, 8, 7, 4, 11, 2, 19, 21]
[6, 2, 9, 5, 12, 8, 7, 4, 11, 13, 19, 21]
[4, 2, 9, 5, 12, 8, 7, 6, 11, 13, 19, 21]
[4, 2, 6, 5, 12, 8, 7, 9, 11, 13, 19, 21]
[4, 2, 5, 6, 12, 8, 7, 9, 11, 13, 19, 21]
[2, 4, 5, 6, 12, 8, 7, 9, 11, 13, 19, 21]
[2, 4, 5, 6, 11, 8, 7, 9, 12, 13, 19, 21]
[2, 4, 5, 6, 9, 8, 7, 11, 12, 13, 19, 21]
[2, 4, 5, 6, 7, 8, 9, 11, 12, 13, 19, 21]

這僅僅是為了檢查算法是否有效(可能是打印錯誤可能導致無限循環)。

快速排序的基礎知識嘗試這可以解決您的問題。

              if (i <= j) {
              tmp = a[i];
              a[i] = a[j];
              a[j] = tmp;
              i++;
              j--;}


           **int exch = a[p];
            a[p] = a[j];
            a[p] = exch;**

編輯了你的代碼。 我建議你使用for-loop。

 public static int partition(int[] a, int p, int r)
    {
        int x = a[p];
        int i = p;
        int j = r + 1;
        while(true)
        {
            while(a[i] < x) 
            {
                i++;
                if (i == r) break;
            }
            while(x > a[j]) 
            {
                j--;
                if (j == p) break;
            }
     if (i <= j) {
          tmp = a[i];
          a[i] = a[j];
          a[j] = tmp;
          i++;
          j--;}

        **int exch = a[p];
        a[p] = a[j];
        a[p] = exch;**

        return j;
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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