web-dev-qa-db-ja.com

javaのマージソート

私はJavaが初めてで、Javaにmergesortを実装しようとしました。しかし、目的のソートされた出力の代わりにプログラムを数回実行した後でも、誰かがこの予期しない動作を理解するのを手伝ってくれるとありがたいです。

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;

    }

}
11
tinker

コードの修正バージョンは次のとおりです。

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;

    }

}
25
uyetch

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]);
    }
_
9
NPE

問題は、Javaは値渡しであり、参照渡しではない...マージメソッドで配列Aに割り当てる場合、参照のコピーをAではなくAに変更することです。 A自体への参照。したがって、Aをマージメソッドに渡し、Aに構造的な変更を加える必要があります。

2
rascal
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] + " ");
    }   
 }
}
1
Judeyou

問題はここにあります:

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);
1
corsiKa

非常にシンプルで理解しやすい

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++];
    }

}
0
Himanshu Singh

これに関する私の見解を追加することもできます:2つの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++;
    }
  }
}
0
Liam Larsen

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;
}

配列を返す必要があるため、要素が1つしかない場合はAを変更せずに返します。そうでない場合は、配列の左右の部分をソートした結果をマージします。

0
crashmstr
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();

}

}
0

上記のコードは少し混乱しています。「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--];
        }
    }
}
0
rafambbr
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++;
        }

    }
}
0
Ragulan
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];
    }
}
0
Rick