motacaplaのめう

日頃得られた知見と気付きをdumpするところ

今更ながらJavaでSortアルゴリズムを実装した

はじめに

Javaに親しむ一貫として、有名なSortアルゴリズムを3つ実装してみた。

今回実装したのは、QuickSort、BucketSort、MergeSortの3つ。

(ジェネリクスの扱いになれてなくて、結局int型配列で実装した)

package motacapla.lib;

public class Sort<T> {
    private final int[] array;
    public Sort(int[] array) {
        this.array = array;
    }
    public int[] quickSort() {
        quickSortRecur(0, array.length-1);
        return array;
    }
    private void quickSortRecur(int left, int right) {   
        if(left >= right) return;     
        int pivot = array[(left+right)/2];
        while(left <= right) {
            while(pivot > array[left]) left++;
            while(pivot < array[right]) right--;
            if(left <= right) {
                int tmp = array[left]; 
                array[left] = array[right]; 
                array[right] = tmp;
                left++; right--;
            }
        }
        quickSortRecur(left, pivot);
        quickSortRecur(pivot, right);
    }    
    public int[] bucketSort(int maxValue) {
        int[] answer = new int[maxValue+1];
        for(int i=0; i<array.length; i++) answer[array[i]]++;
        int[] answerArray = new int[array.length];
        for(int i=0, j=0; i<answer.length; i++) {
            while(answer[i] > 0) {
                answerArray[j] = i;
                answer[i]--;
                j++;
            }
        }
        return answerArray;
    }
    public int[] mergeSort() {
        mergeSortRecur(0, array.length-1);
        return array; 
    }    
    private void mergeSortRecur(int l, int r) {
        if (l < r) { 
            int m = (l+r)/2;   
            mergeSortRecur(l, m); 
            mergeSortRecur(m+1, r);   
            merge(l, m, r); 
        } 
    }
    private void merge(int l, int m, int r) {
        int n1 = m - l + 1; 
        int n2 = r - m; 
        int L[] = new int [n1]; 
        int R[] = new int [n2]; 

        for (int i=0; i<n1; ++i) L[i] = array[l + i]; 
        for (int j=0; j<n2; ++j) R[j] = array[m + 1+ j]; 

        int i = 0, j = 0; int k = l; 
        while (i < n1 && j < n2) { 
            if (L[i] <= R[j]) { 
                array[k] = L[i]; 
                i++; 
            } 
            else { 
                array[k] = R[j]; 
                j++; 
            } 
            k++; 
        } 
        while (i < n1) { 
            array[k] = L[i]; 
            i++; 
            k++; 
        } 
        while (j < n2) { 
            array[k] = R[j]; 
            j++; 
            k++; 
        } 
      }
}

テスト

1ケースのみだが、テストコードも書いたので以下に示す。

package motacapla.lib;

import static org.junit.Assert.*;

import org.junit.Test;

public class SortTest {
    static final int ary_size = 10;
    @Test
    public void testquickSort() {    
        int [] array = new int[ary_size];
        int [] answer = new int[ary_size];
        for(int i=0; i<ary_size; i++) {
            array[i] = ary_size-i;
            answer[i] = i+1;            
        }
        Sort<Integer> srt = new Sort<Integer>(array);
        assertArrayEquals(answer, srt.quickSort());        
    }

    @Test
    public void testbucketSort() {    
        int [] array = new int[ary_size];
        int [] answer = new int[ary_size];
        int maxValue = 0;
        for(int i=0; i<ary_size; i++) {
            array[i] = ary_size-i;
            answer[i] = i+1;            
            maxValue = Math.max(maxValue, answer[i]);
        }
        Sort<Integer> srt = new Sort<Integer>(array);
        assertArrayEquals(answer, srt.bucketSort(maxValue));        
    }    
    @Test
    public void testmergeSort() {    
        int[] actual = { 5, 1, 6, 2, 3, 4 };
        int[] expected = { 1, 2, 3, 4, 5, 6 };
        Sort srt = new Sort(actual);
        actual = srt.mergeSort();
        for(int i=0; i<actual.length; i++) {
            System.out.println(actual[i]);
        }
        assertArrayEquals(expected, srt.mergeSort());        
    }       
}

TODO

RadixSortやHeapSortも実装したい!