簡體   English   中英

遞歸MergeSort和計數比較

[英]Recursive MergeSort and counting comparisons

我編寫了一個程序,其中包含4種排序方法:選擇排序,插入排序,合並排序和遞歸合並排序。 插入和選擇排序方法運行良好,並向我返回了一個排序列表和適當數量的比較。 我的歸並排序方法返回了一個排序后的列表,但是我的比較結果為1。我的遞歸歸並排序甚至不對列表進行排序,還說比較結果為1。有人可以幫助我找到我的錯誤嗎? 這是我所有的代碼。

public class ArraySort {
    private long[] a;                 // ref to array a
    private int nElems;               // number of data items

    public ArraySort(int max) {       // constructor
       a = new long[max];             // create the array
       nElems = 0;                    // no items yet
    }

    public void Clone(ArraySort c) {  // c is another array
       c.nElems = this.nElems;                                 // Copy nElems
       System.arraycopy(this.a, 0, c.a, 0, this.nElems);       // Copy elements
    }

    public void insert(long value) {  // put element into array
       a[nElems++] = value;           // insert value
    }

    public String toString() {           // displays array contents
       String res="";
       for(int j=0; j<nElems; j++)       // for each element,
          res = res + a[j] + " ";        // append it to res
       return res;
    }

    private int insertOrder(int n, long temp) { // insert temp into a[0..(n-1)]
                  // and keep a[0..n] sorted.
        int count = 0;
        while (n > 0) {
            count++;                       // count next comparison
            if (a[n-1] > temp)   {         // until one is smaller,
               a[n] = a[n-1];              // shift item to right
               --n;                        // go left one position
            } else break;
        }
        a[n] = temp;                      // insert marked item
        return count;
    }

    public int insertionSort() {
        int count = 0;
        for (int n=1; n<nElems; n++)  
            count += insertOrder(n, a[n]);   // insert a[n] into a[0..(n-1)]

        return count;
    } // end insertionSort()

    private void swap(int one, int two) {
       long temp = a[one];
       a[one] = a[two];
       a[two] = temp;
    }

    public int selectionSort() {
       int out, in, max, count=0;

       for(out=nElems-1; out > 0; out--) {  // outer loop
          max = out;                        // max is maximum item's index
          for(in=0; in<out; in++) {          // inner loop
             if(a[in] > a[max] )            // if max is smaller,
                 max = in;                  // we have a new max
             count++;                       // count one comparison
          }
          swap(out, max);                   // swap them
       }  // end for(out)
       return count;
    }  // end selectionSort()

    public int mergeSort() {           // called by main()
        int count = 0;
        long[] workSpace = new long[nElems]; // provides workspace
        recMergeSort(workSpace, 0, nElems-1);
        count++;
        return count;
    }


public int recMergeSort(long[] workSpace, int lowerBound,
        int upperBound) {

    int count = 0;

    if(lowerBound == upperBound)            // if range is 1,
        return 1;

    // find midpoint
    int mid = (lowerBound+upperBound) / 2;

    recMergeSort(workSpace, lowerBound, mid);   // sort low half

    recMergeSort(workSpace, mid+1, upperBound);  // sort high half


    merge(workSpace, lowerBound, mid+1, upperBound); // merge them
    count++;
    return count;

}  // end else
  // end recMergeSort()


private int merge(long[] workSpace, int lowPtr,
        int highPtr, int upperBound)
{
    int j = 0;                             // workspace index

    int lowerBound = lowPtr;

    int mid = highPtr-1;

    int n = upperBound-lowerBound+1;       // # of items

    int count = 0;

    while(lowPtr <= mid && highPtr <= upperBound)

        if( a[lowPtr] < a[highPtr] ) {
            workSpace[j++] = a[lowPtr++];
            count++;
        }

        else {
            workSpace[j++] = a[highPtr++];
            count++;
        }

        while(lowPtr <= mid)
            workSpace[j++] = a[lowPtr++];

        count++;


        while(highPtr <= upperBound)
            workSpace[j++] = a[highPtr++];

        count++;

        for(j=0; j<n; j++)

           a[lowerBound+j] = workSpace[j];

        return count;
    }  // end merge()
}

該方法正在從這里調用...

import java.util.*;

public class SortComparison {

    public static void main(String[] args) {

       int count, maxSize = 20;      // array size
       ArraySort arr, carr;           // reference to array
       arr = new ArraySort(maxSize);  // create the arrays
       carr = new ArraySort(maxSize);

       // insert some random numbers
              Random generator = new Random();
       for (int i = 0; i < 20; i++) {
            arr.insert(Math.abs(generator.nextInt())%maxSize);
       }

       System.out.println("Before sort: " + arr);                // display items

       arr.Clone(carr);
       count = carr.insertionSort();          // insertion-sort a clone of arr
       System.out.println("Insert sort: " + carr + " comparions=" + count);                  

       arr.Clone(carr);
       count = carr.selectionSort();          // selection-sort a clone of arr
       System.out.println("Select sort: " + carr + " comparions=" + count); 

       arr.Clone(carr);
       count = carr.mergeSort();
       System.out.println("Merge sort: " + carr + " comparions=" + count);

       arr.Clone(carr);
       count = carr.recMergeSort(null, maxSize, maxSize);
       System.out.println("RecMerge sort: " + carr + " comparions=" + count);

  }  // end main()

}  // end class SortComparison

當程序運行時,這是我收到的輸出...

