package cl.cromer.estructuras; /** * Crear una estructura de dato de tipo array. * @author Chris Cromer */ public class Array { /** * El array. */ private String array[]; /** * La cantidad de elementos en el array. */ private int size; /** * Si es de tipo ordenado o simple. */ private boolean ordered; /** * Crear el array con el tamaño pasador por argumento. * @param tamano int: El tamaño del array a crear. */ public Array(int tamano) { this.array = new String[tamano]; size = 0; ordered = false; } /** * Devolver la cantidad de elementos en el array. * @return int: Devolver la cantidad de elementos en el array. */ public int size() { return size; } /** * Dovolver si el tipo es ordenado o no. * @return boolean: Si el tipo de array es ordenado. */ public boolean isOrdered() { return ordered; } /** * Cambiar el tipo de array entre ordenado o simple. * @param ordered boolean: Si es verdad, es de tipo ordenado, sino el tipo es simple. */ public void setOrdered(boolean ordered) { this.ordered = ordered; } /** * Insertar un valor al array. * @param valor int: El valor a insertar. * @return boolean: Verdad si fue exitoso, sino falso. */ public boolean insertar(int valor) { for (int i = 0; i < array.length; i++) { if (array[i] == null) { array[i] = String.valueOf(valor); size++; return true; } else if (array[i].equals(String.valueOf(valor))) { // Ya existe el valor en el array return false; } } return false; } /** * Eliminar un valor del array si existe. * @param valor int: El valor a eliminar. * @return boolean: Verdad si fue encontrado y borrado, sino falso. */ public boolean eliminar(int valor) { boolean borrado = false; for (int i = 0; i < array.length; i++) { if (array[i] != null && array[i].equals(String.valueOf(valor))) { // Eliminar el valor array[i] = null; borrado=true; size--; if (ordered) { for (int j = i; j < array.length; j++) { if (j != array.length - 1) { // Correr la array hacia arriba array[j] = array[j + 1]; } } array[array.length-1] = null; } else { break; } } } return borrado; } /** * Buscar si existe un valor dentro el array. * @param valor int: Valor a buscar. * @return int: Devuelve el indice donde fue encontrado, o -1 si no fue encontrado. */ public int buscar(int valor) { for (int i = 0; i < array.length; i++) { if (array[i] != null && array[i].equals(String.valueOf(valor))) { // Se encontró return i; } } // No se encontró return -1; } /** * Devolver el valor que está guardado en cada indice del array. Se usa para construir la grafica. * @param indice int: El indice que desea ver. * @return String: El valor que está en dicho indice. */ public String getIndice(int indice) { if (indice >= 0 && indice < array.length) { return array[indice]; } else { return null; } } /** * Ordenar el array usando burbuja. * @param paso boolean: Si es verdad, solo hago en paso del ordenamiento, sino ordenear todos los elementos. * @return boolean: Verdad si algo cambió, sino falso. */ public boolean burbuja(boolean paso) { boolean cambio = false; for (int i = size() - 1; i > 1; i--) { for (int j = 0; j < i; j++) { if (Integer.valueOf(array[j]) > Integer.valueOf(array[j+1])) { String temp = array[j]; array[j] = array[j+1]; array[j+1] = temp; cambio = true; if (paso) { return true; } } } } return cambio; } /** * Ordenar el array usando inserción. * @param paso boolean: Si es verdad, solo hago en paso del ordenamiento, sino ordenear todos los elementos. * @return boolean: Verdad si algo cambió, sino falso. */ public boolean insercion(boolean paso) { boolean cambio = false; for (int i = 1; i < size(); i++) { String temp = array[i]; int j = i; while (j > 0 && Integer.valueOf(array[j-1]) >= Integer.valueOf(temp)) { array[j] = array[j-1]; --j; cambio = true; } array[j] = temp; if (paso && cambio) { return true; } } return cambio; } /** * Ordenar el array usando selección. * @param paso boolean: Si es verdad, solo hago en paso del ordenamiento, sino ordenear todos los elementos. * @return boolean: Verdad si algo cambió, sino falso. */ public boolean seleccion(boolean paso) { boolean cambio = false; for (int i = 0; i < size() - 1; i++) { int minimo = i; for (int j = i + 1; j < size(); j++) { if (Integer.valueOf(array[j]) < Integer.valueOf(array[minimo])) { minimo = j; cambio = true; } } String temp = array[i]; array[i] = array[minimo]; array[minimo] = temp; if (paso && cambio) { return true; } } return cambio; } /** * Ordenar el array usando shell. * @param paso boolean: Si es verdad, solo hago en paso del ordenamiento, sino ordenear todos los elementos. * @return boolean: Verdad si algo cambió, sino falso. */ public boolean shell(boolean paso) { boolean cambio = false; int j, i; String temp; int h = 1; while (h <= size() / 3) { h = h * 3 + 1; } while (h > 0) { for (i=h; i < size(); i++) { temp = array[i]; j = i; while (j > h-1 && Integer.valueOf(array[j-h]) >= Integer.valueOf(temp)) { array[j] = array[j-h]; j -= h; cambio = true; } array[j] = temp; if (paso && cambio) { return true; } } h = (h-1) / 3; } return cambio; } /** * Ordenar el array usando quick. * @param paso boolean: Si es verdad, solo hago en paso del ordenamiento, sino ordenear todos los elementos. * @return boolean: Verdad si algo cambió, sino falso. */ public boolean quick(boolean paso) { String array[] = this.array.clone(); boolean cambio = false; boolean cambio2; cambio2 = recurenciaQuick(0, size() - 1, paso); for (int i = 0; i < size(); i++) { if (!array[i].equals(this.array[i])) { cambio = true; } } return (cambio || cambio2); } /** * Metodo recursivo para ordenar using quick sort. * @param izquerda int: La posición del quick desded la izquerda. * @param derecha int: La posición del quick desded la derecha.. * @param paso boolean: Si es verdad, solo hago en paso del ordenamiento, sino ordenear todos los elementos. * @return boolean: Verdad si algo cambió, sino falso. */ private boolean recurenciaQuick(int izquerda, int derecha, boolean paso) { boolean cambio; boolean cambio2; if (derecha - izquerda <= 0) { return false; } else { String pivot = array[derecha]; ParticionarResult particionarResult = particionar(izquerda, derecha, pivot); if (paso && particionarResult.getCambio()) { return particionarResult.getCambio(); } cambio = recurenciaQuick(izquerda, particionarResult.getPunteroIzquerda() - 1, paso); cambio2 = recurenciaQuick(particionarResult.getPunteroIzquerda() + 1, derecha, paso); return (paso && (cambio || cambio2)); } } /** * Particionar el array desded la izquerda y derecho usando un pivot. * @param izquerda int: La posición del quick desde la izquerda. * @param derecha int: La posición del quick desde la derecha. * @param pivot String: El valor a comparar con los otros. * @return ParticionarResult: Los resultados de particionar. */ private ParticionarResult particionar(int izquerda, int derecha, String pivot) { boolean cambio = false; int punteroIzquerda = izquerda-1; int punteroDerecha = derecha; while (true) { //noinspection StatementWithEmptyBody while (Integer.valueOf(array[++punteroIzquerda]) < Integer.valueOf(pivot)); //noinspection StatementWithEmptyBody while (punteroDerecha > 0 && Integer.valueOf(array[--punteroDerecha]) > Integer.valueOf(pivot)); if (punteroIzquerda >= punteroDerecha) { break; } else { String temp = array[punteroIzquerda]; array[punteroIzquerda] = array[punteroDerecha]; array[punteroDerecha] = temp; cambio = true; } } String temp = array[punteroIzquerda]; array[punteroIzquerda] = array[derecha]; array[derecha] = temp; return new ParticionarResult(cambio, punteroIzquerda); } /** * Esta clase contiene los resultados de Partricionar. */ final public class ParticionarResult { /** * Si habia algun cambio. */ private boolean cambio; /** * La parte izquerda que cambió. */ private int punteroIzquerda; /** * Inicializar. * @param cambio boolean: Si habia un cambio o no. * @param punteroIzquerda: El valor desde la izquerda donde fue un cambio. */ public ParticionarResult(boolean cambio, int punteroIzquerda) { this.cambio = cambio; this.punteroIzquerda = punteroIzquerda; } /** * Devolver el cambio. * @return boolean: Devolver el valor de cambio. */ public boolean getCambio() { return cambio; } /** * Devolver el puntero izquerda. * @return int: Devolver el valor de puntero. */ public int getPunteroIzquerda() { return punteroIzquerda; } } /** * Ordenar el array usando merge. * @param paso boolean: Si es verdad, solo hago en paso del ordenamiento, sino ordenear todos los elementos. * @return boolean: Verdad si algo cambió, sino falso. */ public boolean merge(boolean paso) { String array[] = this.array.clone(); boolean cambio = false; boolean cambio2; String[] temp = new String[size()]; cambio2 = recurenciaMerge(temp, 0, size() - 1, paso); for (int i = 0; i < size(); i++) { if (!array[i].equals(this.array[i])) { cambio = true; } } return (cambio || cambio2); } /** * El metodo recursivo para ordenar con merge. * @param temp String[]: El array temporario para trabajar. * @param izquerda int: El lado izquerda. * @param derecha int: El lado derecha. * @param paso boolean: Verdad si es paso por paso. * @return boolean: Devolver si algo cambió. */ private boolean recurenciaMerge(String[] temp, int izquerda, int derecha, boolean paso) { if (izquerda != derecha) { boolean cambio; boolean cambio2; boolean cambio3; int medio = (izquerda + derecha) / 2; cambio = recurenciaMerge(temp, izquerda, medio, paso); if (paso && cambio) { return true; } cambio2 = recurenciaMerge(temp, medio + 1, derecha, paso); if (paso && cambio2) { return true; } cambio3 = merge(temp, izquerda, medio + 1, derecha, paso); return (paso && cambio3); } else { return false; } } /** * Este metodo hace los cambios al array. * @param temp String[]: El array temporario para trabajar. * @param prevIzquerda int: El valor previo de la izquerda. * @param prevMedio int: El valor previo al medio. * @param prevDerecha int: El valor previo de la derecha. * @param paso boolean: Si es paso por paso. * @return boolean: Devolver si algo cambió. */ private boolean merge(String[] temp, int prevIzquerda, int prevMedio, int prevDerecha, boolean paso) { boolean cambio = false; int j = 0; int izquerda = prevIzquerda; int medio = prevMedio - 1; int derecha = prevDerecha - izquerda + 1; while (prevIzquerda <= medio && prevMedio <= prevDerecha) { if (Integer.valueOf(array[prevIzquerda]) < Integer.valueOf(array[prevMedio])) { temp[j++] = array[prevIzquerda++]; } else { temp[j++] = array[prevMedio++]; } } while (prevIzquerda <= medio) { temp[j++] = array[prevIzquerda++]; } while (prevMedio <= prevDerecha) { temp[j++] = array[prevMedio++]; } for (j = 0; j < derecha; j++) { String temp2 = array[izquerda + j]; array[izquerda + j] = temp[j]; if (paso && !array[izquerda + j].equals(temp2)) { cambio = true; } } return cambio; } }