選択ソートJavaと分析

Aug 26 2020

私はJavaで選択ソートコードを書きました。私はその非常に基本的なアルゴリズムを知っていますが、私は学んでいるので、コードの品質についてのあなたの入力を望んでいました。コードを見てください:package selection_sort;

import java.util.Scanner;

public class SelectionSort {

int [] arrayToBeSorted;
Scanner scan=new Scanner(System.in);


SelectionSort(){
    System.out.println("Enter the number of elements");
    int total=scan.nextInt();
    this.arrayToBeSorted=new int[total];
    for(int i=0;i<total;i++) {
        System.out.println("Enter the "+i+" number of elements");
        this.arrayToBeSorted[i]=scan.nextInt();
    }
    
}

public void Sort() {
    int minIndex,min;
    boolean swapRequired=false;
    for(int i=0;i<arrayToBeSorted.length;i++) {
        minIndex=i;
        min=this.arrayToBeSorted[i];
        for(int j=i+1;j<this.arrayToBeSorted.length;j++) {
            if(this.arrayToBeSorted[j]<min) {
                min=this.arrayToBeSorted[j];
                minIndex=j;
                swapRequired=true;
            }
        }
        if(swapRequired) {
            swap(i,minIndex);
        }
                    
    }
    
    for(int x:this.arrayToBeSorted) {
        System.out.print(x+" ");
    }
        
    }

public void swap(int i,int j) {
    
    //System.out.println("swap called, pos="+i+"and minindex="+j);
    int temp=this.arrayToBeSorted[i];
    this.arrayToBeSorted[i]=this.arrayToBeSorted[j];
    this.arrayToBeSorted[j]=temp;
    
    //System.out.println("------------");
    
}
public static void main(String[] args) {
    SelectionSort s=new SelectionSort();
    s.Sort();
}

}

分析についても、選択はO(n2)なので、ネストされたforループを使用しているためです。コードの複雑さを教えてくれるツールはありますか。よろしくお願いします。非常に素朴な場合はしばらくお待ちください。

回答

1 Bobby Aug 26 2020 at 23:37
int [] arrayToBeSorted;
Scanner scan=new Scanner(System.in);

修飾子がない場合、メンバーと関数はpackage-privateです。つまり、同じパッケージからアクセスできますが、クラスを拡張するインスタンスからはアクセスできません。実際、オブジェクト指向の観点から見ると、これは非常に奇妙なことです。それらを作成するprivateか、拡張クラスがそれらにアクセスできるようにする必要がある場合は、protected

コンストラクターについても同じことが言えます。


    System.out.println("Enter the number of elements");
    int total=scan.nextInt();
    this.arrayToBeSorted=new int[total];

配列の代わりにList/ArrayListを使用できます。これは、事前にカウントを指定しなくても、ユーザーから必要な数の数値を受け取ることができることを意味します。空の入力を使用して、リストの終わりを宣言できます。ただし、これには、のInteger代わりに使用する必要があるという欠点があるintため、何が優れているかを判断するのは少し難しいです。また、空の入力を検出することは、に使用Scannerする必要があるため、から簡単に利用できるという欠点もあります。nextLine手動でをに変換しintます。

List配列を動的に拡大することで、をエミュレートすることもできます。すべてのアイテムに対してそれを行うことによって、このユースケースではパフォーマンスは重要ではありません。または、必要に応じてサイズを2倍にすることによって。


this.arrayToBeSorted=new int[total];

thisコンストラクターなど、同じスコープ内に同じ名前の変数がある場合にのみ、修飾子が必要です。

public ValueContainer(int value) {
    this.value = value;
}

this不要な場合は省略するのが一般的な方法です。インスタンス、静的変数、ローカル変数のいずれが使用されているのか混乱する状況に陥った場合は、とにかくそこで何か間違ったことをしました。


for(int i=0;i<total;i++) {

私は、ループ内の変数に「実際の」名前を使用することを強く支持しています。

for (int counter = 0; counter < total; counter++) {
// or
for (int index = 0; index < total; index++) {

public void Sort() {

Javaの命名規則では、メソッド/関数はlowerCamelCaseである必要があると規定されています。


int minIndex,min;

個人的には、同じ行で複数の変数を宣言することは避けたいと思います。宣言を見逃しやすくなります。


boolean swapRequired=false;

これは、変数の優れた名前の優れた例です。ありがとうございます。


    for(int x:this.arrayToBeSorted) {
        System.out.print(x+" ");
    }

残念ながら、それは変数の悪い名前です。寸法を操作する場合は、「x」、「y」、「z」のみを使用してください。ここでは、「値」または「数値」が最適な名前になります。


全体的に、それは有効に見えます。ただし、機能をテストするために実行しませんでした。変更する必要があるのは、コンストラクターにロジックがあることです。コンストラクターからロジックの意図を理解できないため、コンストラクターがロジックで満たされることを誰も期待していません。彼らは可能な限り何もしてはいけません。つまり、ロジックをに移動するsortか、さらに良いことに、に移動する必要がありますmain。ソーターは入力にまったく関係しない必要があります。理想的には、値の並べ替えのみに関係するInputReader必要があり、別のクラス(?)は入力の取得に関係する必要があります。だからあなたができることは次のようなものです:

public static final void main(String[] args) {
    InputReader inputReader = new InputReader();
    
    int[] values = inputReader.readValues();
    
    Sorter sorter = new Sorter();
    sorter.sort(value);
    
    // TODO Print sorted output.
}

これには、状態を保持する必要がまったくないという利点もありSorterます。これにより、デフォルトでスレッドセーフになります。