[英]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
局部變量完全分開 。 recMergeSort
的count++
行對mergeSort
count
沒有影響。
您的merge
和recMergeSort
方法都返回進行比較的次數,但是您對返回的值不做任何事情。 要計算比較的總數,請刪除上面的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
}
您顯然在調用帶有lowerBound
和upperBound
參數的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.