Before sort: 3 2 4 7 17 11 3 0 14 6 8 7 12 15 0 0 9 4 7 16 
Insert sort: 0 0 0 2 3 3 4 4 6 7 7 7 8 9 11 12 14 15 16 17  comparions=94
Select sort: 0 0 0 2 3 3 4 4 6 7 7 7 8 9 11 12 14 15 16 17  comparions=190
Merge sort: 0 0 0 2 3 3 4 4 6 7 7 7 8 9 11 12 14 15 16 17  comparions=1
RecMerge sort: 3 2 4 7 17 11 3 0 14 6 8 7 12 15 0 0 9 4 7 16  comparions=1

有人可以幫我解決這個問題嗎?


我不知道為什么我的遞歸合並排序方法不會對列表進行排序。 以及為什么最后兩個比較= 1。

由於這是一項家庭作業,因此我僅顯示如何修復mergeSort()

public int mergeSort() {
    int count = 0;
    long[] workSpace = new long[nElems];
    count += recMergeSort(workSpace, 0, nElems-1); // Add the comparisons executed there
    return count;
}

您需要以類似的方式修復recMergeSort()

我想您認為count是一個全局變量。 但事實並非如此。 在所有排序方法中, count是一個局部變量,該變量在方法范圍之外不可見。 因此,如果您在recMergeSort()內部修改了count變量,它將不會自動影響mergeSort()內部的(other) count變量。 將計數從(稱為) recMergeSort()發送到(調用) mergeSort()的自然方法是通過return count ,就像您正確所做的那樣。 不幸的是,您沒有使用recMergeSort()返回的結果。

最后一兩件事,因為也許我還不夠清楚:即使你遞歸調用recMergeSort()recMergeSort()count在調用者變量是從不同count的被叫變量。 因此,即使您進行遞歸調用,被調用的方法仍然需要將結果傳遞給return ,而調用方法需要將其提取。

以下是您的mergeSort()方法:

public int mergeSort() {           // called by main()
    int count = 0;
    long[] workSpace = new long[nElems]; // provides workspace
    recMergeSort(workSpace, 0, nElems-1);
    count++;
    return count;
}

此方法返回1,因為您創建了一個名為count的變量,在調用recMergeSort之后僅將其遞增一次,然后將其返回。 recMergeSort包含另一個名為count局部變量,但是此局部變量 mergeSort局部變量完全分開 recMergeSortcount++行對mergeSort count沒有影響。

您的mergerecMergeSort方法都返回進行比較的次數,但是您對返回的值不做任何事情。 要計算比較的總數,請刪除上面的count++行,然后替換該行

recMergeSort(workSpace, 0, nElems-1);

count += recMergeSort(workSpace, 0, nElems-1);

您還需要對recMergeSort的各種方法調用進行類似的更改。

為什么輸出上方的最后一行沒有對列表進行排序? 好吧,您正在進行以下方法調用:

count = carr.recMergeSort(null, maxSize, maxSize);

您的recMergeSort方法開始如下:

public int recMergeSort(long[] workSpace, int lowerBound,
        int upperBound) {

    int count = 0;

    if(lowerBound == upperBound)            // if range is 1,
        return 1;

    // rest of method omitted
}

您顯然在調用帶有lowerBoundupperBound參數的recMergeSort 結果,該方法返回1 ,因為您明確要求它。

將來,只需發布​​相關代碼即可。 我們不一定需要查看所有有效的方法。

可以僅使用一種方法制作遞歸排序算法(就我個人而言,如果您這樣做的話,會更容易)。 無論如何,您都處在正確的軌道上。 但是看一下mergeSort()-您聲明count = 0,進行遞歸,將1加到count,然后返回它。 您遇到的問題是,當您應該給它由recMergeSort()返回的值時,它只能遞增計數一次。 請參閱我的在線注釋以獲取解決方案。

public int mergeSort() {           // called by main() 
    int count = 0;

    long[] workSpace = new long[nElems]; // provides workspace
        /*
           recMergeSort() returns an integer, but you do not assign it to anything.
        */
    recMergeSort(workSpace, 0, nElems-1);
    count++;
        /* Instead, try something like 
               count = recMergeSort(workspace, 0, nElms-1);
               return count;
        */
return count;
}


public int recMergeSort(long[] workSpace, int lowerBound, int upperBound) { int count = 0;
    if(lowerBound == upperBound) // if range is 1, return 1;
    // find midpoint int mid = (lowerBound+upperBound) / 2;
    recMergeSort(workSpace, lowerBound, mid); // sort low half
    recMergeSort(workSpace, mid+1, upperBound); // sort high half
    merge(workSpace, lowerBound, mid+1, upperBound); // merge them count++; return count; } // end else // end recMergeSort()
    private int merge(long[] workSpace, int lowPtr, int highPtr, int upperBound) { int j = 0; // workspace index
    int lowerBound = lowPtr;
    int mid = highPtr-1;
    int n = upperBound-lowerBound+1; // # of items
    int count = 0;
    while(lowPtr <= mid && highPtr <= upperBound)
    if( a[lowPtr] < a[highPtr] ) {
        workSpace[j++] = a[lowPtr++];
        count++;
    } else {
        workSpace[j++] = a[highPtr++];
        count++; }
    while(lowPtr <= mid)
        workSpace[j++] = a[lowPtr++];
        count++;
    while(highPtr <= upperBound)
        workSpace[j++] = a[highPtr++];
        count++;
    for(j=0; j


                       //AAAAAH! What happened to your For loop???

        a[lowerBound+j] = workSpace[j]; return count; } // end merge()

}

暫無
暫無

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

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