Выборочная сортировка 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.

Вы также можете эмулировать a List, динамически увеличивая массив. Либо выполняя это для каждого элемента, производительность не имеет значения в этом случае использования, либо увеличивая размер вдвое, когда это необходимо.


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, что по умолчанию сделает его поточно-ориентированным.