[英]Mergesort in java
我是 Java 新手,並嘗試在 Java 中實現歸並排序。 但是,即使在多次運行程序之后,我得到的不是所需的排序輸出,而是與輸出相同的用戶給定輸入。 如果有人能幫助我理解這種意外行為,我將不勝感激。
import java.io.*;
import java.util.Arrays;
public class MergeSort {
public static void main(String[] args) throws IOException {
BufferedReader R = new BufferedReader(new InputStreamReader(System.in));
int arraySize = Integer.parseInt(R.readLine());
int[] inputArray = new int[arraySize];
for (int i = 0; i < arraySize; i++) {
inputArray[i] = Integer.parseInt(R.readLine());
}
mergeSort(inputArray);
for (int j = 0; j < inputArray.length; j++) {
System.out.println(inputArray[j]);
}
}
static void mergeSort(int[] A) {
if (A.length > 1) {
int q = A.length / 2;
int[] leftArray = Arrays.copyOfRange(A, 0, q);
int[] rightArray = Arrays.copyOfRange(A, q + 1, A.length);
mergeSort(leftArray);
mergeSort(rightArray);
A = merge(leftArray, rightArray);
}
}
static int[] merge(int[] l, int[] r) {
int totElem = l.length + r.length;
int[] a = new int[totElem];
int i, li, ri;
i = li = ri = 0;
while (i < totElem) {
if ((li < l.length) && (ri < r.length)) {
if (l[li] < r[ri]) {
a[i] = l[li];
i++;
li++;
} else {
a[i] = r[ri];
i++;
ri++;
}
} else {
if (li >= l.length) {
while (ri < r.length) {
a[i] = r[ri];
i++;
ri++;
}
}
if (ri >= r.length) {
while (li < l.length) {
a[i] = l[li];
li++;
i++;
}
}
}
}
return a;
}
}
這是您的代碼的更正版本:
import java.io.*;
import java.util.Arrays;
public class MergeSort {
public static void main(String[] args) throws IOException{
BufferedReader R = new BufferedReader(new InputStreamReader(System.in));
int arraySize = Integer.parseInt(R.readLine());
int[] inputArray = new int[arraySize];
for (int i = 0; i < arraySize; i++) {
inputArray[i] = Integer.parseInt(R.readLine());
}
mergeSort(inputArray);
for (int j = 0; j < inputArray.length; j++) {
System.out.println(inputArray[j]);
}
}
static void mergeSort(int[] A) {
if (A.length > 1) {
int q = A.length/2;
//changed range of leftArray from 0-to-q to 0-to-(q-1)
int[] leftArray = Arrays.copyOfRange(A, 0, q-1);
//changed range of rightArray from q-to-A.length to q-to-(A.length-1)
int[] rightArray = Arrays.copyOfRange(A,q,A.length-1);
mergeSort(leftArray);
mergeSort(rightArray);
merge(A,leftArray,rightArray);
}
}
static void merge(int[] a, int[] l, int[] r) {
int totElem = l.length + r.length;
//int[] a = new int[totElem];
int i,li,ri;
i = li = ri = 0;
while ( i < totElem) {
if ((li < l.length) && (ri<r.length)) {
if (l[li] < r[ri]) {
a[i] = l[li];
i++;
li++;
}
else {
a[i] = r[ri];
i++;
ri++;
}
}
else {
if (li >= l.length) {
while (ri < r.length) {
a[i] = r[ri];
i++;
ri++;
}
}
if (ri >= r.length) {
while (li < l.length) {
a[i] = l[li];
li++;
i++;
}
}
}
}
//return a;
}
}
當您在mergeSort()
重新綁定A
時:
A = merge(leftArray,rightArray);
這對main()
中的inputArray
沒有影響。
您需要從mergeSort()
返回排序的數組,類似於從merge()
返回它的方式。
static int[] mergeSort(int[] A) {
...
return A;
}
在main()
:
int[] mergedArray = mergeSort(inputArray);
for (int j = 0; j < mergedArray.length; j++) {
System.out.println(mergedArray[j]);
}
問題是java是按值傳遞而不是按引用傳遞......當您在合並方法中分配給數組A時,您正在更改對A的引用的副本,而不是對A本身的引用。 因此,您需要將 A 傳遞到您的合並方法中並對 A 進行結構更改。
問題出在這里:
A = merge(leftArray,rightArray);
現在您的合並數組執行以下操作:
static int[] merge(int[] l, int[] r) {
int[] a = new int[totElem];
// bunch of code
return a;
}
開始時,A 是對 inputArray 的引用。 但是隨后您將其重新分配為合並后的任何內容。 不幸的是,這並沒有觸及 main 方法中 inputArray 的內容。 這基本上是說“哦,看看你所做的所有工作……扔掉它!”
你可以用類似的東西改變它
static int[] mergeSort(int[] A) {
// A = merge... // not this
return merge... // use this
}
然后在你的主要方法中,你可以做
int[] merged = mergeSort(inputArray);
for(int i : merged) System.out.println(i);
public class MergeSort{
public static void sort(int[] in){
if(in.length <2) return; //do not need to sort
int mid = in.length/2;
int left[] = new int[mid];
int right[] = new int[in.length-mid];
for(int i=0; i<mid; i++){ //copy left
left[i] = in[i];
}
for(int i=0; i<in.length-mid; i++){ //copy right
right[i] = in[mid+i];
}
sort(left);
sort(right);
merge(left, right, in);
}
private static void merge(int[] a, int[] b, int[] all){
int i=0, j=0, k=0;
while(i<a.length && j<b.length){ //merge back
if(a[i] < b[j]){
all[k] = a[i];
i++;
}else{
all[k] = b[j];
j++;
}
k++;
}
while(i<a.length){ //left remaining
all[k++] = a[i++];
}
while(j<b.length){ //right remaining
all[k++] = b[j++];
}
}
public static void main(String[] args){
int[] a = {2,3,6,4,9,22,12,1};
sort(a);
for(int j=0; j<a.length; j++){
System.out.print(a[j] + " ");
}
}
}
假設您的merge
功能正確:
static int[] mergeSort(int[] A) {
if (A.length > 1) {
int q = A.length/2;
int[] leftArray = Arrays.copyOfRange(A, 0, q);
int[] rightArray = Arrays.copyOfRange(A,q+1,A.length);
return merge(mergeSort(leftArray),mergeSort(rightArray));
}
else
return A;
}
由於我們需要返回數組,如果它只有一個元素,我們返回A
未修改,否則我們合並排序數組左右部分的結果。
public void sort(int[] randomNumbersArrray)
{
copy = randomNumbersArrray.clone();
mergeSort(0 , copy.length - 1);
}
private void mergeSort(int low, int high)
{
if(low < high)
{
int mid = ((low + high) / 2);
mergeSort(low, mid); //left side
mergeSort(mid + 1, high); // right side
merge(low, mid, high); //combine them
}
}
private void merge(int low, int mid, int high)
{
int temp[] = new int[high - low + 1];
int left = low;
int right = mid + 1;
int index = 0;
// compare each item for equality
while(left <= mid && right <= high)
{
if(copy[left] < copy[right])
{
temp[index] = copy[left];
left++;
}else
{
temp[index] = copy[right];
right++;
}
index++;
}
// if there is any remaining loop through them
while(left <= mid || right <= high)
{
if( left <= mid)
{
temp[index] = copy[left];
left++;
index++;
}else if(right <= high)
{
temp[index] = copy[right];
right++;
index++;
}
}
// copy back to array
for(int i = 0; i < temp.length; i++)
{
copy[low + i] = temp[i];
}
}
package Sorting;
public class MergeSort {
private int[] original;
private int len;
public MergeSort(int length){
len = length;
original = new int[len];
original[0]=10;
original[1]=9;
original[2]=8;
original[3]=7;
original[4]=6;
original[5]=5;
original[6]=4;
original[7]=3;
original[8]=2;
original[9]=1;
int[] aux = new int[len];
for(int i=0;i<len;++i){
aux[i]=original[i];
}
Sort(aux,0,len);
}
public void Sort(int[] aux,int start, int end){
int mid = start + (end-start)/2;
if(start < end){
Sort(aux, start, mid-1);
Sort(aux, mid, end);
Merge(aux, start, mid, end);
}
}
public void Merge(int[] aux, int start, int mid, int end){// while array passing be careful of shallow and deep copying
for(int i=start; i<=end; ++i)
auxilary[i] = original[i];
int i = start;
int k = start;
int j = mid+1;
while(i < mid && j <end){
if(aux[i] < aux[j]){
original[k++] = aux[i++];
}
else{
original[k++] = aux[j++];
}
}
if(i == mid){
while(j < end){
original[k++] = aux[j++];
}
}
if(j == end){
while(i < mid){
original[k++] = aux[i++];
}
}
}
public void disp(){
for(int i=0;i<len;++i)
System.out.print(original[i]+" ");
}
public static void main(String[] args) {
MergeSort ms = new MergeSort(10);
ms.disp();
}
}
上面的代碼有點混亂 千萬不要使用帶名字的變量:"k", "j", "m",... 這讓代碼很混亂
以更簡單的方式遵循代碼...
import java.util.Arrays;
public class MergeSort {
public static void main(String[] args) {
Integer[] itens = {2,6,4,9,1,3,8,7,0};
Integer[] tmp = new Integer[itens.length];
int left = 0;
int right = itens.length - 1;
mergeSort(itens, tmp, left, right);
System.out.println(Arrays.toString(itens));
}
private static void mergeSort(Integer[] itens, Integer[] tmpArray, int left, int right) {
if(itens == null || itens.length == 0 || left >= right){
return;
}
int midle = (left + right) / 2;
mergeSort(itens, tmpArray, left, midle);
mergeSort(itens, tmpArray, midle + 1, right);
merge(itens, tmpArray, left, midle + 1, right);
}
private static void merge(Integer[] itens, Integer[] tmpArray, int left, int right, int rightEnd) {
int leftEnd = right - 1;
int tmpIndex = left;
while (left <= leftEnd && right <= rightEnd){
if (itens[left] < itens[right] ){
tmpArray[tmpIndex++] = itens[left++];
} else {
tmpArray[tmpIndex++] = itens[right++];
}
}
while (left <= leftEnd) { // Copy rest of LEFT half
tmpArray[tmpIndex++] = itens[left++];
}
while (right <= rightEnd) { // Copy rest of RIGHT half
tmpArray[tmpIndex++] = itens[right++];
}
while(rightEnd >= 0){ // Copy TEMP back
itens[rightEnd] = tmpArray[rightEnd--];
}
}
}
不妨添加我對此的看法:獲取兩個 int 數組並合並它們。 其中“結果”是一個大小為 a.length + b.length 的數組
public static void merge( int[] a, int[] b, int[] result )
{
int i = 0, j = 0;
while ( true )
{
if ( i == a.length )
{
if ( j == b.length )
return;
result[ i + j ] = b[ j ];
j++;
}
else if ( j == b.length )
{
result[ i + j ] = a[ i ];
i++;
}
else if ( a[ i ] < b[ j ] )
{
result[ i + j ] = a[ i ];
i++;
}
else
{
result[ i + j ] = b[ j ];
j++;
}
}
}
public class MyMergeSort {
private int[] array;
private int[] tempMergArr;
private int length;
public static void main(String a[]){
int[] inputArr = {45,23,11,89,77,98,4,28,65,43};
MyMergeSort mms = new MyMergeSort();
mms.sort(inputArr);
for(int i:inputArr){
System.out.print(i);
System.out.print(" ");
}
}
public void sort(int inputArr[]) {
this.array = inputArr;
this.length = inputArr.length;
this.tempMergArr = new int[length];
doMergeSort(0, length - 1);
}
private void doMergeSort(int lowerIndex, int higherIndex) {
if (lowerIndex < higherIndex) {
int middle = lowerIndex + (higherIndex - lowerIndex) / 2;
// Below step sorts the left side of the array
doMergeSort(lowerIndex, middle);
// Below step sorts the right side of the array
doMergeSort(middle + 1, higherIndex);
// Now merge both sides
mergeParts(lowerIndex, middle, higherIndex);
}
}
private void mergeParts(int lowerIndex, int middle, int higherIndex) {
for (int i = lowerIndex; i <= higherIndex; i++) {
tempMergArr[i] = array[i];
}
int i = lowerIndex;
int j = middle + 1;
int k = lowerIndex;
while (i <= middle && j <= higherIndex) {
if (tempMergArr[i] <= tempMergArr[j]) {
array[k] = tempMergArr[i];
i++;
} else {
array[k] = tempMergArr[j];
j++;
}
k++;
}
while (i <= middle) {
array[k] = tempMergArr[i];
k++;
i++;
}
}
}
非常簡單易懂
static void sort(char[] data) {
int length = data.length;
if (length < 2)
return;
int mid = length / 2;
char[] left = new char[mid];
char[] right = new char[length - mid];
for(int i=0;i<mid;i++) {
left[i]=data[i];
}
for(int i=0,j=mid;j<length;i++,j++) {
right[i]=data[j];
}
sort(left);
sort(right);
merge(left, right, data);
}
static void merge(char[] left, char[] right, char[] og) {
int i = 0, j = 0, k = 0;
while(i < left.length && j < right.length) {
if (left[i] < right[j]) {
og[k++] = left[i++];
} else {
og[k++] = right[j++];
}
}
while (i < left.length) {
og[k++] = left[i++];
}
while (j < right.length) {
og[k++] = right[j++];
}
}
我有一個並行版本的合並排序。 我從 RecursiveAction 和 ForkJoinPool 中受益。 請注意,worker 的數量可以設置為常數。 但是,我將其設置為機器上可用處理器的數量。
import java.util.Arrays;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
public class ParallelMergeSorter {
private int[] array;
public ParallelMergeSorter(int[] array) {
this.array = array;
}
public int[] sort() {
int numWorkers = Runtime.getRuntime().availableProcessors(); // Get number of available processors
ForkJoinPool pool = new ForkJoinPool(numWorkers);
pool.invoke(new ParallelWorker(0, array.length - 1));
return array;
}
private class ParallelWorker extends RecursiveAction {
private int left, right;
public ParallelWorker(int left, int right) {
this.left = left;
this.right = right;
}
protected void compute() {
if (left < right) {
int mid = (left + right) / 2;
ParallelWorker leftWorker = new ParallelWorker(left, mid);
ParallelWorker rightWorker = new ParallelWorker(mid + 1, right);
invokeAll(leftWorker, rightWorker);
merge(left, mid, right);
}
}
private void merge(int left, int mid, int right) {
int[] leftTempArray = Arrays.copyOfRange(array, left, mid + 1);
int[] rightTempArray = Arrays.copyOfRange(array, mid + 1, right + 1);
int leftTempIndex = 0, rightTempIndex = 0, mergeIndex = left;
while (leftTempIndex < mid - left + 1 || rightTempIndex < right - mid) {
if (leftTempIndex < mid - left + 1 && rightTempIndex < right - mid) {
if (leftTempArray[leftTempIndex] <= rightTempArray[rightTempIndex]) {
array[mergeIndex] = leftTempArray[leftTempIndex];
leftTempIndex++;
} else {
array[mergeIndex] = rightTempArray[rightTempIndex];
rightTempIndex++;
}
} else if (leftTempIndex < mid - left + 1) {
array[mergeIndex] = leftTempArray[leftTempIndex];
leftTempIndex++;
} else if (rightTempIndex < right - mid) {
array[mergeIndex] = rightTempArray[rightTempIndex];
rightTempIndex++;
}
mergeIndex++;
}
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.