Clasificación de selección Java y análisis
He escrito un código de clasificación de selección en java. Conozco su algoritmo muy elemental, pero como estoy aprendiendo, quería su opinión sobre la calidad del código. Por favor, eche un vistazo al 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();
}
}
También sobre el análisis, ya que la selección es O (n2), ¿es porque estoy usando un bucle for anidado? ¿Hay alguna herramienta que nos informe sobre la complejidad del código? Gracias de antemano y tenga paciencia si es muy ingenuo.
Respuestas
int [] arrayToBeSorted;
Scanner scan=new Scanner(System.in);
Sin ningún modificador, los miembros y las funciones son package-private. Lo que significa que son accesibles desde el mismo paquete, pero no por instancias que extiendan la clase. Eso es algo extremadamente extraño, en realidad, cuando se mira desde un punto de vista orientado a objetos. Desea crearlos private, o si las clases extendidas deberían poder acceder a ellos, protected.
Lo mismo ocurre con el constructor.
System.out.println("Enter the number of elements");
int total=scan.nextInt();
this.arrayToBeSorted=new int[total];
Podría usar List/ ArrayListen lugar de una matriz, lo que significaría que puede recibir tantos números de los usuarios como desee sin tener que especificar el recuento de antemano. Se podría usar una entrada vacía para declarar el final de la lista. Sin embargo, eso tiene la desventaja de que debe usar Integeren lugar de int, por lo que es un poco difícil saber qué es mejor. También tiene la desventaja de que detectar una entrada vacía está fácilmente disponible desde Scanner, ya que necesitaría usar nextLinepara eso, con conversión manual a int.
También puede emular a Listmediante el crecimiento dinámico de la matriz. Ya sea haciéndolo para cada elemento, el rendimiento no importa en este caso de uso, o duplicando el tamaño cuando sea necesario.
this.arrayToBeSorted=new int[total];
Solo necesita el thismodificador si tiene una variable con el mismo nombre en el mismo ámbito, por ejemplo, en un constructor:
public ValueContainer(int value) {
this.value = value;
}
Es una práctica común omitir thissi no es necesario. Si alguna vez se encuentra en una situación en la que es confuso si se usa una instancia, una variable estática o local, de todos modos hizo algo mal.
for(int i=0;i<total;i++) {
Soy un defensor persistente del uso de nombres "reales" para las variables en los bucles.
for (int counter = 0; counter < total; counter++) {
// or
for (int index = 0; index < total; index++) {
public void Sort() {
Las convenciones de nomenclatura de Java establecen que los métodos/funciones deben ser minúsculasCamelCase.
int minIndex,min;
Personalmente, evitaría declarar múltiples variables en la misma línea. Hace que sea fácil pasar por alto la declaración.
boolean swapRequired=false;
Ese es un gran ejemplo de un gran nombre para una variable, ¡gracias!
for(int x:this.arrayToBeSorted) {
System.out.print(x+" ");
}
Eso, desafortunadamente, es un mal nombre para una variable. Solo use "x", "y" y "z" cuando trabaje con dimensiones. "valor" o "número" sería un gran nombre aquí.
En general, parece válido. Sin embargo, no lo ejecuté para probar la funcionalidad. Lo que debes cambiar es que tienes lógica en el constructor. Nadie espera que los constructores estén llenos de lógica, porque no puedes ver la intención de la lógica en ellos. Deben estar haciendo nada como sea posible. Eso significa que debe mover la lógica a sorto, mejor aún, a main. Su clasificador no debería preocuparse por la entrada en absoluto, solo debería preocuparse por clasificar valores, idealmente, y otra clase ( InputReader?) debería preocuparse por obtener la entrada. Así que lo que podrías hacer es algo como esto:
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.
}
Eso también tiene la ventaja de que no necesita mantener el estado en Sorterabsoluto, lo que lo haría seguro para subprocesos de forma predeterminada.