Java de classificação de seleção e análise
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
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.