Java de classificação de seleção e análise

Aug 26 2020

Eu escrevi um código de classificação de seleção em java. Eu conheço seu algoritmo muito elementar, mas como estou aprendendo, queria sua opinião sobre a qualidade do código. Por favor, dê uma olhada no código: 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();
}

}

Também sobre Análise, como a seleção é O(n2), é porque estou usando loop for aninhado. Existe alguma ferramenta que nos informe sobre a complexidade do código? Agradecemos antecipadamente e seja paciente se for muito ingênuo

Respostas

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

Sem nenhum modificador, membros e funções são package-private. O que significa que eles são acessíveis a partir do mesmo pacote, mas não por instâncias que estendem a classe. Isso é uma coisa extremamente estranha, na verdade, quando se olha de um ponto de vista orientado a objetos. Você deseja torná-los private, ou se as classes de extensão puderem acessá-los, protected.

O mesmo vale para o construtor.


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

Você pode usar um List/ ArrayListem vez de um array, o que significa que você pode receber quantos números os usuários quiserem sem precisar especificar a contagem de antemão. Uma entrada vazia pode ser usada para declarar o fim da lista. No entanto, isso tem a desvantagem de que você deve usar Integerem vez de int, então é meio difícil dizer o que é melhor. Ele também tem a desvantagem de detectar uma entrada vazia prontamente disponível em Scanner, pois você precisaria usar nextLinepara isso, com conversão manual para int.

Você também pode emular um Listaumentando dinamicamente a matriz. Fazendo isso para cada item, o desempenho não importa neste caso de uso, ou dobrando o tamanho quando necessário.


this.arrayToBeSorted=new int[total];

Você só precisa do thismodificador se tiver uma variável com o mesmo nome no mesmo escopo, por exemplo em um construtor:

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

É prática comum omitir thisse não for necessário. Se você alguma vez se encontrar na situação em que é confuso se uma variável de instância, estática ou local é usada, você fez algo errado de qualquer maneira.


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

Sou um defensor muito persistente do uso de nomes "reais" para variáveis ​​em loops.

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

public void Sort() {

As convenções de nomenclatura Java afirmam que os métodos/funções devem ser lowerCamelCase.


int minIndex,min;

Pessoalmente, eu evitaria declarar várias variáveis ​​na mesma linha. Isso torna mais fácil perder a declaração.


boolean swapRequired=false;

Esse é um ótimo exemplo de um ótimo nome para uma variável, obrigado!


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

Isso, infelizmente, é um nome ruim para uma variável. Use apenas "x", "y" e "z" ao trabalhar com dimensões. "valor" ou "número" seria um ótimo nome aqui.


No geral, parece válido. Eu não o executei para testar a funcionalidade, no entanto. O que você deve mudar é que você tem lógica no construtor. Ninguém espera que os construtores sejam preenchidos com lógica, porque você não pode ver a intenção da lógica neles. Eles devem ser tão nada fazendo quanto possível. Isso significa que você deve mover a lógica para sortou, melhor ainda, para main. Seu classificador não deve se preocupar com a entrada, ele deve se preocupar apenas com a classificação de valores, idealmente, e outra classe ( InputReader?) deve se preocupar em obter a entrada. Então o que você poderia fazer é algo assim:

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

Isso também tem a vantagem de que você não precisa manter o estado Sorter, o que o tornaria thread-safe por padrão.