Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
para Ingeniera de
Sistemas y Computacin
Anlisis de Algoritmos
para Ingeniera de
Sistemas y Computacin
Derechos reservados
Diciembre de 2011
ISBN: 978-958-99930-2-6
ELIZCOM S.A.S
www.elizcom.com
ventas@elizcom.com
NIT 90004331-7
Armenia, Quindo Colombia
Tel. 7493244
Cel: 57+3113349748
Java y todas las marcas y logos basados en Java son marcas comerciales o marcas registradas de ORACLE Sun,
La marca de Eclipse y sus logotipos aparecen de acuerdo con las condiciones legales de Eclipse, expuestas en
http://www.eclipse.org/legal/main.html
Microsoft Office y su logotipo es una marca registrada por Microsoft Corporation.
CMAP Tools son marca registrada por ihmc - Florida institute for Human & Machine Cognition
2.2
Algoritmos Divide y Vencers ................................................................... 107
2.2.1 Bsqueda Binaria...................................................................................... 107
2.2.2 Ordenamiento por el mtodo MergeSort .................................................. 108
2.2.3 Multiplicacin de Nmeros Grandes ........................................................ 110
2.3
Algoritmos Devoradores ............................................................................ 114
2.3.1 El Problema de la mochila ........................................................................ 115
2.3.2 Elementos de los Algoritmos Voraces...................................................... 120
2.3.3 El problema de la Devuelta. ..................................................................... 121
2.4
Actividad Independiente: El problema de la Devuelta ........................... 123
2.5
Programacin Dinmica ............................................................................ 126
2.5.1 Serie de Fibonacci .................................................................................... 126
2.5.2 Problema de la Mochila ............................................................................ 130
2.5.3 Problema de la Devuelta ........................................................................... 132
2.5.4 Algoritmo de Dijkstra ............................................................................... 134
2.5.5 Hoja de trabajo: Lotera ............................................................................ 135
3
PRESENTACIN
El Anlisis de Algoritmos se considera como una temtica fundamental dentro del proceso de
formacin de los estudiantes de Ingeniera de Sistemas y Computacin, pues posee una
estrecha relacin con otras reas de formacin del ingeniero, como lo son la programacin de
computadores, las estructuras de datos, las Matemticas Discretas y la teora de grafos entre
otras.
Las orientaciones sociolgicas y pedaggicas que permitieron la elaboracin de este libro y su
viabilidad en el campo profesional y terico, estn orientadas a fortalecer el objetivo o propsito
general de formacin del Ingeniero de Sistemas y Computacin. Desde la perspectiva
sociolgica, quienes comparten los conceptos del anlisis de algoritmos, son capaces de
emplearlo para: comprender, explicar, demostrar, solucionar problemas, crear o hacer
representaciones, orientados a compartir su significado con otras personas. Desde la
perspectiva pedaggica, se pretenden establecer estrategias de enseanza que faciliten a los
estudiantes los aprendizajes requeridos en esta disciplina tanto en lo cientfico como en lo
formal, cotidiano y viceversa.
El presente libro pretende con su estrategia de enseanza, la resolucin de problemas usando
el anlisis de algoritmos. En ste, se agregan actividades que contribuyen a la mejor
comprensin de los conceptos plasmados a lo largo de los captulos. Al poseer una estructura
coherente, el estudiante podr trabajar a travs de cada uno de ellos, convirtindose en un
verdadero actor del proceso de aprendizaje, esto conlleva a que el rol del docente sufra una
profunda transformacin, se ha migrado hacia la idea de un consultor. Teniendo en cuenta que
el anlisis de algoritmos comprende una amplia variedad de temas, consideramos que es
fundamental que los estudiantes identifiquen la importancia de esta disciplina dentro de su
proceso de formacin.
Por un lado el libro recoge nuestra experiencia en la enseanza de las asignaturas
relacionadas con la algoritmia y la programacin, y nos ha permitido ver la importancia que
tiene el disponer de una metodologa de trabajo que permita abordar la resolucin de los
problemas de una forma simple, coherente y estructurada. Por otro lado este libro es una
versin que retoma los conceptos fundamentales de los libros de anlisis de algoritmos en java
y Tcnicas de Diseo de Algoritmos en java, en el cual, continua siendo un objetivo de los
autores proporcionar una introduccin comprensible y slida de los elementos fundamentales
del anlisis de algoritmos. Teniendo en cuenta las observaciones y las oportunidades de
mejora propuestas tanto por estudiantes como profesores que usaron estos libros, se
realizaron cambios para este libro, con el objetivo de aportar al proceso de formacin de los
profesores. El libro se adapt teniendo en cuenta el micro currculo vigente del curso anlisis
de algoritmos I.
El texto fue escrito pensando principalmente en aquellos estudiantes de Ingeniera de Sistemas
y afines que tienen los conocimientos fundamentales de las Matemticas Discretas y Lgica de
Programacin y que deseen aprender los conceptos bsicos a tener en cuenta en el anlisis de
algoritmos. Este libro se utilizar como referencia para la asignatura Anlisis del Algoritmos I
del programa de Ingeniera de Sistemas y Computacin de la Universidad del Quindo.
Este libro pretende ser flexible en la forma como puede impartirse a las personas interesadas.
La comprensin de los temas, depende fundamentalmente de la preparacin de los
estudiantes. Se presentan conceptos bsicos fundamentales e intermedios, los cuales se
pueden aplicar en la prctica, as como tambin realizar un anlisis riguroso de los conceptos
tericos que se imparten. El texto est orientado al estudiante, y hemos puesto el mayor
empeo para explicar cada tema tan claramente como sea posible.
INTRODUCCIN
El objetivo de este libro de texto consiste en mostrar los elementos fundamentales del anlisis
de algoritmos, estrategias de programacin, el anlisis de algoritmos aplicados a estructuras de
datos, anlisis de grafos y tcnicas de optimizacin de cdigo, los cuales son temas que tienen
una serie de aplicaciones en diferentes reas de las ciencias computacionales. Se pretende
establecer una relacin de aplicacin entre los conceptos tericos y su aplicacin especfica en
el campo de la Ingeniera de Sistemas y Computacin.
El libro tiene los siguientes objetivos:
Presentar casos de estudio y hojas de trabajo. En este aspecto, todos los ejemplos se
encuentran desarrollados en java, dado que es un lenguaje de programacin de
aceptacin mundial tanto en mbito industrial como en el mbito acadmico.
Es de suponer que los lectores de este libro tienen los conocimientos bsicos de algoritmia y
est familiarizado con algn lenguaje de programacin. Los ejemplos sern implementados en
su totalidad en el lenguaje de programacin java y se dar importancia nicamente a los
aspectos ms esenciales, sin sobrecargar al lector en temas que pueden ser objeto de estudio
en otros libros relacionados con la programacin y la algoritmia.
El libro est estructurado en 5 captulos los cuales pretenden de forma progresiva mostrar
diferentes temas que son abordados de forma simple y estructurada, a continuacin, se
muestra un breve resumen de los temas que se presentan en el mismo.
En el primer captulo denominado anlisis de algoritmos, se analiza el tiempo de ejecucin de
los algoritmos y presentamos su forma de calcularlo. Se muestra una amplia variedad de
ejemplos los cuales permitirn al estudiante conocer y entender los diferentes tiempos de
ejecucin que se pueden obtener de los algoritmos. Adicionalmente se trabajarn temas como
el tiempo de ejecucin de los algoritmos iterativos, la complejidad computacional y notaciones
asintticas, el anlisis de algoritmos recursivos, de los mtodos de ordenamiento y los
algoritmos de bsqueda.
En el segundo captulo llamado estrategias de programacin, se trabajar con algoritmos que
se emplean en problemas de optimizacin en los cuales se pretende maximizar o minimizar
algn valor. Se mostrarn casos considerados tpicos como el problema de la mochila, el
1.1
ANLISIS DE ALGORITMOS
Introduccin
1.2
Definicin de Algoritmo
Se conoce como algoritmo a una secuencia de instrucciones, que son ejecutadas con
esfuerzos finitos en un tiempo razonable, que recibe un conjunto de valores como entrada y
produce un conjunto de valores como salida. Para la ejecucin de estas instrucciones es
necesario contar con una cantidad finita de recursos.
Segn (Valenzuela, 2003), cuando nos referimos al concepto de algoritmo, hacemos referencia
a los pasos encaminados a la consecucin de un objetivo. Un algoritmo puede ser
caracterizado por una funcin lo cual asocia una salida: s= f (E) a cada entrada E.
Se dice entonces que un algoritmo calcula una funcin f. Entonces la entrada es una variable
independiente bsica en relacin a la que se producen las salidas del algoritmo, y tambin los
anlisis de tiempo y espacio (Valenzuela, 2003).
En las Ciencias de la Computacin cuando se dice que un problema tiene solucin, significa
que existe un algoritmo susceptible de implantarse en una computadora, capaz de producir la
respuesta correcta para cualquier instancia del problema en cuestin. De acuerdo a ello, la
construccin de un programa hace referencia directa a la implementacin de uno o ms
algoritmos.
Un problema es resuelto algortmicamente, si se puede escribir un programa que pueda
producir la respuesta correcta, de forma que para cualquier posible entrada, el programa puede
ser ejecutado en tiempo finito, teniendo en cuenta los recursos computacionales para
resolverlo.
En la literatura asociada al tema se encuentra una cantidad muy amplia de tipos de algoritmos
entre los cuales adicionalmente se pueden citar los algoritmos paralelos, probabilsticos,
voraces, divide y vencers, dinmicos. Estos tres ltimos se tratarn en captulos posteriores
del libro.
La implementacin de un algoritmo debe ser en todos los casos:
Correcta: Si para toda instancia del conjunto de entrada se obtiene la salida esperada,
es decir, que cumpla con el objetivo para el cual est pensado.
Eficiente: Debe ser rpido y usar la menor cantidad de recursos. Es una relacin entre
los recursos consumidos, fundamentalmente tiempo y memoria versus los productos
obtenidos.
Si los anteriores elementos resueltos de forma positiva dan nocin de lo que es un buen
algoritmo. Por lo tanto se pueden generar las siguientes frases que se convertirn en preguntas
cuando estemos analizando cada uno de nuestros programas.
Para aproximar mejor los elementos anteriores, observemos el siguiente ejemplo: se desea
determinar si un nmero entero positivo predeterminado es primo o no lo es. El conjunto de los
nmeros primos es un subconjunto de los nmeros naturales que contiene aquellos que son
divisibles por s mismos y por la unidad.
Son entre otros nmeros primos: 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43. A
continuacin se muestra una implementacin del mtodo que resuelve el problema en
mencin.
10
Implementacin
del Mtodo
Cumple el algoritmo el objetivo para el cual est pensado? Solo en el caso en cual se
ingresa un nmero entero positivo, el algoritmo genera una salida correcta y cumplira
con su objetivo.
El algoritmo hace uso adecuado de los recursos? Si, dado que se usan las variables
estrictamente necesarias para la solucin y se utiliza un tipo de dato con rango de
valores moderado.
Permite el algoritmo identificar posibles errores? No, dado que el programa no maneja
excepciones que controlen posibles errores.
El algoritmo es fcil de modificar para aadir funcionalidad? Si, dada la sencillez del
problema y de la solucin propuesta.
Implementacin
del Mtodo
11
else
{
return false;
}
}
Para esta implementacin es posible dar respuesta a los siguientes interrogantes:
Cumple el algoritmo el objetivo para el cual est pensado? Solo, en el caso en el que
se ingrese un nmero entero positivo, el algoritmo genera una salida correcta.
Hace el algoritmo uso adecuado de los recursos? Si, pues para algunos casos no
itera toda la cantidad de veces permitida por el ciclo.
El algoritmo permite identificar posibles errores? No, dado que el programa no maneja
excepciones que controlen posibles errores.
El algoritmo es fcil de modificar para aadir funcionalidad? Si, dada la sencillez del
problema y de la solucin propuesta.
ACTIVIDAD
Implementacin
del Mtodo
Respuesta
12
Implementacin
del Mtodo
Respuesta
ACTIVIDAD
Entre las varias sucesiones interesantes de nmeros que existen en las matemticas discretas
y combinatorias, estn los nmeros armnicos, los cuales tienen la forma:
13
H1 + H2 + H3 + donde:
Y en general,
para cualquier
(Grimaldi, 1998)
Implementacin
del Mtodo
}
Con bases en la implementacin propuesta, responda los siguientes interrogantes.
Pregunta
Cumple el algoritmo el objetivo
para el cual est pensado?
Resuelve el algoritmo el problema
en el menor tiempo posible?
El algoritmo permite identificar
posibles errores?
Respuesta
Realice una comparacin entre el mtodo que usted implement, con el siguiente mtodo y
posteriormente responda la pregunta:
Implementacin
del Mtodo
Pregunta
Cul de los dos algoritmos es
ms eficiente?
Respuesta
14
1.3
Preciso: Un algoritmo preciso, posee un orden especfico en cada uno de los pasos
que este ejecuta. Por esta razn cuando se ejecuta un paso del algoritmo, se conoce
con certeza cul es el paso siguiente a ejecutar.
Finito: El algoritmo debe finalizar tras una secuencia o nmero finito de pasos.
Efectivo: La eficiencia hace alusin al logro de la solucin a un problema de la mejor
manera posible (en trminos de tiempo). En el ambiente computacional, lo son el buen
uso de los recursos de hardware.
Determine si la siguiente implementacin del mtodo, cumple con las caractersticas de los
algoritmos definidas anteriormente.
Implementacin
del Mtodo
Respuesta
Para finalizar esta seccin cabe mencionar que dentro de la Ingeniera de software, tambin se
contemplan factores fundamentales en la calidad del software, entre los cuales tenemos:
15
1.4
Compatibilidad: Facilidad para que un programa pueda usarse en unin con otros
programas.
Extensibilidad: Es la capacidad que tiene un programa de ampliar la funcionalidad de
acuerdo a nuevas necesidades o requerimientos.
Verificabilidad: Es la capacidad que tiene un programa para soportar casos de prueba
y para identificar posibles errores.
Exactitud: Es el atributo que determina el nivel de precisin de los resultados
obtenidos por un programa.
16
los nombres de variables, de las clases y de los mtodos, todos estos deben estar
acordes a las tareas que realizan.
Existen estndares para usar convenciones de programacin. Las convenciones de
cdigo son importantes para los programadores por un gran nmero de razones
(Molpeceres, 2001) :
o
o
o
o
Para conocer las convenciones de cdigo definidas por el proveedor oficial de java se
recomienda visitar el site (octubre de 2011), el cual contiene los elementos bases para
el uso de estndares: http://www.oracle.com/technetwork/java/codeconv-138413.html
1.5
Dentro del entorno de la informtica no siempre los problemas necesidades de las personas
o las organizaciones, se encuentran claramente definidas, es necesario en muchas ocasiones
realizar una clara formulacin del problema. Solo partiendo de una correcta formulacin de
este, ser posible especificar una metodologa para su solucin.
Segn (Cardona, Jaramillo, & Carmona, Anlisis de Algoritmos en Java, 2007), una buena
planificacin de las tareas a realizar para desarrollar un programa favorece el xito en la
implementacin. La planificacin debe estar basada en el establecimiento de fases. Las fases,
tanto para realizar programas sencillos como para llevar a cabo proyectos de envergadura de
construccin de aplicaciones informticas se pueden ver en la figura.
Una vez definido el problema, se realiza la especificacin del problema, por medio de
los que se conoce como diseo detallado o algortmico, en donde se definen y
documentan los detalles y algoritmos de cada una de las funciones
Con base en el diseo, se construyen los algoritmos necesarios para la solucin del
problema, para posteriormente estos se implementados en un lenguaje de
programacin. Cada algoritmo implementado, debe ser verificado para comprobar las
operaciones para las cuales fue construido, estos se deben someter a un conjunto de
pruebas.
Finalmente se tiene una aplicacin de software, que debe dar la solucin esperada de
acuerdo a los requerimientos planteados inicialmente.
17
1.6
Para este libro, tendremos en cuenta el anlisis para el peor de los casos.
Tradicionalmente se usan estrategias para la estimacin de los tiempos de ejecucin, el
siguiente mapa conceptual nos muestra los elementos fundamentales:
18
1.6.1
Despus de realizar un estudio sobre las diversas tcnicas para el anlisis de algoritmos, se
utilizar la tcnica de anlisis. Esta tcnica permitir que la estimacin, se realizar en funcin
del nmero de operaciones elementales que realiza dicho algoritmo para un tamao de entrada
dado.
Entendiendo por operaciones elementales como aquellas operaciones cuyo tiempo de
ejecucin se puede acotar superiormente por una constante (Guerequeta & Vallecillo, 2000).
As, se consideran como operaciones elementales:
Nombre
Operaciones aritmticas bsicas
Asignaciones a variables
Comparaciones lgicas o relacionales
Acceso a estructuras de datos estticas y dinmicas
Parmetros que llegan a los mtodos
Instrucciones de salto
Retorno de valores
Instrucciones condicionales
Creacin de Objetos
Expresiones que con incrementos y decrementos
Referencias a objetos
Operadores de acumulacin
Operadores o instrucciones
+,-,*,/,%
=
&&,||,<,<,>=,=<,==,!=
[], [][]
mtodo(variable valor)
break, continue
return
if, if-else
new
++, -null, object
+=,-=
1.6.2
19
Ejemplo
Mtodo
Anlisis del
tiempo de
ejecucin
T(n)
ACTIVIDAD
Mtodo
Explicacin del
tiempo de
ejecucin
T(n)
1.6.3
Muchos de los problemas que se resuelven a nivel de programacin, estn relacionados con el
uso de ciclos. A continuacin, se muestran una serie de ejemplos que permitirn establecer el
tiempo de ejecucin para mtodos que poseen ciclos en su implementacin. Para cada uno de
los mtodos se considerar el peor caso.
20
Ejemplo
Mtodo
Anlisis del
Tiempo de
ejecucin
T(n)
T(n) = 4n+3.
A continuacin se muestra otro ejemplo en el cual se estima el tiempo de ejecucin del mtodo.
El mtodo recibe tres parmetros por valor, lo que implica que cada uno de esos valores se
ejecuta una vez.
Ejemplo
Mtodo
Anlisis del
Tiempo de
ejecucin
T(n)
int x
int y
int n
i = 3
i <= n
x = i * j
y = w * x
i++
Se ejecuta 1 vez
Se ejecuta 1 vez
Se ejecuta 1 vez
Se ejecuta 1 vez
Se ejecuta ((n + 1) - 3) + 1 veces
Se ejecuta (n-2) veces
Se ejecuta (n-2) veces
Se ejecuta (n-2) veces
21
Ejemplo
Mtodo
Anlisis del
Tiempo de
ejecucin
T(n)
A continuacin se muestra una forma de estimar la funcin T(n) cuando se tiene la estructura ifelse. Segn la sintaxis de los lenguajes de programacin, cuando se cumple el if el else no
se analiza, en el caso en el que no se cumpla el if el else se ejecuta.
Cuando if o else tienen igual nmero de lneas de implementacin, se puede escoger
cualquiera de los dos. Para este ejemplo el valor del parmetro n, debe ser n > 1.
Ejemplo
Mtodo
22
Anlisis del
Tiempo de
ejecucin
T(n)
ACTIVIDAD
Estime y argumente el clculo del tiempo de ejecucin para los siguientes mtodos:
Ejercicio
Mtodo
Explicacin del
tiempo de
ejecucin
T(n)
T(n) =
Mtodo
23
Anlisis del
Tiempo de
ejecucin
T(n)
Estimar el tiempo de ejecucin del siguiente mtodo, analizando el caso en el cual el
condicional if (w % i == 1) es verdadero en la ltima iteracin.
Ejercicio
Mtodo
Anlisis del
Tiempo de
ejecucin
T(n)
1.6.4
El uso de los ciclos anidados es una prctica muy frecuente y necesaria para la
implementacin de diferentes tipos de algoritmos. A continuacin vamos a estimar el tiempo de
ejecucin del mtodo que posee dos ciclos anidados.
Es comn cuando se tienen dos ciclos anidados que inician en un valor entero positivo e iteran
hasta n (siendo n un entero positivo muy grande) o viceversa, encontramos que la funcin T(n)
tiene un orden cuadrtico. Para verificar el correcto clculo del tiempo de ejecucin, se
recomienda asignar algn valor entero a la variable n y realizar un conteo de las instrucciones.
Ejemplo
Mtodo
24
Anlisis del
Tiempo de
ejecucin
T(n)
El mtodo tiene tres ciclos anidados, cada uno de los cuales se analizar por separado para
posteriormente estimar el tiempo de ejecucin total. Cada uno de los ciclos itera desde un valor
pequeo hasta n, por lo que el orden de la funcin de tiempo de ejecucin debera ser cbico.
Ejemplo
Mtodo
Tiempo de
ejecucin
T(n)
ACTIVIDAD
25
Ejercicio
Mtodo
Anlisis del
Tiempo de
ejecucin
T(n)
Estime y argumente el clculo del tiempo de ejecucin para el siguiente mtodo:
Ejercicio
Mtodo
Anlisis del
Tiempo de
ejecucin
T(n)
El siguiente cuadro, facilitar la forma para estimar la cantidad de veces que se repite un ciclo.
En ella se puede observar cual es la cantidad de iteraciones, teniendo claramente establecido:
26
Cantidad de iteraciones
n
n+1
n-k
n
n+1
n-k
n/k
(n-j)/k
log2 (n)
log2 (n) + 1
A continuacin se muestra un ejemplo que usa una estructura similar a la del ciclo for (i=n;
i > 0; i/=2). Para el anlisis de este algoritmo, debemos tener en cuenta el valor asignado
inicialmente a la variable i = 32, esta variable dentro del ciclo se va dividiendo cada vez por 2.
Se puede afirmar entonces la cantidad de veces que itera el ciclo es: log2(n) + 1.
Ejemplo
Mtodo
Anlisis del
Tiempo de
ejecucin
temp = 0
Se ejecuta 1 vez
x = 0
Se ejecuta 1 vez
y = 1
Se ejecuta 1 vez
i = 32
Se ejecuta 1 vez
while(i > 0) Se ejecuta log2(i) + 2 veces
x++
Se ejecuta log2(i) + 1 veces
temp++
Se ejecuta log2(i) + 1 veces
y = y * 1
Se ejecuta log2(i) + 1 veces
i = i/2
Se ejecuta log2(i) + 1 veces
Se realizan 6 comparaciones en el ciclo while(i > 0) ms la
ltima comparacin, basndose en la forma como cambia el
tamao de i. En este caso encontramos una relacin entre el
nmero de comparaciones del ciclo, (6 comparaciones) y el valor de
5
i = 32. Se puede determinar que 2 = 32, (5 es logaritmo en base 2
de 32), entonces las veces que se repite el ciclo es log2(i)+1.
T(n)
T(n) = 5(log2(i) + 1) + 5
A continuacin se muestra un ejemplo que usa una estructura similar a la del ciclo for (i=1;
i < n; i*=2).
27
Ejemplo
Mtodo
Anlisis del
Tiempo de
ejecucin
T(n)
ACTIVIDAD
Mtodo
Anlisis del
Tiempo de
ejecucin
T(n)
28
Ejercicio
Mtodo
Anlisis del
Tiempo de
ejecucin
T(n)
Explique detenidamente el funcionamiento del siguiente algoritmo y calcule su tiempo de
ejecucin. Deduzca el problema que resuelve y compare el mismo con otras implementaciones.
Mtodo
29
Anlisis del
Tiempo de
ejecucin
T(n)
1.6.5
Muchos de los problemas que se resuelven a nivel de programacin estn relacionados con los
llamados a los mtodos de las clases. A continuacin, se mostrarn ejemplos en los cuales se
calcula el tiempo de ejecucin para algoritmos que realizan este tipo de llamado.
Para la estimacin del tiempo de ejecucin realizando llamadas a mtodos, es necesario
analizar el tiempo de cada uno de los mtodos, y de esta forma establecer cul es el peor caso,
siempre considerando valores enteros grandes.
Ejemplo
Mtodo
Anlisis del
Tiempo de
ejecucin
T(n)
30
Las acciones A1, A2, A3, ..., An pueden ser acciones simples (una sola accin) o acciones
compuestas (un conjunto de acciones).
El tipo de la variable que se utiliza para controlar el switch es llamada selector. Cada uno de
los valores presentes en los casos (C1....Cn) debe ser de tipo compatible con el del selector.
Cada uno de estos valores debe ser nico, es decir, no se aceptan rangos.
El default (por defecto) se utiliza cuando ninguno de los casos coincide con el selector. Sin
embargo, la sentencia default es opcional. Si ningn case coincide y no hay sentencia
default, no se hace nada.
El break se utiliza en sentencias switch para terminar una secuencia de acciones. Cuando
se encuentra un break, la ejecucin salta a la primera lnea de cdigo que sigue a la sentencia
switch completa. Esto tiene el efecto de saltar fuera del switch.
Ejemplo
Mtodo
Anlisis del
Tiempo de
ejecucin
T(n)
T(n) = 4n + 5n + n + 18
ACTIVIDAD
31
Mtodo
Anlisis del
Tiempo de
ejecucin
T(n)
Calcular el tiempo de ejecucin para el siguiente mtodo.
Ejercicio
Mtodo
Anlisis del
Tiempo de
ejecucin
T(n)
Calcular el tiempo de ejecucin para el siguiente mtodo.
32
30
+ 5
n + 3
5
Ejercicio
Mtodo
Anlisis del
Tiempo de
ejecucin
T(n)
Calcular el tiempo de ejecucin para el siguiente mtodo.
Ejercicio
Mtodo
Anlisis del
Tiempo de
ejecucin
T(n)
33
1.7
ENTRADAS
RESULTADOS
Listado con todos los libros
34
NOMBRE
R4 - Mostrar el valor total de los libros que hay en la biblioteca.
RESUMEN Muestra el valor total de los libros que hay en la biblioteca.
ENTRADAS
RESULTADOS
El valor total de los libros.
DESCRIPCIN
Es la clase principal del mundo
Permite manejar la informacin de un docente
Contiene la informacin de la Editorial
c) Modelo de clases
Para este caso de estudio se muestran las clases del principales del dominio, estas clases
contienen todos los mtodos que cumplen con los requerimientos funcionales especificados en
el problema.
35
d) Implementacin de mtodos
Se mostraran los mtodos ms relevantes para la clase Biblioteca. Se debe calcular el
tiempo de ejecucin para cada uno de los mtodos.
Implementacin de los mtodos
public Biblioteca()
{
contador1=contador2=contador3=0;
mLibro=new ArrayList<Libro>();
}
T(n) =
void setMLibro(ArrayList <Libro> mLibro)
/**
* Permite fijar el array de libros
* @param mLibro se obtiene del archivo
*/
public void setMLibro(ArrayList <Libro> mLibro)
{
this.mLibro=mLibro;
}
T(n) =
ArrayList <Libro> getMLibro()
/**
* Devuelve el valor del array que contiene los libros
* @return ArrayList <Libro>
*/
public ArrayList <Libro> getMLibro()
{
return mLibro;
}
T(n) =
agregarLibro( String codEditorial, String
/**
* Permite agregar un libro
*/
public void agregarLibro(String codEditorial,String isbn,double valor)
{
Libro unLibro = new Libro(codEditorial);
if(codEditorial.equals("001"))
{
contador1++;
}
else
{
if(codEditorial.equals("002"))
{
contador2++;
}
36
else
{
contador3++;
}
}
unLibro.setIsbn(isbn);
unLibro.setValor(valor);
mLibro.add(unLibro);
}
T(n) =
obtenerCantidaFabricantes()
/**
* Permite obtener la cantidad de fabricantes
* @return String Contiene la cantidad de artculos por fabricante
*/
public String obtenerCantidaFabricantes()
{
return "Addison Wesley: "+contador1+" Mc Graw Hill: "+contador2+
"Prentice Hall: "+contador3;
}
T(n) =
determinarValorMercancia()
/**
* determina el valor total de la mercanca que hay en la biblioteca.
* @return double valor de los libros en la biblioteca
*/
public double determinarValorMercancia()
{
double valor=0;
for(int i=0; i<mLibro.size(); i++)
{
valor+=mLibro.get(i).getValor();
}
return valor;
}
T(n) =
getInfoLibros()
/**
* Devuelve la informacin de los libros que hay en la biblioteca
* @return String[]
*/
public String[] getInfoLibros()
{
String []info=new String [mLibro.size()];
for(int i=0; i<mLibro.size(); i++)
{
info[i] = mLibro.get(i).toString();
}
return info;
}
T(n) =
37
Nuestro proceso no ha finalizado aqu puesto que debemos pasar del diseo a la
implementacin. Esta fase se inicia con la evaluacin (en trminos de complejidad de
algoritmos y de espacio ocupado, de dificultad y de grado de desacoplamiento) de los diseos
que fueron propuestos, los cuales debern refinarse hasta que sea posible argumentar por qu
ese diseo es el mejor, siendo importante llevar a cabo las comparaciones pertinentes respecto
a los diseos obtenidos, fruto de la cual se seleccionar uno de ellos.
ACTIVIDAD
Escriba los mtodos para la clase Biblioteca que resuelven los problemas que se describen
a continuacin.
Ejercicio
Escriba un
mtodo que
retorne la
posicin en la
cual se
encuentra el
libro con el
mayor valor.
}
Anlisis del
Tiempo de
ejecucin
T(n)
Ejercicio
Escriba un
mtodo que
muestre el isbn
de los libros que
se encuentran
las posiciones
impares del
ArrayList.
}
Anlisis del
Tiempo de
ejecucin
T(n)
38
Ejercicio
Escriba un
mtodo que
muestre las
posiciones de
los libros cuyo
cdigo isbn
termina en el
carcter 5.
}
Anlisis del
Tiempo de
ejecucin
T(n)
Ejercicio
Escriba un
mtodo que
permita
determinar el
valor total de la
mercanca de
los elementos
que se
encuentran en
las posiciones
pares del
ArrayList.
Anlisis del
Tiempo de
ejecucin
T(n)
1.8
39
Cuando en una aplicacin se van a procesar pocos datos de entrada, es poco importante
analizar un algoritmo independiente del crecimiento de la funcin. Por ejemplo, si se desea
procesar 50 datos, es casi indistinto que se utilice un algoritmo con tiempo de ejecucin n o n
log(n), pero si se desea procesar 2000000 datos, el algoritmo con n log(n) crece
considerablemente con relacin a n. Es por ello necesario entrar a realizar un estudio sobre el
crecimiento y comportamiento asinttico de los tiempos de ejecucin de los algoritmos.
Funcin
Log2(n)
n
n log(n)
2
n
3
n
n
2
nombre
(Logartmico)
(Lineal)
n log(n)
Cuadrtico
Cbico
Exponencial
A continuacin se muestra una tabla con el crecimiento de algunas funciones polinmicas y las
cuales son las ms frecuentemente usadas en el anlisis de algoritmos.
40
ACTIVIDAD
Dadas la siguiente grafica con sus correspondientes funciones, realice un anlisis del
comportamiento de las mismas e indique cuando la una es ms eficiente que la otra. Las
2
funciones a comparar son 2n y log(n).
Para una implementacin completa que permita comparar dos algoritmos, se desea determinar
el mximo comn denominador de dos nmeros enteros positivos. El mximo comn divisor
(MCD) se define de la forma ms simple como el nmero ms grande posible, que permite
dividir a esos nmeros.
A continuacin se muestran dos implementaciones diferentes del mismo problema.
41
Mtodo 1
Mximo comn
Divisor
Mtodo 2
Mximo comn
Divisor
Se comparan ambos algoritmos asumiendo que los valores que se envan por parmetro al
mtodo son: a = 30 y b = 18. En el siguiente cuadro se observan las instrucciones necesarias
para la deduccin del MCD del segundo algoritmo.
A
30
b
18
..
..
resultado
1
i
18
17
16
15
14
..
7
6
i>0
18>0
17>0
16>0
15>0
14>0
..
7>0
6>0
If(a%i==0 b%i==0)
30%18==0 && 18%18==0
30%17==0 && 18%17==0
30%16==0 && 18%16==0
30%15==0 && 18%15==0
30&14==0 && 18%14==0
6
En el siguiente cuadro se observan las instrucciones que son necesarias para la deduccin del
MCD del primer algoritmo.
Valora
30
12
12
6
Valorb
18
18
6
6
While(valora!=valorb)
30!=18
12!=18
12!=6
6!=6
42
If(valora<valorb)
30<18
12<18
12<6
Considerando los cuadros anteriores, se puede deducir por los valores ingresados, que el
primer algoritmo es ms eficiente que el segundo. Esto dada la cantidad de instrucciones que
se ejecutan. Pero es posible afirmar lo mismo si los valores que se ingresan son
respectivamente: a = 38 y b = 4.
En el siguiente cuadro se observan las instrucciones necesarias para la deduccin del MCD del
segundo algoritmo.
a
38
B
4
resultado
1
2
i
4
3
2
i>0
4>0
3>0
2>0
If(a%i==0 b%i==0)
38%4==0 && 4%4==0
38%3==0 && 4%3==0
38%2==0 && 4%2==0
En el siguiente cuadro se observan las instrucciones que son necesarias para la deduccin del
MCD del primer algoritmo, con los valores anteriormente dados.
Valora
38
34
30
26
..
6
2
2
Valorb
4
4
4
4
..
4
4
2
While(valora != valorb)
38 != 4
34 !=4
30 != 4
26 != 4
.
6 != 4
2 != 4
2 != 2
1.9
Se desea crear una Aplicacin para manejar la informacin de una Agenda Telefnica.
Se debe permitir Agregar Persona, Eliminar Persona, mostrar el listado de todas las personas,
buscar persona por nombre y generar un listado de personas que estn cumpliendo aos el
da de hoy.
43
a) Requerimientos funcionales
NOMBRE
RESUMEN
ENTRADAS
RESULTADOS
NOMBRE
RESUMEN
ENTRADAS
RESULTADOS
NOMBRE
RESUMEN
ENTRADAS
RESULTADOS
NOMBRE
RESUMEN
ENTRADAS
RESULTADOS
NOMBRE
RESUMEN
ENTRADAS
RESULTADOS
DESCRIPCIN
44
d. Construccin de la aplicacin
Para las siguientes clases escriba en java las los mtodos e instrucciones necesarias para el
correcto funcionamiento de la aplicacin. Como estrategia se dejan parcialmente planteados
mtodos de implementacin y los cuales deben ser completados.
En la clase AgendaTelefonica puedes observar que se ha hecho uso de ArrayList. Un
ArrayList es una estructura contenedora dinmica que crece o disminuye dinmicamente.
import
import
import
import
java.io.Serializable;
java.util.ArrayList;
java.util.Calendar;
java.util.GregorianCalendar;
45
/**
* @return ArrayList <Persona> devuelve la informacin de las
* personas contenidas en la agenda.
*/
public ArrayList <Persona> getListaPersona()
{
__________________________;
}
/**Constructor de la AgendendaTelefonica
* @param listaPersona */
public AgendaTelefonica( ArrayList <Persona> listaPersona )
{
this.listaPersona = ____________________;
}
public void agregarPersona( String cedula, String nombre,
String direccion, int dia, int mes,
int anio, ArrayList telefono )
{
miPersona.____________________ ( cedula );
miPersona.____________________ ( nombre );
miPersona.setDireccion
( ___________________ );
miPersona.setMiFechaNacimiento ( ________________ );
miPersona._____________________( telfono );
listaPersona.add(_________________);
}
/**
* @return String[] devuelve la informacin de los contactos
*/
public String[] obtenerContactos()
{
int i;
contadorTotal = 0;
String[] contactos;
Contactos = new String[ listaPersona.size() + 1 ];
contadorTotal = listaPersona.size();
for( i=0 ; i < listaPersona.size() ; i++ )
{
String infoT = listaPersona.get(i).getTelefono().
toString();
String info = listaPersona.get( i ).getCedula() + "" +
__________________________________+ infoT;
contactos[ i ] = info;
}
contactos[ i ] = "En total: " + contadorTotal + " contactos";
return contactos;
}
/**
* Permite obtener un contacto que contenga a nombre.
* @return String[] informacin del contacto que coincide con el
* nombre especificado.
*/
46
}
/** Devuelve el contador de contactos */
public int getContadorContactos()
{
________________________
}
/** Devuelve el contadorTotal */
public int getContadorTotal()
{
__________________________
}
/** Contador de personas que estn cumpliendo aos */
public int getContadorCumpleaos()
{
_________________________
}
/** Devuelve la informacin de las personas que estn cumpliendo
* aos */
public String[] obtenerContatosCumpleaos()
{
String[] contactos;
int i;
GregorianCalendar go = new GregorianCalendar();
//sacamos los valores del dia, mes y ao
int dia = go.get ( Calendar.DAY_OF_MONTH );
int mes = go.get ( Calendar.MONTH
) + 1;
contadorCumpleaos = 0;
ArrayList <String> contactosNombre = new ArrayList <String>();
47
}
}
ACTIVIDAD
Una vez escritos los mtodos para la clase AgendaTelefonica, se debe calcular el tiempo de
ejecucin de cada uno de ellos.
Tiempo de Ejecucin
T(n)
Mtodo
String[] obtenerContactos()
String[] buscarContatosNombre(String nombre)
int getContadorContactos()
int getContadorTotal()
String[] obtenerContatosCumpleaos()
void eliminarPersona(String cedula)
Log2(n) (Logartmico). Los algoritmos con este tiempo de ejecucin son considerados
como muy eficientes.
n (Lineal). Es comn en aplicaciones que utilizan ciclos sencillos.
n log(n). Comn encontrarla en algoritmos de ordenamiento eficientes.
2
n (Cuadrtico). Habitual cuando se usan 2 ciclos anidados.
3
n (Cbico). Habitual cuando se usan 3 ciclos anidados.
n
2 (Exponencial). No suelen ser muy tiles en la prctica por el elevado tiempo de
ejecucin.
48
La eleccin de un buen algoritmo est orientada hacia la disminucin del costo que implica la
solucin del problema; considerando este enfoque es posible orientar esta eleccin en dos
criterios (Iparraguirre, 2009):
Debemos tener claro que los aspectos interesantes a reducir son el tiempo y el espacio en
memoria. En cuanto al tiempo nos hemos centrado en la funcin T(n), la cual determina la
cantidad de operaciones que efecta un algoritmo. De acuerdo a la forma como se calcula el
T(n) es importante hacer dos precisiones:
Estas dos precisiones nos permiten dar una aproximacin al concepto de complejidad
computacional de un algoritmo, como un concepto que recoge la naturaleza asinttica de la
funcin T(n) y no su valor exacto. Dicha naturaleza debe dar informacin de cmo crece la
funcin cuando aumenta el tamao de n. Normalmente, el anlisis de la complejidad de los
algoritmos est relacionado con conceptos matemticos que son necesarios precisar.
Si f(n) es alguna funcin definida sobre los enteros no negativos n, se dice entonces que T(n)
es O(f(n)) (McConnell, 2007).
49
T(n) es O(f(n)) si existe un entero n0 y una constante c > 0, tal que para todos los enteros
n >= n0 , tenemos que T(n) <= cf(n). En la Figura anterior se realiza una comparacin de
O(f(n)) con relacin a T(n)
Para determinar el orden de complejidad de un algoritmo a partir de su funcin de tiempo, se
eliminan todos los trminos excepto el de mayor grado y se eliminan todos los coeficientes del
trmino mayor. Lo anterior es debido a que al aumentar el tamao de la entrada, es ms
significativo el incremento en el trmino de mayor orden, que el incremento de los dems
trminos de la funcin. En conclusin, la notacin O(n) nos permite conocer lo verdaderamente
importante en la complejidad de un algoritmo, eliminando los pequeos factores de l.
Dada una funcin f, queremos estudiar aquellas funciones g que a lo sumo crecen tan de prisa
como f. Al conjunto de tales funciones se le llama cota superior de f y lo denominamos O(f).
Conociendo la cota superior de un algoritmo podemos asegurar que, en ningn caso, el tiempo
empleado ser de un orden superior al de la cota (Cormen, Leiserson, Rivest, & Stein, 2001).
A continuacin se muestran convenciones o reglas para escribir la notacin O.
Es una prctica comn cuando escribimos expresiones Big Oh, eliminar todos los
trminos menos el trmino ms significativo. Por ejemplo si tenemos una funcin
5
3
5
f(n)=4n -2n , simplemente escribimos O(n ).
Segn (Ramirez, 2003), las propiedades de la funcin O son la transitiva, los trminos de
orden inferior y la regla de la suma, a continuacin se muestra una descripcin de cada uno de
ellos.
Transitividad
Esta regla est basada en la transitividad de la relacin menor que <, ya que si A <= B y
B <=C se puede concluir que A<= C. Asociando esto a la funcin O se tiene que: Si f(n) es
O(g(n)) y g(n) es O(h(n)), se puede concluir que f(n) es O(h(n)).
50
Regla de la Suma
2
Suponga que un algoritmo est formado por dos secciones, una de ellas con O(n ) y la otra
3
con O(n ). Entonces es posible sumar estos dos rdenes de complejidad para obtener la
complejidad total del algoritmo. La regla es la siguiente:
Suponga que para T1(n) se sabe que es O(f1(n)) y T2(n) es O(f2(n)) y suponga, adems,
que f1 crece ms rpido que f2. Esto se traduce en que f2(n) es O(f1(n)). En consecuencia
se puede concluir que T1(n) + T2(n) es O(f1(n)).
1.10.3 Notacin Omega
Dada una funcin f, queremos estudiar aquellas funciones g que a lo sumo crecen tan
lentamente como f. Al conjunto de tales funciones se le llama cota inferior de f y lo
denominamos f. Conociendo la cota inferior de un algoritmo podemos asegurar que, en ningn
caso, el tiempo empleado ser de un orden inferior al de la cota.
Decir que T(n) es (f(n)) se lee omega grande de f(n), significa que existe una constante
positiva c y tal que para los n, no se cumple que T(n) cf(n), (f(n) es una cota inferior para
T(n)).
1.10.4 Notacin
Dada una funcin g de los enteros no negativos a los nmeros reales positivos. Entonces
(g)=O(g) (g), es decir, el conjunto de funciones que estn tanto en O(g) como en (g).
Comunmente la forma de leer es f a (g), es decir, f es del orden de g.
La funcin f a (g) si
( )
( )
Asociada a las anteriores notaciones es posible el uso de otros conceptos matemticos entre
las cuales encontramos las denominadas funciones de piso y techo. La funcin piso y techo
puede ser utilizada para cualquier nmero flotante o entero y.
La expresin denotada como y se conoce como la funcin piso de y corresponde al entero
ms grande que es menor o igual que x. 2.1 = 2, 4.5 = 4 y 6.9 = 6.
La expresin denotada como y se conoce como la funcin techo de y corresponde al nmero
entero ms pequeo que es mayor o igual que x. Por ejemplo, [2.8]=2 y [6.2]=7.
51
( )
( )
( )
( )
( )
( ( ))
( )
( )
( )
( ( ))
( )
( ( ))
( )
( )
( )
( ( ))
( ( ))
( ( ))
A continuacin se muestra una serie de ejemplos con lo que se pretende mostrar mediante la
regla del lmite si una funcin est en la otra.
Ejemplo 1
es (
La funcin
, por L Hpital
, por L Hpital
=
=
=
Cuando
de
La funcin
es
( )
, por L Hpital
( )
, simplificando
( )
( )
( )
52
, simplificando
no es del orden
( )
( )
( )
, por L Hpital
( )
( )
Cuando
( )
de
, simplificando
no es del orden
Ejemplo 3
La funcin
es (
))
, por L Hpital
( )
( )
( )
, simplificando
, simplificando
, simplificando
( )
( )
( )
( )
( )
, por L Hpital
, simplificando
( )
( )
Cuando
tiende al infinito, la evaluacin de este lmite tiende al infinito
( ), pero
( ) pertenece al orden de
no es del orden de
.
Ejemplo 4
La funcin
es (
por L Hpital
( )
53
por L Hpital
, por lo tanto
por L Hpital
por L Hpital
( )
( )
Cuando
orden de
est en el
Ejemplo 5
La funcin
es
( )
( )
por L Hpital
, simplificando
( )
( )
( )
, por L Hpital
( )
( )
, por L Hpital
( )
( )
( )
( )
, simplificando
, simplificando
Cuando
, la evaluacin de este lmite tiende al infinito
, por lo tanto
no
( )
es del orden de
. Entre ms complejo sea un algoritmo, se puede afirmar que este
es menos eficiente.
54
Mtodo
Anlisis del
Orden de
Complejidad
Orden de
complejidad
La complejidad logartmica tiene un mayor orden que la complejidad constante, este orden de
complejidad se obtiene entre otros en algunos algoritmos recursivos clsicos como la bsqueda
binaria y los rboles binarios de bsqueda con sus operaciones de eliminacin, bsqueda e
55
insercin. Este orden de complejidad est relacionado con algoritmos que son consideramos
muy eficientes.A continuacin se muestran valores asociados a la complejidad log(n).
Complejidad O( logn)
5+
2 log(n)
log(n) + 150000
96
log(n) + 3
El mtodo tiene una complejidad logartmica, a continuacin mostraremos su anlisis mediante
la implementacin de un mtodo.
Ejemplo
Mtodo
Anlisis del
Orden de
Complejidad
Orden de
complejidad
56
Complejidad (n)
10 +
3 log(n) +n
n + 520000
9
n+4
Para el mtodo que aparece en el Cuadro, tenemos que su complejidad est relacionada
directamente con la implementacin de ciclos sencillos. Este mtodo retorna la sumatoria de
los elementos de un arreglo de enteros.
Ejemplo
Mtodo
}
Anlisis del
Orden de
Complejidad
Orden de
complejidad
La complejidad nlog(n) tiene un orden mayor que la complejidad constante, logartmica, lineal,
encontramos este orden de complejidad en algunos algoritmos de ordenamiento como el
heapSort y el mergeSort. A continuacin se muestran algunas funciones con orden nlog(n).
Complejidad (n)
nlog(n) +n+10
nlog(n) + log(n)
A continuacin se muestra la implementacin de un mtodo con el orden de complejidad que
se est analizando.
Ejemplo
Mtodo
57
Orden de
complejidad
O(nlog2(n))
Complejidad (n )
2
n + nlog(n) +n+10
2
n + log(n)
2
25
n +2
La complejidad cuadrtica est relacionada con el uso de dos ciclos anidados. En el Cuadro
mostramos un ejemplo en el cual se suman los elementos de un arreglo bidimensional de
enteros.
Ejemplo
Mtodo
Anlisis del
Orden de
Complejidad
Orden de
Complejidad
O(n )
La complejidad cbica tiene un orden mayor que la complejidad constante, logartmica, lineal,
nlog(n) y la cuadrtica. Este orden de complejidad normalmente se obtiene cuando se tiene
tres ciclos anidados.
58
Complejidad (n )
3
2
n + n +n
3
n + log(n) + 500
3
2
15
n +n +5
A continuacin se muestra la implementacin de un mtodo con el orden de complejidad que
se est analizando.
Ejemplo
Mtodo
Anlisis del
Orden de
Complejidad
Orden de
Complejidad
O(n )
Complejidad Exponencial
Complejidad (2 )
n
3
2 + n +n
n+5
2 + log(n)
n
3
2
45
2 +n +n +7
n+2
100
2 +n
A continuacin se muestra la implementacin de un mtodo con el orden de complejidad que
se est analizando.
Ejemplo
59
Mtodo
public int
{
int
m =
for
{
potencia( int n )
m, i;
1;
( i = 1 ; i <= Math.pow( 2, n ) ; i++ )
m = m * i;
}
return m;
}
Anlisis del
Orden de
Complejidad
Orden de
Complejidad
O(2 )
ACTIVIDAD
Mtodo
Anlisis del
Orden de
Complejidad
Orden de
complejidad
Dado el siguiente mtodo explique qu problema resuelve y determine su orden de
complejidad.
Ejercicio
Mtodo
60
{
suma= suma + matriz[i][j];
}
}
}
return suma;
}
Anlisis del
Orden de
Complejidad
Orden de
complejidad
Dado el siguiente mtodo explique qu problema resuelve y determine su orden de
complejidad.
Ejercicio
Mtodo
Anlisis del
Orden de
Complejidad
Orden de
complejidad
Dado el siguiente mtodo explique qu problema resuelve y determine su tiempo de ejecucin.
Ejemplo
Mtodo
Anlisis del
Tiempo de
ejecucin
Orden de
complejidad
61
Mtodo
Anlisis del
Tiempo de
ejecucin
Orden de
complejidad
NOMBRE
RESUMEN
ENTRADAS
RESULTADOS
El puntaje del docente
62
NOMBRE
R3 Ordenar por nombre a los docentes.
RESUMEN
ENTRADAS
RESULTADOS
NOMBRE
R4 Ordenar por puntaje.
RESUMEN
ENTRADAS
RESULTADOS
NOMBRE
R5 Mostrar la informacin de un docente.
RESUMEN
ENTRADAS
RESULTADOS
DESCRIPCIN
63
DESCRIPCIN
setDoctorado(boolean doctorado)
getCantidadLibros()
setCantidadLibros(int
cantidadLibros)
fijarPuntos()
getPuntos()
c. Relaciones entre las clases
Construya el diagrama de clases para Profesor y concursoProfesor.
64
fijarPuntos()
/** Permite fijar la cantidad de puntos */
public void fijarPuntos()
{
puntos=178;
if(especializacion==true)
{
puntos+=30;
}
if(_________________________)
{
puntos+=120;
}
if(_________________________)
{
puntos+=60;
}
if(doctorado==true)
{
if(______________________)
{
puntos+=170;
}
else
{
puntos+=80;
}
}
puntos += ( _________________*15);
}
ACTIVIDAD
1. Escriba una interpretacin en torno a la forma como se calcula el puntaje de cada docente.
65
66
determinarSiNoHayRepeticiones()
/**
* Permite determinar si no hay profesores repetidos.
* @return booleano que indica si existe o no.
*/
public boolean determinarSiNoHayRepeticiones()
{
for(___________________________)
{
for(______________________________)
{
if(________________________________________________________)
{
return ____________;
}
}
}
return ____________;
}
generarListadoPorPuntaje()
/**
* Permite generar el listado de docentes por puntaje.
* @return un array de String con la informacin de los docentes.
*/
public String[] generarListadoPorPuntaje()
{
}
generarListado()
/**
* Permite generar el listado de los docentes.
* @return un array de String.
*/
public String[] generarListado()
{
String info[]=new String[miProfesor.size()];
67
generarListadoOrdenadoPorNombre()
/**
* Permite generar el listado ordenado por nombre.
* @return un array con la informacin de los docentes.
*/
public String[] generarListadoOrdenadoPorNombre()
{
String info[]=new String[miProfesor.size()];
for(int i=0; i<miProfesor.size(); i++)
{
for(int j=0; j<miProfesor.size()-1; j++)
{
}
}
return info;
}
ACTIVIDAD
Una vez escritos los mtodos para la clase AgendaTelefonica, se debe calcular el tiempo de
ejecucin de cada uno de ellos.
Mtodo
Orden de Complejidad
O(
)
fijarPuntos()
agregarParticipante()
ConcursoProfesor()
determinarSiExisteProfesor(String cedula)
determinarSiNoHayRepeticiones()
generarListadoPorPuntaje()
generarListado()
generarListadoOrdenadoPorNombre()
O(
O(
O(
O(
O(
O(
O(
68
La llamada a un algoritmo recursivo conduce a una nueva versin del mtodo que comienza a
ejecutarse, tambin a una organizacin de la gestin de los parmetros y la memoria. Estos
datos deben estar organizados de forma que al terminar cada llamado que se est ejecutando,
se devuelvan los datos correctos y se actualice la informacin que permita su gestin.
A nivel del diseo de los algoritmos, el uso de la recursividad puede presentar soluciones
cortas y claras, adems de permitir en muchas ocasiones la solucin de problemas complejos.
Mtodo
69
Mtodo
Este mtodo recibe por parmetros un arreglo y una variable n la cual contiene el tamao del
arreglo. La instruccin if(arreglo[n-1]==0) es la encargada de verificar si el elemento en
la posicin n es igual a cero. El algoritmo termina cuando el valor de n es cero.
70
ACTIVIDAD
Dados los siguientes mtodos recursivos, determinen si resuelven el problema que se plantea,
en el caso en el cual exista un error se debe organizar el mtodo en la parte de observaciones
de forma tal que este quede correcto.
Ejercicio
Mtodo
Observaciones
71
Ejercicio
Mtodo
Observaciones
Ejercicio
Mtodo
Observaciones
Mtodo
72
Ejercicio
Mtodo
73
Sustituir repetidamente la regla inductiva dentro de ella misma, hasta que se obtenga
alguna relacin entre T(n) y T(1), es decir, la expresin de induccin y la base.
Suponer una solucin y probar su correctitud sustituyndola en la expresin base y la
inductiva.
Introducidos por el matemtico Leonardo de Pisa, quien se llamaba a si mismo Fibonacci. Cada
nmero de la secuencia se obtiene sumando los dos anteriores.
fib(n) = 0,
n=0
fib(n) = 1,
n=1
fib(n) = fib(n -1) + fib(n - 2), n >= 2
Por definicin, los dos primeros valores son 0 y 1 respectivamente. Los otros nmeros de la
sucesin se calculan sumando los dos nmeros que le preceden. A continuacin se muestran
los primeros 13 nmeros de Fibonacci. A continuacin se muestra la implementacin el
algoritmo recursivo que encuentra el n-simo nmero de la sucesin Fibonacci.
Ejemplo
Mtodo
Anlisis del
Tiempo de
Ejecucin
T(1) = a
T(n) = b + T(n - 2) + T(n - 1)
74
Se asignan valores a n:
T(1) = a
T(2) = b + 2T(1) =
T(3) = b + 2T(2) =
T(4) = b + 2T(3) =
T(5) = b + 2T(4) =
T(6) = b + 2T(5) =
b + 2a
b + 2(b + 2a)
=
b + 2(3b + 4a) =
b + 2(7b + 8a) =
b + 2(15b + 16a) =
( 2 1 )b + 2 a
3
3
( 2 1 )b + 2 a
4
4
( 2 1 )b + 2 a
5
5
( 2 1 )b + 2 a
n-1
1)b + ( 2
n-1
)a
O(2 )
Ejemplo
Mtodo
Anlisis del
Orden de
Complejidad
75
T(2) = b + T(1) = 1b + a
T(4) = b + T(2) = b + b + a = 2b + a
T(8) = b + T(4) = b + 2b + a = 3b + a
T(16) = b + T(8) = b + 3b + a = 4b + a
O(log(n))
Ejemplo 3
Mtodo
Anlisis del
tiempo de
ejecucin
}
Se tiene que para el peor de los casos, el caso base es T(1) = 2.
Para el caso inductivo tenemos que el caso base es de orden
constante O(1) y se tienen 2 llamadas recursivas cada una de
2*(n/2), por lo tanto el caso inductivo T(n) = 2T( n/2 ) + O(1).
Generalizando tenemos, que el caso base
y el caso inductivo, quedan expresados de la siguiente manera:
T(1) = O(1) = a (se reemplaza por una constante):
T(n) = 2T( n/2 ) + b
Reemplazando la base en la induccin, tenemos:
T(2) = 2T(1) + b T(2) = 2a + b
T(4) = 2T(2) + b T(4) = 4a + 3b
76
O(n)
ACTIVIDAD
Mtodo
Anlisis del
Tiempo de
Ejecucin
Orden de
complejidad
Dado el siguiente mtodo recursivo, determine su tiempo de ejecucin y su orden de
complejidad.
Ejercicio
Mtodo
77
Anlisis del
Tiempo de
Ejecucin
Orden de
complejidad
Dado el siguiente mtodo recursivo, determine su tiempo de ejecucin y su orden de
complejidad.
Ejercicio
Mtodo
Anlisis del
Tiempo de
Ejecucin
Orden de
complejidad
Ejemplo 1
Mtodo
78
else
{
return calcularPotencia(x,n/2) *
calcularPotencia(x, n/2) * x;
}
}
}
Se tiene que para el peor de los casos, el caso base es T (1) = 2. Para el caso inductivo
tenemos que el caso base es de orden constante O (1) y se tienen 2 llamadas recursivas cada
una de 2*(n/2), por lo tanto el caso inductivo T(n) = 2T(n/2)+O (1). Generalizando tenemos, que
el caso base y el caso inductivo, quedan expresados de la siguiente manera:
T (1) = O (1) = a (se reemplaza por una constante).
T(n) = 2T(n/2) + b
Reemplazando la base en la induccin, tenemos:
T (2) = 2T (1) + b
T (4) = 2T (2) + b
T (8) = 2T (4) + b
T (16) = 2T (8) + b
T (2) = 2a + b
T (4) = 4a + 3b
T (8) = 8a + 7b
T (16) = 16a + 15b
...
T(n) = 2T(n/2) + b
T(n) = na + (n - 1) b O(n)
Ejemplo 2
A continuacin se muestra otro algoritmo recursivo que retorna la potencia de un nmero. Este
algoritmo debe tener un orden de complejidad inferior al anterior. Esto se deduce dada la
cantidad de llamados recursivos que se utilizan para resolver el problema.
Mtodo
En el anlisis del caso base se tiene que para el peor de los casos el tiempo de ejecucin es:
T (1) = 2. Para el caso inductivo se tienen una llamada recursiva de (n/2) y el caso base es de
orden constante, por lo tanto el caso inductivo T(n) = T(n/2) + O (1).
Generalizando tenemos, que el caso base y el caso inductivo, quedan expresados de la
siguiente manera:
79
T (1) = 8
T(n) = T(n/2) + 8
T (1) = O (1) = a (se reemplaza por una constante)
T(n) = T(n/2) + b
Reemplazando la base en la induccin, tenemos:
T (2) = T (1) + b
T (4) = T (2) + b
T (8) = T (4) + b
T (16) = T (8) + b
T (2) = a + b
T (4) = a + 2b
T (8) = a + 3b
T (16) = a + 4b
...
T(n) = a + b (log n) O (log n)
T(n) = T(n/2) + b
Ejemplo 3
T (2) = 2a
T (3) = 4a
T (4) = 8a
T (5) = 16a
T (6) = 32
...
T(n) = 2T(n)
T(n) = 2
n-1
a
n
Ejemplo 4
Mtodo
80
else
{
return n*(recursivo4(n-1) +
recursivo4(n-1) + recursivo4(n-1));
}
}
En el caso base se tiene que para el peor de los casos el tiempo de ejecucin es: T (1) = 4.
Para el caso inductivo se tienen 3 llamadas recursivas, cada una de (n-1), por lo tanto el caso
inductivo es: T(n) = 3T(n-1)+4.
Generalizando tenemos, que el caso base y el caso inductivo, quedan expresados de la
siguiente manera:
T (1) = 4
T(n) = 3T(n - 1) + 4
T (1) = a (se reemplaza por una constante)
T(n) = 3T(n - 1) + b
Reemplazando la base en la induccin, tenemos:
T (2) = 3T (1) + b
T (3) = 3T (2) + b
T (4) = 3T (3) + b
T (5) = 3T (4) + b
T (n) = 3T (n - 1) + b
T (2) = 3a + b
T (3) = 3(3a + b) + b = 9a + 4b
T (4) = 3[3(3a + b) + b] + b = 27a + 13b
T (5) = 3[3[3(3a + b) + b] + b] + b
= 81a + 27b + 9b + 3b + b
n-1
n-2
n-3
T (n) = 3 a + [3 b + 3 b +: : : + b]
Generalizando, tenemos:
T (n) = 3T (n - 1) + b
T (n) = 3
n+1
a+
)
n
El orden complejidad para un algoritmo con este caso base e inductivo es de orden O (3 ).
ACTIVIDAD
Mtodo
81
Mtodo
Ejemplo 1
Este algoritmo retorna la cantidad de nmeros divisibles tanto por 2 y por 3. Se analizar su
tiempo de ejecucin y su orden de complejidad.
Mtodo
82
, si n 1
, si n > 1
T (n) = T (n - 1) + c1
= (T (n - 2) + c1) + c1 = T (n - 2) + 2c1
= (T (n - 3) + c1) + 2c1 = T (n - 3) + 3c1
= (T (n - 4) + c1) + 3c1 = T (n - 4) + 4c1
= (T (n - 5) + c1) + 4c1 = T (n - 5) + 5c1
= (T (n - q) + nc1
Cuando q = n - 1, entonces T(n) = T (1) + c1(n - 1), por lo tanto el orden de complejidad una vez
resuelta la relacin de recurrencia es O(n).
Ejemplo 2
Mtodo
n-1
Ejemplo 3
Mtodo
83
, si n 1
, si n > 1
T (n) = T (n/2) + 1
2
= T (n/2 ) + 1
3
= T (n/2 ) + 1
4
= T (n/2 ) + 1
k
= T (n/2 ) + n
k
n/2 = 1, se resuelve para k = log2(n), tenemos por lo tanto que el tiempo de ejecucin es T(n) =
T(1)+log2(n-1) y por lo tanto T(n) es O(log2(n)).
Ejemplo 4
Mtodo
T(n) = T(n - 1) + n
= (T(n - 2) + (n - 1)) + n
= ((T(n - 3) + (n - 2)) + (n - 1) + n
...
= T (n - k) + (
)
Si k = n - 1,
T (n) = T (1) +
) = 1+ (
( ) +
84
ACTIVIDAD
Mtodo
Mtodo
85
Mtodo
Anlisis del
mtodo de
ordenamiento
Orden de
complejidad
O(n )
86
ACTIVIDAD
73
485
485
202
3005
831
407
Mtodo
Anlisis del
mtodo de
ordenamiento
Orden de
complejidad
T(n) = 8n + 12n + 9
2
O(n )
87
Mtodo
Anlisis del
mtodo de
ordenamiento
Orden de
complejidad
O(n )
ACTIVIDAD
173
8425
85
221
305
6371
5407
88
Mtodo
Anlisis del
mtodo de
ordenamiento
Orden de
complejidad
O(n )
ACTIVIDAD
89
Mtodo
Orden de
complejidad
90
ACTIVIDAD
237
183
245
122
2305
1131
212
1398
658
23
91
Despus que los primeros k subgrupos han sido ordenados, se escoge un nuevo valor de k
ms pequeo, y el arreglo es de nuevo partido entre el nuevo conjunto de subgrupos. Cada
uno de los subgrupos mayores es ordenado y el proceso se repite de nuevo con un valor ms
pequeo de k. Eventualmente, el valor de k llega a ser 1, de tal manera que el subgrupo
consiste de todo el arreglo ya casi ordenado.
Mtodo
Anlisis del
mtodo de
ordenamiento
Orden de
complejidad
O(n )
ACTIVIDAD
Ordene la siguiente secuencia basndose en el mtodo de ordenamiento shellSort.
2824
122
1832
435
128
92
3505
1599
776
Mtodo
Anlisis del
mtodo de
ordenamiento
Orden de
complejidad
93
datos. Existen diferentes algoritmos que resuelven el problema de la bsqueda, cada uno de
ellos tiene precondiciones que deben ser tenidas en cuenta para su aplicacin. Por ejemplo
para muchos de ellos es necesario que los elementos dentro de la estructura de datos estn
ordenados, en cambio para otros algoritmos este orden no es importante.
Estos tipos de algoritmos son de uso frecuente en contextos en los cuales se lleva a cabo
procesamiento de informacin. Estos pueden usarse para solucionar diferentes problemas,
entre algunos de ellos podemos citar:
Mtodo
Anlisis del
mtodo de
bsqueda
Orden de
complejidad
94
Se busca el nmero 21 y se empieza por el primer elemento del arreglo, se compara el valor
que se encuentra en la posicin con el valor 21.
Continua la bsqueda hacia el cuarto elemento del arreglo, el cual se encuentra en la posicin
3, al momento de realizar la comparacin, se tiene que el elemento buscado se encuentra
dentro del arreglo, lo que nos indicara que la bsqueda fue satisfactoria.
Esta implementacin tiene que aun encontrando el elemento dentro del arreglo, se contina
realizando las comparaciones que permite el tope superior del lmite del ciclo.
95
Mtodo
Anlisis del
mtodo de
bsqueda
Orden de
complejidad
O(n)
Mtodo
96
Anlisis del
mtodo de
bsqueda
Orden de
complejidad
Mtodo
while ( true )
{
centro = (limSup + limInf) / 2;
if( limInf > limSup )
{
return false;
}
else
{
if ( arreglo[ centro ] < dato )
{
limInf = centro + 1;
}
else
{
if (arreglo [centro] > dato)
{
limSup = centro - 1;
97
}
else
{
return true;
}
}
}
Anlisis del
mtodo de
bsqueda
Orden de
complejidad
}
}
Cuando se realiza una comparacin en la cual se busca el nmero,
se encuentra en caso de no ser cierto, que el conjunto de datos se
divide a la mitad. Si el tamao del arreglo es n, se va reduciendo
n
por cada comparacin a n/2, n/4, n/8,., n/2
hasta llegar a
cualquiera de los lmites del arreglo, por lo anterior se puede
deducir que el algoritmo de bsqueda lineal tiene un orden de
complejidad de orden O(log(n)).
O(log(n)).
ACTIVIDAD
Mtodo
Anlisis del
mtodo de
bsqueda
Orden de
complejidad
98
estudiantes ordenado por nota 1, nota 2 o promedio. De igual forma se debe informar la nota
definitiva que ms se repite (moda) y ser posible localizar el primer estudiante que posea la
nota definitiva ingresada por el usuario.
DESCRIPCIN
Estudiante
DESCRIPCIN
99
e. Implementacin
A continuacin se muestra el principal mtodo de la clase Estudiante.
calcularDefinitiva()
/*Calcula la nota definitiva usando formato decimal de dos cifras */
public void calcularDefinitiva()
{
DecimalFormat formatoDecimal;
formatoDecimal = new DecimalFormat ( "0.0" );
String dato = formatoDecimal.format ( (nota1+nota2)/2 );
dato = dato.replace(',','.');
definitiva=Double.parseDouble(dato);
}
100
101
temp = miEstudiante.get(i);
miEstudiante.set(i,miEstudiante.get(j));
miEstudiante.set(j,temp);
}
}
}
for(i=0; i<miEstudiante.size(); i++)
{
array[i]=miEstudiante.get(i).getNombre()+ "
"+miEstudiante.get(i).getApellido()+ " Nota 1:
"+miEstudiante.get(i).getNota1()+" Nota 2:
"+miEstudiante.get(i).getNota2()+" Def:
"+miEstudiante.get(i).getDefinitiva();
}
return array;
}
obtenerDefinitivaModa()
public double obtenerDefinitivaModa()
{
int contadorOcurrencias=0,cantidad=0,i,j,posicion=0;
for (i=0; i<miEstudiante.size(); i++)
{
for(j=0; j<miEstudiante.size(); j++)
{
if(i!=j)
{
if(miEstudiante.get(i).getDefinitiva()==
miEstudiante.get(j).getDefinitiva())
{
contadorOcurrencias++;
}
}
}
if(cantidad<contadorOcurrencias)
{
posicin =i;
cantidad=contadorOcurrencias;
}
contadorOcurrencias=0;
}
if(miEstudiante.size()>0)
{
JOptionPane.showMessageDialog(null,"La que ms se repite "
+ miEstudiante.get(posicion).getDefinitiva());
return miEstudiante.get(posicion).getDefinitiva();
}
return -1;
}
busquedaSecuencial(double nota)
public Estudiante busquedaSecuencial(double nota)
{
DecimalFormat formatoDecimal;
formatoDecimal = new DecimalFormat ( "0.0" );
String dato = formatoDecimal.format ( nota );
102
dato = dato.replace(',','.');
nota = Double.parseDouble(dato);
for (int i=0; i<miEstudiante.size(); i++)
{
if(nota==miEstudiante.get(i).getDefinitiva())
{
return miEstudiante.get(i);
}
}
return null;
}
busquedaBinaria(double nota)
public Estudiante busquedaBinaria(double nota)
{
DecimalFormat formatoDecimal;
int inicio, fin, medio;
inicio=0;
fin=miEstudiante.size()-1;
ordenarPorSeleccion();
formatoDecimal = new DecimalFormat ( "0.0" );
String dato = formatoDecimal.format ( nota );
dato=dato.replace(',','.');
nota=Double.parseDouble(dato);
while(inicio<=fin)
{
medio=(inicio+fin)/2;
if(nota==miEstudiante.get(medio).getDefinitiva())
{
return (miEstudiante.get(medio));
}
else
{
if(nota>miEstudiante.get(medio).getDefinitiva())
{
inicio=medio+1;
}
else
{
fin=medio-1;
}
}
}
return null;
}
ACTIVIDAD
Una vez escritos los mtodos para la clase GrupoEstudiante, determinar su orden de
complejidad.
103
Mtodo
Orden de Complejidad
O(
)
encontrarPersona()
ordenarPorBurbuja()
ordenarPorInsercion()
obtenerDefinitivaModa()
busquedaSecuencial(double nota)
busquedaBinaria(double nota)
O(
O(
O(
O(
O(
Para el caso de estudio Registro notas, agregar el mtodo ordenar por shellSort.
104
Observe que el ciclo se rompe cuando encuentra una persona que posee un salario superior a
430000. Intente construir ahora el algoritmo que permita encontrar la informacin del primer
estudiante que posea una determinada nota definitiva.
public Estudiante busquedaSecuencial(double nota)
{
for (int i=0; i<miEstudiante.size(); i++)
{
}
}
105
106
2.1
ESTRATEGIAS DE PROGRAMACIN
Introduccin
2.2
2.2.1
Bsqueda Binaria
107
else
{
if (arreglo [centro]<dato)
{
return binRecursiva(arreglo,dato,centro+1,limSup );
}
else
{
return true;
}
}
}
}
Cuando se realiza una comparacin en la cual se busca el nmero, se encuentra en caso de no
ser cierto, que el conjunto de datos se divide a la mitad. Si el tamao del arreglo es n, se va
reduciendo por cada comparacin a n/2,n/4,n/8 n/2n, hasta llegar a cualquiera de los lmites
del arreglo, por lo anterior se puede deducir que el algoritmo de bsqueda lineal tiene un orden
de complejidad de orden O(log(n)).
La anterior implementacin se basa en la tcnica divide y vencers ya que para solucionar el
problema necesariamente se tienen que realizar llamadas recursivas al mtodo de
implementacin.
2.2.2
Este mtodo se basa en la tcnica de Divide y Vencers ya que toma el arreglo original de
datos y lo divide en dos partes del mismo tamao, lo sigue dividiendo hasta que slo se tenga
un elemento. Cada una de estas divisiones es ordenada de manera separada y posteriormente
fusionadas para formar el conjunto original ya ordenado. Este algoritmo divide inicialmente
la lista hasta su mnimo valor y luego si ordena el arreglo.
Mtodo
108
] )
];
];
];
}
}
Se tienen las siguientes expresiones de base y de induccin.
T(1) = a
T(n) = 2T(n/2) + O(n)
Reemplazando el caso base por una constante, tenemos que:
T(1) = a
T(n) = 2T(n/2) + bn
Anlisis del
mtodo de
ordenamiento
Orden de
complejidad
ACTIVIDAD
109
Arreglo a Ordenar
5
2.2.3
Rango de valores
-128 a 127
-32768 a 32767
-2147483648 a 2147483647
-9223372036854775808 a
9223372036854775807
Tamao en bits
8
16
32
64
Declaracin
byte var1;
short var2
int
var3;
long
var4;
Mientras que si se utiliza una variable de tipo double, son necesarios 64 bits.
Nombre
float
double
Rango de valores
3,4E-38 a 3,4E38
1.7E-308 a 1.7E308
Tamao en bits
32
64
Declaracin
float num1;
double num2;
Con base en los anteriores valores es posible en determinadas situaciones que el resultado de
una multiplicacin de un nmero entero muy grande sobrepase la capacidad de un tipo de dato,
lo que puede llevar a resultados incorrectos. Cuando esta situacin sucede es posible apoyarse
en estructuras de datos dinmicas que ayudan a que una operacin de multiplicacin se realice
correctamente, esto, utilizando la tcnica de divide y vencers.
A continuacin se muestra de forma evolutiva como por medio de diferentes estrategias de
programacin se puede resolver el problema de la multiplicacin de nmeros grandes.
110
cada una de ellas por el multiplicando. Existe para ello las formas tradicionales de
multiplicaciones conocidas como la americana y la iglesia.
2
Mtodo
for(int y=0;y<=tam1+tam2-1;y++)
{
res[y]=0;
}
for( int i=tam1-1;i>=0;i--)
{
for( int j=tam2-1;j>=0;j--)
{
res[l]+=Num[i]*Num2[j];
if(res[l]>9)
{
res[l-1]+=res[l]/10;
res[l]=res[l]%10;
}
l--;
}
l=pos;
pos--;
l--;
}
Anlisis del
mtodo de
ordenamiento
return res;
}
2
El orden de complejidad de este mtodo de multiplicacin es O(n ),
esto teniendo en cuenta que los ciclos anidados iteran
completamente desde una posicin inicial hasta una posicin final.
111
Numero 1
221
110
55
27
13
6
3
1
Numero 2
1194
2388
4776
9552
19104
38208
76416
152832
Suma
1194
4776
9552
19104
76416
152832
263874
La ventaja de este algoritmo es que solo se realizan operaciones de suma y de divisin por 2. A
continuacin, se muestra una implementacin de este mtodo para multiplicar dos nmeros.
Mtodo
Anlisis del
mtodo de
ordenamiento
Segn (Ramirez, 2003) este algoritmo cuando se aplica la tcnica de divide y vencers,
consiste de dividir tanto multiplicando como multiplicador en dos mitades, ambas con el mismo
nmero de cifras y adems que este nmero de cifras sea potencia de dos (si no los tienen, se
rellenan con ceros a la izquierda). El objetivo final de este algoritmo es efectuar a los ms 4
multiplicaciones, siguiendo los pasos que a continuacin se listan:
1. Multiplique la mitad izquierda del multiplicando (w), por la mitad izquierda del
multiplicador (y), el resultado desplcelo a la izquierda, tantas cifras tenga el
multiplicador.
2. Multiplique la mitad izquierda del multiplicando (w), por la mitad derecha del
multiplicador (z), el resultado desplcelo a la izquierda, la mitad de las cifras que tenga
el multiplicador.
3. Multiplique la mitad derecha del multiplicando (x), por la mitad izquierda del
multiplicador (y), el resultado desplcelo a la izquierda, la mitad de las cifras que tenga
el multiplicador.
4. Multiplique la mitad derecha del multiplicando (x), por la mitad derecha del multiplicador
(z), el resultado no lo desplace.
A continuacin se muestra la implementacin de la Multiplicacin divide y vencers.
112
113
for(int i=0;i<n;i++)
{
t[i]=auxt[i];
}
//u guarda la multiplicacin de los arreglos "x" y "z"
u=new int[n];
iniceros(u,n);
u=dv1(x,z,n/2);
res=new int[2*n];
iniceros(res,2*n);
res=suma(r,2*n,s,n+(n/2));//res guarda la suma de "r" y "s"
res2=new int[(n/2)+n];
iniceros(res2,(n/2)+n);
res2=suma(t,n+(n/2),u,n); //res2 guarda la suma de "t" y "u"
res3=new int[2*n];
iniceros(res3,2*n);
//res3 guarda la suma de "res" y "res2", es el resultado final
res3=suma(res,2*n,res2,(n/2)+n);
return res3;
}
}
2.3
Algoritmos Devoradores
Los algoritmos devoradores son algoritmos que toman decisiones, partiendo de los datos que
tienen disponibles, ignorando las consecuencias que tales decisiones puedan tener. Esta
caracterstica los hace sencillos de disear e implementar. Poseen los siguientes elementos
caractersticos:
Conjunto de candidatos: Son los posibles elementos que pueden ser considerados.
Algunos de ellos sern seleccionados mientras que otros rechazados.
Funcin de solucin: Verifica si con los elementos seleccionados ya se ha completado
la solucin
Funcin de factibilidad: verifica si hay posibilidad de completar la solucin apoyndose
en los elementos seleccionados.
Funcin de seleccin: permite elegir el candidato ms prometedor. Generalmente
existe una relacin directa con la funcin objetivo relacionada con la funcin objetivo.
Por ejemplo si nuestra intencin es minimizar costos elegiremos el candidato ms
econmico.
Funcin objetivo: Entrega la solucin del problema
Los Algoritmos Voraces, tambin conocidos como algoritmos glotones, vidos o algoritmos
greedy, se emplean en problemas de optimizacin en los cuales se pretende maximizar o
minimizar algn valor. La codificacin de un algoritmo voraz se caracteriza por tener un bucle,
denominado bucle voraz.
114
2.3.1
El Problema de la mochila
Una empresa transportadora requiere de una Aplicacin que permita llenar un camin con
objetos sin exceder el peso mximo soportado por ste, logrando una maximizacin de valor.
Cada objeto tiene un peso y un valor asociado. Es importante anotar, que los objetos pueden
fraccionarse. La aplicacin debe permitir:
DESCRIPCIN
Es la clase principal del problema
Elemento
sobre
el
cual
se
realizan
principales operaciones
115
las
116
117
118
ACTIVIDAD
Si se tienen los siguientes objetos y se desea llenar el camin de peso mximo 520 indique
cules y cuntos elementos fueron seleccionados y el valor de la carga obtenido gracias a sta
seleccin.
w
v
20
15
30
50
15
20
40
55
80
92
Se pudo observar que la estrategia de seleccin utilizada en la clase Camion fue minimizar wi.
Ahora se debe, resolver el punto anterior partiendo del hecho de que se desea maximizar v i.
Repita este procedimiento maximizando vi/wi.. Indique cul de las tres funciones de seleccin te
parece ms apropiada.
119
2.3.2
Segn (Hernndez, 2004), los siguientes corresponden a los elementos de los algoritmos
voraces:
Los candidatos: Tenemos que resolver algn problema de forma ptima. Para construir
la solucin de nuestro problema, disponemos de un conjunto o una lista de candidatos:
las monedas disponibles.
A medida que avanza el algoritmo, vamos acumulando dos conjuntos. Uno contiene
candidatos que ya han sido considerados y seleccionados, mientras que el otro
contiene candidatos que ya han sido considerados y rechazados.
Hay una segunda funcin que comprueba si incierto conjunto de candidatos es factible,
esto es, si es posible o no completar el conjunto aadiendo otros candidatos para
obtener al menos una solucin de nuestro problema. Una vez mas no nos preocupa
aqu si esto es optimo o no.
Normalmente, se espera que el problema tenga al menos una solucin que sea posible
obtener empleando candidatos del conjunto que estaba disponible inicialmente.
Hay otra funcin ms, la funcin de seleccin, que indica en cualquier momento cual es
el ms prometedor de los candidatos restantes, que no han sido seleccionados ni
rechazados.
Por ltimo, existe una funcin objetivo que da el valor de la solucin que hemos
hallado: el nmero de monedas que es utilizado para dar la vuelta, la longitud de la ruta
que hemos construido.
En todo algoritmo voraz existen las cuatro funciones mencionadas anteriormente, aunque
frecuentemente no estn explicitas en la codificacin del algoritmo.
120
ACTIVIDAD
Dada una coleccin de elementos enteros positivos de tamao n, los cuales se almacenarn en
un arreglo c. Cul es el conjunto solucin al aplicar el siguiente algoritmo voraz?
public boolean[] algoritmo(int p, int s)
{
int n=s-p+1,k;
boolean[] solucion=new boolean[n]; //agregado solucin vaco
for(int i=-1; i<n-1; )
{
k=i+1;
//candidato
i++;
if(par(c[k+p])) //condicin de prometedor
{
solucion[k]=true; //aadir candidato a la solucin
}
}
return solucion;
}
public boolean par(int i)
{
return (i%2==0);
}
}
2.3.3
El problema de la Devuelta.
Los algoritmos voraces son usados espontneamente por las personas en distintas ocasiones,
por ejemplo, existe un algoritmo voraz que las personas usan para conformar una devuelta. A
continuacin se muestra el conocido caso del tendero.
Supongamos que un tendero tiene que devolver $ 700 y para ello tiene las siguientes 10
monedas.
200
200
200
200
100
100
100
100
50
50
121
Se acepta esa moneda, porque sirve para conformar los $100 restantes.
El algoritmo termina, porque las monedas seleccionadas y aceptadas suman $700 que
era lo que haba que devolver.
ACTIVIDAD
Dado el siguiente mtodo, explicar el funcionamiento del siguiente algoritmo voraz. El mtodo
da el cambio de n unidades utilizando el menor nmero posible de monedas.
public int [ ] devolverCambio (int n)
{
int[] denominacion = {100, 25, 10, 5, 1};
int solucion [ ];
int cantidad = 0;
int i=0, j=0;
while(cantidad!= n)
{
if( (cantidad + denominacion[ i ]) <= n)
{
solucion[ j ] = denominacion[ i ];
cantidad = cantidad + denominacion[ i ];
j++;
i--;
}
i++;
}
return solucion;
}
Considerando el caso del tendero, argumente las siguientes situaciones:
Que subconjunto se extrajo del conjunto dado?
122
Segn las caractersticas de los algoritmos voraces, es posible que el tendero analice varias
para dar la devuelta?
2.4
Un tendero requiere de una Aplicacin que le permita dar a sus clientes las vueltas de tal
forma que ellos reciban la menor cantidad de monedas. Se debe permitir:
a) Requerimientos funcionales
NOMBRE
R1
RESUMEN
ENTRADAS
RESULTADOS
NOMBRE
R2
RESUMEN
ENTRADAS
RESULTADOS
123
NOMBRE
R3
RESUMEN
ENTRADAS
RESULTADOS
DESCRIPCIN
DESCRIPCIN
124
return suma;
}
public double getCambio()
{
return cambio;
}
public void setCambio(double cambio)
{
this.cambio = cambio;
}
public String[] listar() throws Exception
{
int i=0;
if(misMonedas.size()==0)
{
throw new Exception("Debe ingresar denominaciones
antes de poder realizar cambios");
}
else
{
double salida=realizarCambio();
String info[]=new String[misMonedas.size()+2];
for(i=0; i<misMonedas.size(); i++)
{
info[i]="Denominacion:"+misMonedas.get(i).
intValue()+" Cantidad: "+cantidad[i];
}
info[i]="Se cambio en total "+(int)salida+" pesos";
info[i+1]= "No se pudieron cambiar "+(int)(cambiosalida)+" pesos";
return info;
}
}
125
ACTIVIDAD
Identificar en la clase Devuelta los elementos caractersticos de los algoritmos devoradores.
Conjunto de candidatos:
Funcin de solucin:
Funcin de factibilidad:
Funcin de seleccin:
Funcin objetivo:
Pruebe el mtodo que construy con las siguientes denominaciones: 580, 500, 200, 100, 25,
10, 5. Los valores a cambiar son: a) 1050 b) 610 c) 602
2.5
Programacin Dinmica
2.5.1
Serie de Fibonacci
126
a) Cada pareja de conejos frtiles tiene una pareja de conejitos cada mes.
b) Cada pareja de conejos comienza a ser frtil a partir del segundo mes de vida
c) Ninguna pareja de conejos muere ni deja de reproducirse (Bohquez, 2006).
La aplicacin debe mostrar cuantos conejos hay al trmino del mes n, para que el granjero
pueda tomar decisiones en torno a si debe comprar ms conejeras o empezar a vender
parejas.
La siguiente tabla muestra la cantidad conejos que debe haber al cabo de 6 meses
Mes
Cantidad de conejos
0
1
1
1
2
2
3
3
4
5
5
8
Observe que se inicia con una pareja de conejos (mes 0). Esta pareja (la cual llamaremos A) al
inicio del mes dos se reproduce con lo cual quedara la pareja de padres y la pareja de hijos (la
cual llamaremos B). Al tercer mes la pareja B aun no es frtil pues solo tiene un mes de vida,
pero sus padres continuacin siendo frtiles dando lugar a una nueva pareja (pareja C). Es
decir en el mes tres ya se tendran 3 parejas. En el mes cuatro, la pareja A tiene un nuevo hijo
(D), al igual que la pareja B, mientras que la pareja C aun no es frtil pues solo tiene un mes de
vida, con lo cual quedara cinco parejas.
Esta relacin se puede expresar de la siguiente forma:
Fib(n)= Fib (n-1) + fib (n-2)
Donde Fib (0) = 1 y Fib (1) = 1
La clase Fibonacci permite resolver el problema de la reproduccin de conejos.
public class Fibonacci
{
/**
* @param n Es la cantidad de trminos de la serie. n>=0
* @return el valor en la serie fibonacci
*/
public int calcularFibonacci (int n)
{
if ((n == 0) || (n == 1))
{
return 1;
}
else
{
return calcularFibonacci(n-1) + calcularFibonacci(n-2);
}
}
}
n
Fib(1)
Fib(2)
127
....
Fib(n)
ACTIVIDAD
128
ACTIVIDAD
129
2.5.2
Problema de la Mochila
Se va a retomar el problema del llenado del camin pero haciendo uso de programacin
dinmica. Se debe permitir fijar el peso mximo, agregar un nuevo objeto, y arrojar el valor
mximo que puede llevar el camin.
a. Identificar las entidades o clases.
ENTIDAD DEL MUNDO
Camion
DESCRIPCIN
130
131
ACTIVIDAD
Pruebe el funcionamiento del mtodo realizarCambio() llenando la siguiente tabla. Asuma
los siguientes valores y pesos:
Limite
De peso 0
W 1=1
v1=1
W 1=3
v1=5
W 1=6
v1=17
W 1=8
v1=20
W 1=8
v1=25
2.5.3
Problema de la Devuelta
Ahora deseamos retomar el problema del cambio de moneda tratado en el captulo anterior. Se
debe permitir agregar una nueva denominacin, fijar el total a cambiar e indicar con cuantas
monedas puede ser efectuado el cambio.
132
133
ACTIVIDAD
d2= 3
d3= 6
Modifique el mtodo para que adems de indicar la totalidad de monedas requeridas para
efectuar el cambio, especifique cuales y cuntas de cada una.
2.5.4
Algoritmo de Dijkstra
134
Mtodo
Anlisis del
mtodo
Orden de
complejidad
2.5.5
Se desea crear una Aplicacin que permita generar combinaciones ganadoras. La lotera debe
proporcionarnos 6 nmeros para jugar a la lotera Primitiva. Evitando con ello evitar tener que
rellenar las columnas para conseguir un ahorro de tiempo.
Se debe permitir generar combinaciones aleatorias de seis nmeros para la lotera Primitiva,
resetear la lotera y mostrar el total de combinaciones existentes.
135
a) Requerimientos funcionales
NOMBRE
R1
RESUMEN
ENTRADAS
RESULTADOS
R2
NOMBRE
RESUMEN
ENTRADAS
RESULTADOS
NOMBRE
R3
RESUMEN
ENTRADAS
RESULTADOS
b. Identificar las entidades o clases.
ENTIDAD DEL MUNDO
Loteria
DESCRIPCIN
c. Implementacin de mtodos
public class Loteria
{
prvate int arreglo[];
prvate final int TOTAL=6;
public Loteria()
{
arreglo=new int[TOTAL];
}
public int[] generarCombinacionGanadora()
{
int dato;
for(int i=0; i<TOTAL; i++)
{
}
return arreglo;
}
136
}
}
//Esta es la version recursiva
public double calcularCombinatorias(int n, int k)
{
if(k==0||k==n)
{
return 1;
}
else
{
if(k>0&&k<n)
{
return calcularCombinatorias(n-1, k-1)+
calcularCombinatorias(n-1, k);
}
else
{
return 0;
}
}
}
ACTIVIDAD
137
C(5,3) =
0
1
2
3
4
5
6
.
.
n
Con base en dicha tabla construya un algoritmo ms eficiente, que haga uso de programacin
dinmica.
public double calcularCombinatorias(int n, int k)
{
138
139
140
3.1
Introduccin
Arboles Binarios
Los rboles son estructuras de datos dinmicas con una naturaleza diferente en cuanto a las
estructuras de datos anteriormente analizadas, esta naturaleza esta determinada directamente
con su estructura, la cual impone una jerarqua sobre una coleccin de objetos. Un rbol es
una coleccin de elementos llamados nodos, uno de los cuales se distingue como raz. Sobre
ellos se encuentra definida una relacin de paternidad que define la estructura jerrquica a la
que nos referimos anteriormente. Los nodos de un rbol contienen dos o ms enlaces. El nodo
raz es el primer nodo de un rbol. Cada enlace del nodo raz hace referencia a un hijo. el hijo
izquierdo es el primer nodo del subrbol izquierdo, y el hijo derecho es el primer hijo del
subrbol derecho.
Este captulo se basar fundamentalmente es los rboles binarios. Este tipo de rbol se
caracteriza por que tiene un nodo llamado padre y el cual puede tener cero, uno o dos hijos
como mximo. A su vez cada hijo puede verse como otro rbol.
Una definicin recursiva de rbol es que un rbol puede verse como una estructura formada
por un nodo (la raz de dicho rbol) y una lista de rboles. Este nodo (raz) es el padre de las
races de los rboles que componen la lista, a partir de lo cual, se establece la relacin de
paternidad entre ellos. La siguiente figura muestra una representacin de un rbol binario.
Raiz
nodo
o
nodo
nodo
141
nodo
o
Nodo de un rbol
10
60
90
Padre: Es un nodo que puede o no tener hijos. El nodo con informacin 34, tiene 2
hijos, el hijo izquierdo, cuya que contiene el valor 1, y el hijo derecho, cuya informacin
es 44.
34
44
99
Hoja: Una hoja es un nodo que no tiene hijo derecho ni izquierdo. Por ejemplo, en la
siguiente figura, el nodo 2 es una hoja mientras que el nodo con informacin 1 no se
puede considerar como hoja por que tiene ramificacin por la izquierda.
1
20
30
40
20
142
Nivel: Cada nodo tiene un nivel dentro de un rbol binario. El nodo raz tiene un nivel 0
y los dems nodos tienen el nivel de su padre mas 1. Por esto los nodos que son hijos
del nodo raz tienen nivel 1. Segn la figura: El nodo 34 tiene nivel 0, los nodos 2 y 44
tienen nivel 1 y los nodos 2 y 98, tienen nivel 2.
10
60
90
34
99
44
Niveles de un rbol
Altura: La altura de un rbol binario es el nivel de la hoja o de las hojas que estn ms
distantes de la raz. Basndonos en la siguiente figura, la altura del rbol cuya raz es
A, corresponde a la longitud del camino para llegar a la hoja mas distante de la raz.
En este caso ser 3.
2
34
44
99
44
3.2.1
34
Arbol Binario Completo: Un rbol binario completo es aquel en el que todo nodo no
terminal tiene sus dos hijos. Todos los nodos no terminales tienen sus dos hijos. El
mximo numero de nodos que puede tener un rbol de nivel n es: 20 + 21 + 22 + 23...
+ 2n . Si n es 3 entonces : 20 + 21 + 22 + 23 = 15
Los rboles binarios de expresin, tienen aplicaciones en diferentes contextos, entre las ms
aplicadas en el contexto de las ciencias de la computacin se encuentran la representacin de
expresiones proposicionales y expresiones aritmticas con las cuales se pueden realizar
diferentes clculos matemticos.
143
En este caso el operador principal de la expresin es la implicacin y por ello se ubica como el
padre del rbol, este rbol tiene dos subexpresiones que se pueden denominar hijo izquierdo e
hijo derecho, cada uno de los cuales se compone de una expresin.
La expresin: ((p v q) ^ (st)) (s v t), tiene el siguiente rbol de representacin:
En este caso el operador principal de la expresin es l bicondicional y por ello se ubica como
el padre del rbol, este rbol tiene dos subexpresiones que se pueden denominar hijo izquierdo
e hijo derecho, cada uno de los cuales se compone de una expresin. El hijo izquierdo tiene a
su vez una expresin compuesta de hijo izquierdo e hijo derecho, cuyo operador principal es la
conjuncin. El hijo derecho tiene como operador principal es la disyuncin.
ACTIVIDAD
p q r ^ q q p
q (p ^p) r v s p
(p q) ^ (p q) ^ p ^ s q
(p ^ r) (p ^ q) q
144
Operador
Operador
Operador
Operador
Operador
de negacin
de conjuncin ^
de disyuncin v
condicional
bicondicional
Otra aplicacin muy conocida de los rboles es la de los Arboles de expresin, en la cual cada
expresin (compuesta por dos operandos y un operador) se representa a travs de esta
estructura. La raz del rbol contiene un operador, mientras que los subrboles izquierdo y
derecho son los operandos izquierdo y derecho respectivamente. En la hojas solo pueden ir
operandos. Por ejemplo la expresin ((3+5)*(6-2)) puede expresarse tal como se muestra a
continuacin.
145
9
8
2
7
7
9
9
1
9
7
3.2.2
Un rbol binario es un conjunto de elementos que est vaco o dividido en tres subconjuntos. El
primer subconjunto es la raz, los otros dos son los subrboles izquierdo y derecho. Cada nodo
puede tener cero, uno o mximo dos hijos.
Para la implementacin de rboles Binarios, se utilizar una clase Nodo de la cual se pueden
utilizar tantos objetos como sean necesarios. A continuacin, se puede apreciar la
implementacin esta clase en Java:
public class
{
public
public
public
Mtodo
Anlisis del
Orden de
Complejidad
Nodo
Comparable info;
Nodo derecho;
Nodo izquierdo;
Tambin es necesario para la implementacin de rboles Binarios crear una clase Arbol. Esta
clase es la que contiene la implementacin de las principales operaciones que se pueden llevar
a cabo con los rboles, estas operaciones son fundamentalmente de creacin, bsqueda,
eliminacin. A continuacin, se puede apreciar la implementacin esta clase en Java, as como
una explicacin de los mtodos ms utilizados en los rboles, posteriormente, se analizar el
orden de complejidad de cada uno de los mtodos.
146
Mtodo
Anlisis del
Orden de
Complejidad
}
El constructor de rbol, tiene en sus implementacin nicamente
operaciones elementales, por lo tanto el orden de complejidad de
este mtodo es O(1).
Se declara una instancia de la Clase Nodo y una variable entera que servir para contar los
nodos que se tienen en el rbol.
A continuacin se analizar el orden de complejidad de cada uno de los mtodos que
implementan la estructura de datos rbol.
Buscar en un Arbol
Mtodo
Anlisis del
Orden de
Complejidad
147
La figura muestra un caso cuando se desea buscar un elemento cuyo valor en su campo de
datos es 3. La eficiencia de las operaciones sobre los rboles binarios estas asociada en la
mayora de casos a la mitad del conjunto de datos de entrada.
34
44
98
97
99
Cuando se realiza la primera comparacin, se encuentra que el valor que se busca es menor al
valor de la raz y se debe realizar una bsqueda por el subrbol izquierdo.
34
44
98
97
99
La bsqueda continua por la mitad del subrbol, en este caso caso el subrbol derecho en
donde se encuentra el elemento que se esta buscando.
Insertar en un rbol
148
Mtodo
Anlisis del
Orden de
Complejidad
}
Cuando se hace cada comparacin dentro del while, se est ignorando
la mitad el rbol (ya sea la izquierda o la derecha), lo que implica que
el conjunto de datos de entrada se esta reduciendo a la mitad y se
puede afirmar que el orden de complejidad de este mtodo es
O(log n). Esta deduccin es posible hacerla, pues en el capitulo
anterior por el mtodo de sustitucin ya se demostr.
Dado que se no est haciendo balanceo del rbol, es decir, se inserta el nodo donde le
corresponda sin tener en cuenta la proporcin de las ramas del rbol, todo nodo que se inserte
se convertir en una hoja del rbol. Esto implica que como mximo el recorrido que se hace es
la altura misma del rbol y por lo tanto la relacin entre la altura y el nmero de nodos es del
orden de O(logn).
34
44
98
97
149
99
34
44
98
97
99
Finalmente se puede insertar el nodo garantizando siempre la propiedad del rbol binario
ordenado.
34
44
98
97
99
Eliminar en un rbol
El mtodo eliminar permite remover un nodo del rbol, recibe como parmetro un valor que
servir para encontrar el nodo a eliminar. Una vez se halla este nodo se procede a eliminarlo
del rbol y se realizan los correspondientes cambios en el rbol.
El mtodo eliminar(Comparable dato, Nodo nodo), es un mtodo recursivo. Para nuestro
anlisis se debe tener en cuenta el peor de los casos, y este es que el nodo que se est
buscando es un nodo hoja. En el caso de eliminar un nodo de un rbol, se deben tener en
cuenta los siguientes casos:
El aspecto mas sencillo, si el nodo que deseamos remover es un nodo hoja, Se elimina
la referencia que tiene el nodo padre del nodo. Lo anterior colocando una referencia
nula.
150
Los siguientes son aspectos que deben ser tenidos en cuenta si el nodo que se desea eliminar
posee dos subrboles, estas se detallan a continuacin:
Se puede sustituir el nodo a eliminar por el mayor elemento (nodo ms a la derecha) del
subrbol izquierdo del nodo a eliminar.
Es similar al caso anterior. Se puede sustituir el nodo a eliminar por el menor elemento
(nodo ms a la izquierda) del subrbol derecho del nodo a eliminar.
Es similar al caso anterior. Se puede colocar el subrbol derecho a la derecha del mayor
elemento (nodo ms a la derecha) del subrbol izquierdo del nodo a eliminar.
Mtodo
Anlisis del
Orden de
Complejidad
Realiza un recorrido por todo el subrbol izquierdo de acuerdo a un nodo especfico, con el
objetivo de encontrar el menor elemento del subrbol.
151
Mtodo
Anlisis del
Orden de
Complejidad
88
89
90
Mtodo recursivo que elimina el menor elemento del rbol, realiza siempre un recorrido por el
subrbol izquierdo.
Mtodo
152
Anlisis del
Orden de
Complejidad
ACTIVIDAD
Mtodo
Anlisis del
Orden de
Complejidad
3.2.3
Existen tres tipos de recorridos que pueden realizarse a un rbol. El primero de ellos es el
preorden, el cual consiste en recorrer primero la raz, luego el subrbol izquierdo y finalmente el
derecho. El recorrido inorden a su vez procesa primero el subrbol izquierdo, despus el raz y
a continuacin el subrbol derecho. Finalmente el recorrido postorden procesa primero los
subrboles izquierdo y derecho y finalmente procesa la raz.
Para el siguiente rbol los recorridos son:
ballena
ratn
pez
tit
tigre
ballena
cocodrilo
153
ACTIVIDAD
}
Determine el orden de complejidad para los mtodos:
imprimirInorder(Nodo n)
imprimirPostorder(Nodo n)
imprimirPreorder(Nodo n)
O(
O(
O(
154
)
)
)
3.3
Se desea crear una Aplicacin que permita manejar la informacin de una agenda telefnica.
Cada Contacto tiene un nombre, una direccin y un telfono. Se debe permitir:
Agregar un contacto.
Eliminar la informacin de toda la agenda
Listar la informacin en preorden
Listar la informacin en inorden
Listar la informacin en postorden
DESCRIPCIN
Nodo
Persona
Nodo
Nodo izquierda;
Nodo derecha;
Object dato;
155
ArbolBinario
Nodo raiz;
String salida=" ";
boolean esta=false;
156
else
{
esta=false;
throw new RepetidoException("elemento ya est");
}
}
}
public void verificar( String nombre, Nodo n)
{
esta=false;
verificarRepetido( nombre, n);
}
public void verificarRepetido( String nombre, Nodo n)
{
if (n != null)
{
verificarRepetido(nombre,n.obtenerIzquierda());
if(((Persona) n.getData()).getNombre().equals(nombre))
{
esta=true;
}
verificarRepetido(nombre,n.obtenerDerecha());
}
}
public void insertarNodo(Nodo n, Nodo temp)
{
String nInfoNombre, tInfoNombre;
nInfoNombre = ((Persona)n.getDato()).getNombre();
tInfoNombre = ((Persona)temp.getDato()).getNombre();
if (tInfoNombre.compareTo(nInfoNombre) > 0)
{
// Prueba para adicionar a la derecha
if (n.obtenerDerecha() == null)
{
// halla un espacio para colocar el nodo
n.fijarALaDerecha(temp);
}
else
{
//intenta nuevamente hacia abajo
insertarNodo( n.obtenerDerecha(), temp);
}
}
else{
// prueba a la izquierda
if (n.obtenerIzquierda() == null)
{
n.fijarALaIzquierda(temp);
}
else
{
insertarNodo( n.obtenerIzquierda(), temp);
}
}
}
157
3.4
Se desea crear una aplicacin que permita almacenar los nombres de varias personas, acorde
a las reglas seguidas en un rbol binario de bsqueda.
La aplicacin debe permitir agregar un nombre, eliminar un nombre, eliminar el mnimo
elemento, hallar el nombre de mximo elemento y borrar el rbol. De igual forma el rbol
deber poder mostrarse grficamente.
158
a) Requerimientos funcionales
NOMBRE
R1
RESUMEN
ENTRADAS
RESULTADOS
NOMBRE
R2
RESUMEN
ENTRADAS
RESULTADOS
NOMBRE
R3
RESUMEN
ENTRADAS
RESULTADOS
b. Identificar las entidades o clases.
ENTIDAD DEL MUNDO
ArbolBinarioDeBusqueda
Nodo
DESCRIPCIN
ElementoDuplicadoException
ElementoNoEncontradoException
159
160
161
*/
162
*/
163
164
O(
hallarAlturaDelArbol(Nodo t)
O(
obtenerMaximo(int a, int b)
O(
calcularPosicionesDeNodos()
O(
O(
O(
eliminarElMinimo( Nodo t )
O(
O(
hallarElMinimo( Nodo t )
O(
hallarElMaximo( Nodo t )
O(
165
3.5
Grafos
Las estructuras de datos no lineales se caracterizan por no existir una relacin de adyacencia,
entre sus elementos, es decir, un elemento puede estar relacionado con cero, uno o ms
elementos.
Entre las mltiples aplicaciones que tienen estas estructuras podemos mencionar (Besembel,
2006) :
Los grafos son estructuras que se utilizan para modelar diversas situaciones tales
como: sistemas de aeropuertos, flujo de trfico.
Los grafos tambin son utilizados para realizar planificaciones de actividades, tareas
del computador, planificar operaciones en lenguaje de mquinas para minimizar tiempo
de ejecucin.
Los grafos pueden ser utilizados como la estructura bsica para mltiples aplicaciones
en el rea de la Computacin.
Existe una gran cantidad de problemas que se puede formular en trminos de grafos. Para la
solucin de estos es posible que sea necesario examinar todos los nodos o todas las aristas
del grafo. En algunos casos se imponen el orden en que deben ser examinados (recorridos)
estos nodos.
3.5.1
3.5.2
Grafos Dirigidos
166
Los elementos de E se llaman aristas, o aristas dirigidas, o arcos. Para la arista dirigida
(
) en E, v es su cola y w es su cabeza; (
) se representa en los diagramas con la flecha
.
Grficamente se muestra la estructura de un grafo dirigido.
En los casos para los que los grafos representan a nivel computacional la situacin real,
comnmente se tiene en cuenta otro tipo de variable dada por el peso de cada uno de los
arcos, este pero puede representar costo, distancia, tiempo u cualquier otra medida de
conexin entre los vrtices.
3.5.3
Grafos No Dirigidos
167
Ciclo: Es un camino en el que el primer nodo es igual al ltimo, este ciclo ser simple
si el camino tambin lo es, para grafos dirigidos. En grafos no dirigidos es necesario
que los arcos sean distintos.
3.6
3.6.1
Algoritmo de Prim
Mtodo
168
Anlisis del
Orden de
complejidad
3.6.2
Algoritmo de Kruskal
Segn (Colmenares, 2006), sea G=(V,A) un grafo ponderado y conexo; el conjunto de aristas
de candidatas es A. Sea G=(V,T) ; donde T es un conjunto de aristas que comienza vaco.
Luego se selecciona en cada etapa la arista de menor peso que todava no haya sido
inspeccionada (seleccionada o rechazada) independientemente de donde se encuentra dicha
arista. Inicialmente el conjunto de aristas T est vaco y a medida que progresa el algoritmo se
van aadiendo aristas a T. Mientras no se haya encontrado la solucin, el grafo parcial que
contiene los nodos de G y las aristas de T consta de varias componentes conexas. Si una
arista une a dos vrtices de componentes conexas distintas, entonces la aadimos a T, y ahora
forman una sola componente conexa. En caso contrario se rechaza la arista. El algoritmo se
detiene cuando queda una sola componente conexa.
169
ACTIVIDAD
Implemente algoritmo de Kruskal de forma tal que pueda encontrar en camino mnimo en un
grafo.
Mtodo
Anlisis del
Orden de
complejidad
3.6.3
Algoritmo de Dijkstra
170
DESCRIPCIN
Es la clase principal del mundo
b. Diagrama de clase
c. Implementacin
A continuacin se muestra la implementacin de los principales mtodos del algoritmo de
Dijkstra en el contexto de la empresa de comunicaciones.
import java.util.Stack;
public class Dijkstra
{
//Constante para indicar que no hay camino
private final int INF=Integer.MAX_VALUE; //Infinito
private int noExiste=8;
public int numVertices, primerNodo=0, ultimoVertice;
private int[] predecessor, []distancia;
private String[] misNombres;
private boolean arregloAuxiliar[];
private int pesos[][];
/* Constructor de la clase Dijkstra*/
public Dijkstra(int pesos[][],int numVertices,String misNombres[])
{
this.pesos=pesos;
this.numVertices=numVertices;
this.misNombres=misNombres;
distancia=new int[numVertices];
arregloAuxiliar=new boolean[numVertices];
predecesor=new int[numVertices];
ultimoVertice=numVertices-1;
}
171
172
ACTIVIDAD
173
3.7
Arboles n-arios
Un rbol n-rio es un rbol cuyos nodos tienen n o menos hijos. Es de anotar que n puede ser
cualquier valor entero positivo. En n-rio no es importante el orden, a diferencia de lo que
ocurre en el rbol binario de bsqueda.
tit
tigre
titi
cocodrilo
pez
pantera
Este tipo de rboles puede ser recorrido mediante preorden, logrando de esta forma que cada
nodo aparezca una sola vez al realizar el listado de los elementos del rbol. En este tipo de
rbol se requiere que se indique al momento de realizar una insercin, el sitio en el cual deber
ser agregado.
Las definiciones expuestas para rboles binarios pueden perfectamente ajustarse a este tipo
de rboles.
Para iniciar la construccin de nuestra aplicacin empezaremos con una porcin de la clase
ArbolNArio. A continuacin debe analizar el mtodo recorrer y escribir una interpretacin en
torno a la labor que realiza
public class ArbolNArio<T>
{
private Nodo<T> raiz;
private boolean asignado=false;
private Puesto miPuesto=null;
public String recorrer()
{
ArrayList <Nodo<T>> misNodos = new ArrayList<Nodo<T>>();
recorrerEnInorden(raiz, misNodos);
return misNodos.toString();
}
private void recorrerEnInorden(Nodo<T> miNodo,List<Nodo<T>>miLista)
{
miLista.add(miNodo);
for (Nodo<T> info : miNodo.getHijos())
{
recorrerEnInorden(info, miLista);
}
}
174
175
boolean asignado=false;
public Nodo(Tipo informacion)
{
this.informacion =________________________;
}
public boolean isAsignado()
{
return asignado;
}
public void setAsignado(boolean asignado)
{
this.asignado = asignado;
}
public void setHijos(ArrayList<Nodo<Tipo>> hijos)
{
this.hijos = hijos;
}
public Tipo getInformacion()
{
return informacion;
}
public void setInformacion(Tipo informacion)
{
this.informacion = informacion;
}
public ArrayList <Nodo<Tipo>> getHijos()
{
if (hijos != null)
{
return hijos;
}
else
{
return new ArrayList<Nodo<Tipo>>();
}
}
public void agregarHijo(Nodo<Tipo> hijo)
{
if (hijos == null)
{
________= new ArrayList<Nodo<Tipo>>();
}
hijos.add(hijo);
}
public void eliminarHijoPosicion(int posicion) throws
IndexOutOfBoundsException
{
hijos.remove(posicion);
}
176
}
}
3.8
Se desea crear una aplicacin que permita asignar personas de acuerdo al cargo que ocuparn
dentro del organigrama de una empresa.
La aplicacin debe permitir crear un el organigrama por defecto (para ello se deben agregar los
cargos especificados en el grfico anterior), asignar un puesto (un puesto tiene un nombre y
una persona asignada), consultar que persona labora en un puesto determinado y mostrar el
recorrido en preorden del organigrama. Es de anotar que una persona tiene una cedula, un
nombre y una direccin asociada.
177
Se puede ver que el organigrama que debemos trabajar no corresponde a un rbol binario, por
el contrario estamos trabajando un rbol n-ario.
3.9
Arboles AVL
La solucin de este caso de estudio requiere de la comprensin del concepto de rbol AVL. Se
le denomin AVL por los nombres de sus creadores Adelson-Velskii y Landis. Es un rbol que
adems de ser binario de bsqueda cumple con la condicin de que para cada uno sus nodos,
la diferencia entre las alturas de sus subrboles es como mximo 1.
Gracias al equilibrio logrado es posible asegurarnos de que la profundidad del rbol sea
O(log(n)), logrando de esta forma que el tiempo de ejecucin de las operaciones que se
ejecutan sobre dichos rboles sea como mximo (log(n)) en el peor caso, siendo n la cantidad
de elementos. No obstante, es de resaltar que mantener esta propiedad de equilibrio agregue
una dificultad adicional a la hora de insertar y eliminar datos.
Es importante que tengas claro que el factor de equilibrio (FE) es igual a restar a la altura del
subrbol derecho la altura del subrbol izquierdo, en caso de que de un valor diferente de 1, -1
0 podemos concluir que no es AVL
3.9.1
Los rboles AVL son fundamentalmente arboles de bsqueda con una condicin particular de
equilibrio entre sus subrboles. Esa condicin se fundamenta en que la altura de cada uno de
sus subrboles (izquierdo y derecho) no pueden diferenciarse en a los sumo una unidad.
Lo condicin de equilibrio entre los subrboles esta dado por un rango comprendido entre -1, 0
y 1. Si en determinado momento este rango no corresponde, se debe aplicar un procedimiento
de rotacin que se muestra posteriormente en este libro.
178
El siguiente rbol muestra que no es un rbol AVL, el motivo esta sustentado en que la
condicin de equilibrio no se encuentra entre -1, 0 y 1. La diferencia entre la altura de los
subrboles derecho e izquierdo en de 2 unidades.
3.9.2
A continuacin se muestran las operaciones fundamentales que se pueden realizar con los
arboles AVL.
179
Caso 1: Para este caso se usa una rotacin simple a la izquierda (RSI). Recuerda que el
problema surgi porque se insert un nodo en el subrbol izquierdo del hijo izquierdo de Y,
siendo Y el nodo que ha perdido el equilibrio.
Para nuestro ejemplo particular: y= 13, puesto que fue quien perdi el equilibrio, x=12, A=10.
Entonces el rbol quedara con la siguiente estructura luego de la rotacin.
180
ACTIVIDAD
17
53
18
20
Caso 4: para este caso particular se usa una rotacin simple a la derecha (RSD). Recuerda
que el problema surgi porque se insert un nodo en el subrbol derecho del hijo derecho de Y.
A continuacin se presenta un rbol en el cual se aplica este tipo de rotacin.
181
ACTIVIDAD
Plantee un rbol y una posible insercin sobre ste que implique la prdida de equilibrio y para
su solucin requiera una rotacin simple a la derecha. Ilustre el proceso seguido.
Caso 2: Para este caso particular se usa una rotacin doble izquierda derecha. Recuerde que
el problema surgi porque se insert un nodo en el subrbol derecho del hijo izquierdo de Y.
El rbol original
182
rbol original
183
Se observa que en este caso se ha perdido el equilibrio en el elemento 15. Por lo tanto: y=15,
z=20 y x=19. Con lo cual nuestro rbol resultante sera:
ACTIVIDAD
Dada la secuencia de valores enteros 18, 10, 31, 5, 22, 12, 3, 37, 24, 11, 6, 2, representa
grficamente el rbol AVL que surge e indica los momentos en los cuales debiste efectuar la
rotacin.
Identificar cules de los siguientes rboles binarios de bsqueda son AVL. Los que no lo sea
deben marcarse e indicar todos los nodos que violen el equilibrio.
184
Es de anotar que el objetivo de este caso de estudio es introducir el concepto de rbol AVL.
DESCRIPCIN
Nodo
ArbolAvl
Luego de haber entendido los conceptos referentes a rboles AVL, podemos proceder a la
construccin de la aplicacin
b. Implementacin de las clases
public class Persona
{
private int codigoEstudiante;
private double nota1, nota2, notaDefinitiva;
/* Mtodo constructor de la clase Estudiante
*/
public Persona(int codigoEstudiante, double nota1, double nota2 )
{
this.codigoEstudiante=codigoEstudiante;
this.nota1=nota1;
this.nota2=nota2;
}
/**Permite calcular la nota definitiva*/
public double calcularDefinitiva()
{
notaDefinitiva=(nota1+nota2)/2;
return notaDefinitiva;
}
185
186
187
else
{
miNodo = rotarDoubleHijosIzquierda( miNodo );
}
}
}
else if( resultadoComparacion > 0 )
{
miNodo.setDerecho(insertar(nuevo, miNodo.getDerecho ()));
if( darAltura( miNodo.getDerecho() ) - darAltura( miNodo.
getIzquierdo ()) == 2 )
{
if(nuevo.compareTo(miNodo.getDerecho().
getInformacion())>0)
{
miNodo = rotarConHijosALaDerecha( miNodo );
}
else
{
miNodo = rotarDobleHijosDerecha( miNodo );
}
}
}
}
else
{
//Se descartan los duplicados
throw new Exception("El elemento est duplicado: "+nuevo.
getCodigoEstudiante());
}
miNodo.setAltura (Math.max( darAltura( miNodo.getIzquierdo() ),
darAltura( miNodo.getDerecho() ) ) + 1);
return miNodo;
}
/** Halla el elemento ms pequeo del rbol
* @throws Exception cuando el rbol esta vaco */
public Persona hallarMinimo( ) throws Exception
{
if( !estaVacio( ) ){
return hallarMinimo( raiz ).getInformacion();
}
else
{
throw new Exception("El rbol est vaco");
}
}
/** Halla el dato ms pequeo en un subrbol
* @param miNodo El nodo raz en el subrbol */
private Nodo<T> hallarMinimo( Nodo<T> miNodo )
{
if( miNodo == null ){
return miNodo;
}
while( miNodo.getIzquierdo() != null ){
miNodo = miNodo.getIzquierdo();
}
return miNodo;
}
188
189
190
191
else
{
return
}
miNodo.getAltura();
}
/** Rotacin simple caso 1 */
private Nodo<T> rotarConHijosALaIzquierda( Nodo<T> miNodo )
{
Nodo<T> k1 = miNodo.getIzquierdo();
miNodo.setIzquierdo ( k1.getDerecho());
k1.setDerecho ( miNodo);
miNodo.setAltura(Math.max( darAltura( miNodo.getIzquierdo()),
darAltura( miNodo.getDerecho()))+1);
k1.setAltura ( Math.max( darAltura( k1.getIzquierdo() ),
miNodo.getAltura() ) + 1);
return k1;
}
/** Rotacion simple caso 4 */
private Nodo<T> rotarConHijosALaDerecha( Nodo<T> miNodo )
{
Nodo<T> k2 = miNodo.getDerecho();
miNodo.setDerecho (k2.getIzquierdo());
k2.setIzquierdo( miNodo);
miNodo.setAltura(Math.max( darAltura( miNodo.getIzquierdo() ),
darAltura( miNodo.getDerecho() ) ) + 1);
k2.setAltura ( Math.max( darAltura( k2.getDerecho() ),
miNodo.getAltura())+1);
return k2;
}
/** Rotacin doble caso 2 */
private Nodo<T> rotarDoubleHijosIzquierda( Nodo<T> miNodo )
{
miNodo.setIzquierdo(rotarConHijosALaDerecha(
miNodo.getIzquierdo() ));
return rotarConHijosALaIzquierda( miNodo );
}
/** Rotacion doble caso 3 */
private Nodo<T> rotarDobleHijosDerecha( Nodo<T> miNodo )
{
miNodo.setDerecho ( rotarConHijosALaIzquierda(
miNodo.getDerecho() ));
return rotarConHijosALaDerecha( miNodo );
}
}
ACTIVIDAD
O(
192
hallarMaximo( )
O(
estaContenido( T elemento )
O(
listarConDefinitivas( )
O(
O(
obtenerPorcentajeGanaron( )
O(
O(
O(
O(
O(
O(
Analice cual debe ser siempre el orden de complejidad de la altura de un rbol AVL.
Analice cual debe ser siempre el orden de complejidad de la insercin de un rbol AVL.
3.11 Backtracking
El backtracking (conocido tambin como vuelta atrs) permite encontrar soluciones a
problemas. Su funcionamiento podra verse como una bsqueda sistemtica, en la cual
bsicamente lo que se hace es probar todo lo posible hasta encontrar la solucin o determinar
que no existe solucin para dicho problema. Este tipo de algoritmos presentan naturaleza
recursiva. Se caracterizan adems porque en caso de no hallar solucin a una subtarea se
vuelva a la subtarea original y se ensaya por otra ruta diferente a las que ya se han probado.
Ejemplos tpicos de juegos en los cuales se aplica backtracking son el laberinto, la ubicacin de
8 reinas en un tablero de ajedrez de forma que no se ataquen, pacman, juegos de carros, entre
otros.
193
DESCRIPCIN
Es la clase principal del mundo
b. Diagrama de Clases
194
}
/** Permite llenar el array con la ubicacin de las reinas
* @param q: arreglo que contiene las posiciones q!=null */
public void obtenerUbicacionReinas(int[] q)
{
resultado=new int[8];
for (int i = 0; i <q.length; i++)
{
resultado[i]=q[i];
}
}
/** Considera las permutaciones posibles usando backtracking
* @param n. Es el tamao del arreglo n>0 */
public void enumerarPosibilidar(int n)
{
int[] a = new int[n];
resultado=new int[8];
contador=0;
salida="";
enumerarPosibilidad(a, 0,(int)(Math.random()*8));
}
195
196
ACTIVIDAD
Si el nmero generado por la funcin random es 2, indique los valores con los cuales queda el
array a.
197
a. Clases o entidades
ENTIDAD DEL MUNDO
Laberinto
DESCRIPCIN
Es la clase principal del problema
Posicion
b. Diagrama de Clases
c. Implementacin de mtodos
public class Laberinto
{
private char[][] matriz;
private ArrayList<Posicion> rutaSolucion;
private final char noSePuede = '*';
private final char vacio = '_';
private final char ruta = 'c';
private final char muro = 'X';
public Laberinto()
{
matriz=new char[12][12];
rutaSolucion=new ArrayList<Posicion>();
}
/** Devuelve la matriz de caracteres*/
public char[][] getMatriz()
{
return matriz;
}
198
}
}
199
*/
200
4.1
Introduccin
Una estructura de datos es un conjunto de objetos que facilitan el uso dinmico de la memoria,
en consecuencia se logra una mejora en el desempeo de los algoritmos que las usan. La
mayora de los algoritmos tratados aqu pueden ser implementados usando arreglos; sin
embargo, pueden no ser tan eficientes o requerir mayor cantidad de lneas de cdigo para
lograr el mismo efecto.
Las estructuras de datos que analizaremos en este captulo son las listas, las pilas, las colas y
los rboles. Para cada una de estas estructuras se mostraran algunas de las muchas
implementaciones posibles de estas, as como tambin el anlisis del orden de complejidad de
los mtodos que las implementan. Comenzaremos con la estructura de datos dinmica lista
4.2
Las listas son las estructuras de datos lineales ms generales. Permiten generalmente el
acceso para consulta o modificacin en cualquiera de los extremos de la estructura, e incluso
en un punto medio, es frecuente recorrer una lista una lista buscando cierto elemento y, una
vez hallado, eliminarlo, modificar el contenido o insertar un elemento a su izquierda o a su
derecha.
Cuando se habla del concepto de lista, existen casos especiales lo cuales presentan problemas
en el diseo de algoritmos, y estos ocasionan con frecuencia errores en el cdigo. Por lo tanto
se debe procurar escribir cdigo que evite esos casos especiales. Uno de estos casos es
implementar lo que se conoce como nodo cabecera. Un nodo cabecera es un nodo adicional
en la lista que no guarda ningn dato, pero que sirve para satisfacer el requerimiento de que
cada nodo que contenga un elemento tenga un nodo anterior.
Para nuestras implementaciones de cada una de las listas, tendremos siempre en cuenta la
implementacin y el nodo cabecera.
4.2.1
Una lista enlazada tambin recibe el nombre de "lista concatenada", "lista eslabonada" o "lista
lineal". Es una coleccin de elementos llamados nodos, que en su conjunto forman un
ordenamiento lineal. Comnmente cada nodo contiene un dato y una referencia al siguiente
nodo. Una lista enlazada es una estructura de datos dinmica que permite almacenar cualquier
cantidad de nodos (Bedoya, 2008).
La siguiente figura muestra una lista sencillamente enlazada, esta lista esta conformada por
nodos, los cuales tienen un campo que contiene el dato y una referencia al siguiente nodo de la
lista.
201
Mtodo
(Clase
Completa)
Anlisis del
Orden de
Complejidad
A continuacin se muestra una primera implementacin para una lista sencillamente enlazada, se
analizar para cada uno de los mtodos de la clase lista su orden de complejidad, siempre teniendo en
cuenta y considerando el peor de los casos.
Anlisis del
Orden de
Complejidad
Lista()
{
cabecera = new Nodo(null);
cantidad = 0;
}
}
La clase Lista, tiene un mtodo constructor llamado Lista( ), cuyo
orden de complejidad es O(1).
El mtodo eliminar(), permite remover el primer nodo de la lista, verifica inicialmente si la lista
esta vaca, si se cumple el condicional se muestra un mensaje indicado que no hay nodos en la
lista. Si existen nodos en la lista, se actualiza la referencia siguiente del nodo cabecera, a la
referencia que tiene el nodo siguiente del siguiente de cabecera.
Mtodo
Anlisis del
Orden de
Complejidad
202
Mtodo
Anlisis del
Orden de
Complejidad
while (p != null)
{
if (elemento.equals(p.info))
{
if (p == cabecera.siguiente)
{
eliminar();
p=q= cabecera.siguiente;
}
else
{
q.siguiente = p.siguiente;
p = p.siguiente;
}
cantidad--;
}
else
{
q = p;
p = p.siguiente;
}
}
}
Para el anlisis del orden de complejidad de este mtodo se debe
tener en cuenta el peor de los casos, asumiendo que se tiene una
lista con n nodos, si se desea remover todos los nodos con igual
campo de dato, se debe realizar un recorrido lineal de toda la
estructura y nodo por nodo, por lo tanto el orden de complejidad
para este mtodo es O(n).
Mtodo
203
Anlisis del
Orden de
Complejidad
Mtodo
}
Anlisis del
Orden de
Complejidad
El mtodo Nodos(), retorna la cantidad de nodos que tenga la lista hasta ese momento.
Mtodo
Anlisis del
Orden de
Complejidad
4.2.2
Mtodo
204
Anlisis del
Orden de
Complejidad
Para nuestro caso, la siguiente figura permite realizar una abstraccin de un nodo.
null
null
Mtodo
Anlisis del
Orden de
Complejidad
ListaSencilla()
{
cabecera = new Nodo(null);
ultimo = cabecera;
actual = cabecera;
}
El orden de complejidad para el mtodo lista sencilla es O(1), pues
solo tiene operaciones de asignacin las cuales son todas de orden
constante.
El mtodo nuevo, permite inicializa un nodo, este nuevo nodo es el nodo cabecera el cual
contiene un campo de datos null y una referencia siguiente null, adicionalmente se inicializan
las referencias ltimo y actual a cabecera.
Mtodo
Anlisis del
Orden de
Complejidad
Mtodo
Anlisis del
Orden de
Complejidad
205
Para el caso en la cual la lista solo tenga el nodo cabecera, el mtodo estavacia() retorna
verdadero. La figura siguiente muestra una lista con esta precondicin.
null
null
Lista Vacia.
Si la lista posee nodos, el mtodo estavacia(), retorna falso. La figura muestra esta situacin.
3
null
12
null
null
Mtodo
Anlisis del
Orden de
Complejidad
A continuacin se muestra en la figura una situacin cuando la lista est vaca, es decir, solo
est el nodo cabecera.
cabecera
null
null
Lista Vacia.
Una vez que se invoque el mtodo insertarInicio(Object element), la lista queda con un nodo y
ese nodo tiene un nombre el cual llega por parmetro al mismo. La figura muestra como queda
la lista una vez se inserta un nodo siguiente al nodo cabecera. Para este caso el valor que llega
por parmetro al mtodo es dat.
cabecera
null
dat
null
insertarInicio.
206
null
12
null
La figura muestra la insercin de un nodo cuando ya existen nodos en la lista, el objeto que
llega por parmetro es el valor 5, por lo tanto la lista queda con tres nodos.
null
insertarInicio.
12
null
Mtodo
Anlisis del
Orden de
Complejidad
En la figura se muestra una situacin cuando la lista est vaca, es decir solo esta el nodo
cabecera en la lista.
cabecera
null
null
Lista Vacia.
Una vez que se invoque el mtodo insertarUltimo(Object elemento, la lista queda con un nodo
y ese nodo tiene un nombre el cual llega por parmetro al mismo. La siguiente figura muestra
como se inserta un nodo siguiente al nodo cabecera.
207
cabecera
null
10
null
InsertarUltimo
En caso de que ya existan nodos en la lista, como se sabe mediante la referencia al ltimo
nodo, cual es el ltimo nodo, se procede a insertar el nuevo nodo. La siguiente figura muestra
una precondicin de una lista de objetos, la lista tiene dos nodos.
12
null
null
null
null
12
10
null
null
12
insertarUltimo.
null
null
Mtodo
208
Anlisis del
Orden de
Complejidad
La siguiente figura, muestra una lista de con tres nodos, el mtodo eliminar inicio, eliminar el
nodo siguiente al nodo cabecera, el nodo a ser eliminado es el nodo sealado por el valo.
null
null
null
sun
null
Lista con tres nodos.
Una vez se elimine el nodo, la lista sencillamente enlazada quedar con dos nodos, la siguiente
figura, muestra el estado final de la lista.
12
null
null
null
EliminarInicio.
4.2.3
Una lista sencilla circular es una coleccin de elementos llamados nodos, organizados de tal
manera que el ultimo nodo de la lista apunta al nodo cabecera. La figura, muestra una lista
circular. Se puede observar que lista contiene un nodo cabecera, el cual nos sirve para
referenciar el inicio de la lista. Una lista sencilla circular es una lista en la cual el ltimo nodo
apunta al primer nodo de la lista, para nuestro caso al nodo cabecera.
null
33
Anlisis del
Orden de
Complejidad
public Nodo(Object O)
{
dato = O;
siguiente = null;
}
}
El orden de complejidad para la clase Nodo es O(1).
209
Mtodo
Orden de
Complejidad
ListaSencillaCircular()
{
cabecera = new Nodo(null);
ultimo = cabecera;
actual = cabecera;
}
El orden de complejidad para el mtodo lista sencilla es O(1).
El mtodo nuevo, permite crear un nuevo nodo a la lista, este nuevo nodo es el nodo cabecera
el cual contiene un campo de datos null y una referencia siguiente null. Se inicializa una
variable tamao en cero pues el nodo cabecera no se cuenta dentro de la lista.
Mtodo
Orden de
Complejidad
Mtodo
Orden de
Complejidad
La figura, muestra una lista sencilla circular vaca, esta lista posee nicamente el nodo
cabecera. Por lo tanto el mtodo estaVacia() para este caso retornara trae.
null
Lista circular vaca.
Caso contrario al anterior se presenta cuando la lista tiene uno o mas nodos, la figura muestra
una lista sencilla circular con 3 nodos, para este caso el mtodo estaVacia() retorna falso,
puesto que existen nodos en la lista.
null
234
21
210
312
Mtodo
Orden de
Complejidad
}
El orden de complejidad de este mtodo es O(1) ya que todas sus
instrucciones son constantes.
La siguiente figura muestra una precondicin en la cual se tiene una lista vaca, a esta lista se
le adicionara un nuevo nodo, el cual ser el siguiente del nodo cabecera.
null
Lista circular vaca.
Una vez se inserte el nodo en la lista, esta quedar como se muestra en la figura a
continuacin.
null
15
insertarInicio.
Tambin existe el caso en el cual la lista circular tenga nodos, la figura a continuacin muestra
esta situacin.
null
11
15
insertarInicio.
Una vez se invoque el mtodo insertarInicio(), se adiciona un nuevo nodo, el cual quedar
como siguiente del nodo cabecera. Para este caso se inserto un nuevo nodo cuyo contenido en
el campo info es 5.
null
11
insertarInicio.
211
15
El mtodo insertarUltimo() permite insertar un nodo como el ultimo nodo de la lista, inicialmente
verifica si la lista esta vaca, si esta vaca inserta un nodo como siguiente al cabecera, de lo
contrario ya existen nodos en la lista y lo inserta al final.
Mtodo
Anlisis del
Orden de
Complejidad
La siguiente figura muestra lista con un nodo, a esta lista se le adicionar un nuevo nodo el
cual se convertir en el ultimo nodo de las lista despus de su insercin.
null
pl
insertarUltimo.
Una vez se inserte este nodo en la lista, esta quedara como se muestra en la figura.
null
pl
ca
Mtodo
212
else
{
if(borrar==ultimo)
{
cabecera.siguiente=null;
actual=cabecera;
ultimo=actual;
}
else
{
cabecera.siguiente=borrar.siguiente;
actual=cabecera.siguiente;
}
}
}
Anlisis del
Orden de
Complejidad
La siguiente figura, muestra una lista sencilla circular con tres nodos. El ovalo rojo muestra cual
es el nodo que ser removido de la lista.
null
Una vez se invoque el mtodo eliminarInicio(), se elimina el nodo siguiente al nodo cabecera y
la lista queda como se muestra en la figura a continuacin.
null
eliminarInicio.
4.2.4
Una lista doblemente enlazada es una coleccin de elementos llamados nodos, los cuales
tienen generalmente tres campos: un campo izquierda, un campo dato y un campo derecha.
Los campos izquierda y derecha son referencias a los nodos ubicados en cada nodo. Tiene la
ventaja de que estando en cualquier nodo se puede acceder al nodo que est tanto a la
izquierda como a la derecha. El tiempo para todas las operaciones es constante, excepto para
las operaciones que requieran un tiempo proporcional a la longitud de la lista.
La siguiente figura muestra una lista doblemente enlazada.
null
null
10
33
85
null
213
public class
{
NodoDE
Object
NodoDE
Mtodo
Orden de
Complejidad
NodoDE
izquierda;
dato;
derecha;
Mtodo
Orden de
Complejidad
ListaDoble()
{
cabecera = new NodoDE(null);
ultimo = cabecera;
actual = cabecera;
}
El orden de complejidad para el mtodo lista doble es O(1).
El mtodo nuevo, permite crear un nuevo nodo a la lista, este nuevo nodo es el nodo cabecera
el cual contiene un campo de datos null y una referencia siguiente null. Se inicializa una
variable tamao en cero pues el nodo cabecera no se cuenta dentro de la lista.
Mtodo
Orden de
Complejidad
Mtodo
Orden de
Complejidad
214
En la grafica a continuacin se observa que la lista esta vacia, pues solo se tiene el nodo
cabecera con sus respectivas referencias y por lo tanto el mtodo para este caso retorna
verdadero.
null
null
null
En este caso la lista contiene un nodo cuyo contenido es el nmero 5 y por lo tanto el mtodo
retorna falso.
null
null
5
null
Mtodo
Orden de
Complejidad
}
El orden de complejidad de este mtodo es O(1) ya que todas sus
instrucciones son constantes.
Para este caso se observa que inicialmente la lista esta vaca y posteriormente se inserta un
nodo, actualizndose la referencia derecha del nodo cabecera.
null
null
null
96
215
null
El mtodo insertarUltimo() permite insertar un nodo como el ultimo nodo de la lista, inicialmente
verifica si la lista esta vaca, si esta vaca inserta un nodo como siguiente al cabecera, de lo
contrario ya existen nodos en la lista y lo inserta al final.
public void insertarUltimo(Object elemento)
{
NodoDE nuevo = new NodoDE (elemento);
if(estaVacia())
{
ultimo.derecha=nuevo;
nuevo.izquierda=ultimo;
ultimo= nuevo;
actual = nuevo;
}
else
{
ultimo.derecha=nuevo;
nuevo.izquierda=ultimo;
ultimo = nuevo;
actual = nuevo;
}
Mtodo
Anlisis del
Orden de
Complejidad
}
El orden de complejidad de este mtodo es O(1), ya que todas sus
instrucciones son constantes.
Este mtodo inserta un nodo al final de la lista, para este caso se pretende insertar el nodo con
valor 3.
null
2
null
null
null
null
null
if(estaVacia())
{
JOptionPane.showMessageDialog(null,"Lista
Esta Vacia");
}
216
else
{
if(borrar==ultimo)
{
cabecera.derecha=null;
borrar.izquierda=null;
actual=cabecera;
ultimo=actual;
}
else{
NodoDE temporal=borrar.derecha;
cabecera.derecha=temporal;
temporal.izquierda=cabecera;
actual=cabecera.derecha;
}
}
Anlisis del
Orden de
Complejidad
}
El orden de complejidad de este mtodo es O(1) ya que todas sus
instrucciones son constantes.
El mtodo elimina el primer nodo de la lista, para ello es necesaria la actualizacin de las
correspondientes referencias. Para es caso el nodo a eliminar es el que contiene el nmero 73.
null
73
233
69
null
null
Lista Doblemente enlazada
4.2.5
233
69
null
Una lista doblemente enlazada es una coleccin de elementos llamados nodos, los cuales
tienen generalmente tres campos: un campo izquierda, un campo dato y un campo derecha.
Los campos izquierda y derecha son referencias a los nodos ubicados en cada nodo. Tiene la
ventaja de que estando en cualquier nodo se puede acceder al nodo que esta tanto a la
izquierda como a la derecha. El tiempo para todas las operaciones es constante, excepto para
las operaciones que requieran un tiempo proporcional a la longitud de la lista.
La siguiente figura muestra una lista doblemente enlazada.
null
34
21
217
78
NodoDE
izquierda;
dato;
derecha;
Mtodo
}
Orden de
Complejidad
Mtodo
Orden de
Complejidad
ListaDoble()
{
cabecera = new NodoDE(null);
ultimo = cabecera;
actual = cabecera;
}
El orden de complejidad para el mtodo lista doble es O(1).
El mtodo nuevo, permite crear un nuevo nodo a la lista, este nuevo nodo es el nodo cabecera
el cual contiene un campo de datos null y una referencia siguiente null. Se inicializa una
variable tamao en cero pues el nodo cabecera no se cuenta dentro de la lista.
Mtodo
Orden de
Complejidad
Mtodo
218
Orden de
Complejidad
Para este primer caso el mtodo retornar falso, teniendo en cuenta que nicamente la lista
tiene el nodo cabecera.
null
Lista vacia doblemente enlazada circular
Para este segundo caso el mtodo retornar verdadero, teniendo en cuenta que la lista se
compone de varios nodos.
null
500
21
64
El mtodo insertarInicio permite insertar un nodo como siguiente al nodo cabecera, inicialmente
verifica si la lista esta vaca, si esta vaca inserta un nodo como siguiente al cabecera, de lo
contrario ya existen nodos en la lista y lo inserta.
public void insertarInicio(Object elemento)
{
NodoDE nuevo = new NodoDE(elemento);
NodoDE temporal = cabecera.derecha;
Mtodo
Anlisis del
Orden de
Complejidad
if (estaVacia())
{
cabecera.derecha=nuevo;
nuevo.izquierda=cabecera;
ultimo = nuevo;
actual = nuevo;
}
else
{
nuevo.derecha=cabecera.derecha;
nuevo.izquierda=cabecera;
temporal.izquierda=nuevo;
cabecera.derecha=nuevo;
actual = nuevo;
}
}
El orden de complejidad de este mtodo es O(1) ya que todas sus
instrucciones son constantes.
Para este caso si se parte de una lista circular doblemente enlazada que se encuentra vaca, el
proceso de insertar un nodo se muestra a continuacin.
null
Lista doblemente enlazada circular
219
El mtodo insertarUltimo permite insertar un nodo como el ultimo nodo de la lista, inicialmente
verifica si la lista esta vaca, si esta vaca inserta un nodo como siguiente al cabecera, de lo
contrario ya existen nodos en la lista y lo inserta al final.
public void insertarUltimo(Object elemento)
{
NodoDE nuevo = new NodoDE (elemento);
Mtodo
Orden de
Complejidad
if(estaVacia())
{
ultimo.derecha=nuevo;
nuevo.izquierda=ultimo;
ultimo= nuevo;
actual = nuevo;
}
else
{
ultimo.derecha=nuevo;
nuevo.izquierda=ultimo;
ultimo = nuevo;
actual = nuevo;
}
}
El orden de complejidad de este mtodo es O(1) ya que todas sus
instrucciones son constantes.
Mtodo
if(estaVacia())
{
JOptionPane.showMessageDialog("Lista Vacia");
}
else
{
if(borrar==ultimo)
{
cabecera.derecha=null;
borrar.izquierda=null;
actual=cabecera;
ultimo=actual;
}
220
else
{
NodoDE temporal=borrar.derecha;
cabecera.derecha=temporal;
temporal.izquierda=cabecera;
actual=cabecera.derecha;
}
}
Anlisis del
Orden de
Complejidad
}
El orden de complejidad de este mtodo es O(1) ya que todas sus
instrucciones son constantes.
Para este caso se quiere eliminar el nodo que se encuentra al inicio de la lista. En este caso se
desea eliminar el nodo con valor 80.
null
80
21
98
4.3
221
a) Requerimientos funcionales
NOMBRE
RESUMEN
ENTRADAS
RESULTADOS
NOMBRE
RESUMEN
ENTRADAS
RESULTADOS
NOMBRE
RESUMEN
ENTRADAS
RESULTADOS
NOMBRE
RESUMEN
ENTRADAS
RESULTADOS
222
DESCRIPCIN
Ciudad
GrupoCiudades
d. Implementacin
Se deben implementar las clases del dominio del problema asociadas con la estructura de lista
que considere ms apropiada.
public class GrupoCiudades
{
223
4.4
2
7
0
6
9
8
5
4.4.1
Se debe especificar algn tamao mximo N para la pila; EJ= 1000 elementos. Entonces la pila
consiste en un arreglo S de N elementos mas una variable entera t, que expresa ndice del
elemento superior del arreglo S.
N-1
Al considerar que los arreglos comienzan en java con el ndice 0, se inicializa t en 1, y se usa
este valor de t para indicar cuando est vaca la pila. De igual forma, se puede usar esta
variable para determinar la cantidad de elementos (t+1) en una pila. Se introduce la excepcin
llamada StackFullException para indicar la condicin de error que se produce si se trata de
insertar un elemento nuevo y la pila S se encuentra llena (Goodrich & Tamassia, 2002).
A continuacin se muestra la implementacin de una pila mediante un arreglo, mediante los
siguientes mtodos fundamentales:
Mtodo
224
}
El orden de complejidad de los mtodos constructores tiene
nicamente instrucciones constantes y por lo tanto el orden de
complejidad es O(1).
Retorna si la pila esta vaca, como se esta trabajando con un ndice que controla el tope de la
pila, cuando el valor del ndice es menor que cero, retorna que la pila no tiene elementos,
como nicamente se esta retornando en el mtodo un valor.
Mtodo
Orden de
Complejidad
Mtodo
Orden de
Complejidad
El mtodo top retorna un objeto de la pila, el objeto que retorna en caso de encontrarse es el
elemento que esta en el tope de la pila. Si la pila se encuentra vaca, se muestra un mensaje
de advertencia indicando esta situacin.
Mtodo
225
else
{
return s[top];
}
}
Anlisis del
Orden de
Complejidad
El mtodo pop elimina el ultimo elemento de la pila y lo retorna, inicialmente verifica si la pila
contiene o no elementos, en caso de estar la pila vaca, muestra un mensaje de advertencia
indicando la situacin, en caso contrario, actualiza la posicin del ndice mediante un
decremento y se retorna el elemento de la posicin en la cual se encontraba el ndice
inicialmente.
public Object pop () throws StackEmptyException
{
Object elem;
Mtodo
Anlisis del
Orden de
Complejidad
if (isEmpty())
{
throw new StackEmptyException
Vacia");
}
else
{
elem=s[top];
s[top]=null;
top--;
return elem;
}
("Pila
}
Por la regla de la suma podemos deducir que el orden de
complejidad de este mtodo es constante O(1).
Las siguientes dos clases son las que contienen las excepciones que se mencionan en la
implementacin de los mtodos de pila.
public class StackEmptyException extends Exception
{
StackEmptyException (String cadena)
{
System.out.println (cadena);
}
}
Mtodo
Anlisis del
Orden de
Complejidad
226
4.4.2
La implementacin de una pila tambin es posible utilizando nodos, lo importante en este caso
es que se respete el principio FIFO. El constructor de la pila permite crear una pila vaca.
public class Pila
{
Nodo tope;
Mtodo
Anlisis del
Orden de
Complejidad
Pila()
{
tope = new Nodo(null);
}
}
El orden de complejidad para este mtodo es O(1), complejidad
constante.
El mtodo pop() elimina el ultimo elemento de la pila y lo retorna, inicialmente verifica si la pila
contiene o no elementos, en caso de estar la pila vaca, muestra un mensaje de advertencia
indicando la situacin, en caso contrario, actualiza la posicin del ndice mediante un
decremento y se retorna el elemento de la posicin en la cual se encontraba el ndice
inicialmente.
Mtodo
Orden de
Complejidad
Object pop()
{
Object dato;
if (tope == null)
{
System.out.println("Pila esta Vacia");
dato = null;
}
else
{
dato = tope.siguiente.info;
tope.siguiente =
tope.siguiente.siguiente;
}
return dato;
}
Por la regla de la suma podemos deducir que el orden de
complejidad de este mtodo es constante O(1).
Mtodo
227
Anlisis del
Orden de
Complejidad
El mtodo mostrar permite realizar un recorrido de todos los elementos de la pila, cuando
realiza este recorrido, va mostrando el contenido de cada uno de los elementos de la pila, se
realiza el recorrido mediante la instruccin p = p.siguiente.
Mtodo
Anlisis del
Orden de
Complejidad
void mostrar()
{
Nodo p = new Nodo();
p = tope.siguiente;
while (p != null)
{
System.out.print(" " + p.info + "\n");
p = p.siguiente;
}
}
El anlisis de este mtodo para el peor de los casos asumiendo
que se tienen n nodos en la pila es de orden O(n) lineal, pues
recorre la pila desde el primer nodo hasta el ltimo.
Este mtodo retorna si la pila esta vaca, como se esta trabajando con un ndice que controla el
tope de la pila, cuando el valor del ndice es menor que cero, retorna que la pila no tiene
elementos, como nicamente se esta retornando en el mtodo un valor.
Mtodo
Anlisis del
Orden de
Complejidad
boolean pilaVacia()
{
return tope.siguiente == null
}
El orden de complejidad para el mtodo isEmpty() es constante,
O(1)
El mtodo top() retorna un objeto de la pila, el objeto que retorna en caso de encontrarse es el
elemento que esta en el tope de la pila. Si la pila se encuentra vaca, se muestra un mensaje
de advertencia indicando esta situacin.
Mtodo
Anlisis del
Orden de
Complejidad
4.5
Nodo cima()
{
return tope.siguiente;
}
Por la regla de la suma podemos deducir que el orden de
complejidad de este mtodo es O(1).
228
4.5.1
Inicialmente se muestra una implementacin de una cola utilizando como estructura base una
arreglo unidimensional de elementos. Es necesario al momento de trabajar con colas definir
cual ser el frente y cual ser el final de la cola, lo anterior es fundamental para establecer por
donde insertarn elementos a la cola y por donde se eliminarn los elementos de la cola.
Para definir el frente y el final de la cola es necesario definir dos variables, frente y final. Donde
frente es un ndice dentro del arreglo que guarda el primer elemento de la cola y final es un
ndice dentro del arreglo que indica la siguiente celda disponible de arreglo para insertar un
elemento.
Al principio se asignar frente = final = 0, para indicar que la cola se encuentra vaca. Cuando
se saca un elemento del frente de la cola, solo incrementar frente para sealar la siguiente
celda. De igual manera, cuando se agrega un elemento, tan solo se incrementa final para
sealar la siguiente celda disponible en la cola. Sin embargo de acuerdo a lo anterior existe un
problema con este mtodo.
Por ejemplo, considrese lo que sucede cuando se coloca y se quita de la cola N veces
distintas a un solo elemento. Se obtendra frente = final = N. Si a continuacin se tratara de
insertar el elemento solo una vez mas, se obtendra un error de arreglo fuera de lmites, aun
cuando haya suficiente lugar en la cola para ese caso. Para evitar ese problema, se har que
los ndices frente y final se repitan. Esto es, se considerar ahora que la cola es un arreglo
circular.
Uso del arreglo Q en forma circular, la configuracin normal con f r.
N-1
Uso del arreglo Q en forma circular, la configuracin envuelta con r < f. Se resaltan las celdas
que guardan los elementos de la cola (Goodrich & Tamassia, 2002).
N-1
Cada vez que se incrementa frente o final, es posible calcular este incremento en la forma:
(frente+1) %n (final+1) % n, respectivamente, siendo n el tamao total del arreglo
unidimensional. Lo anterior garantiza el manejo circular de la cola.
Se examinar ahora el caso que se presenta si se forman N objetos en la cola Q, sin sacar
ninguno de ellos. Se tendra que f=r, que es la misma condicin que se presenta cuando la cola
esta vaca. Por consiguiente, no se podra decir cual es la diferencia entre una cola llena y una
vaca en este caso. La solucin es insistir en que Q nunca puede contener mas de N-1 objetos
(Goodrich & Tamassia, 2002).
229
Mtodo
Orden de
Complejidad
public
queue ()
{
this (CAPACIDAD);
}
public queue (int cap)
{
n = cap;
Q = new Object [n];
}
}
El orden de complejidad para este mtodo es O(1), complejidad
constante.
El siguiente mtodo llamado isEmpty() retorna si la cola esta vaca, como se esta trabajando
con un ndice que controla el tope de la pila y el final de la pila, cuando estos valores son
iguales, se determina que la cola esta llena.
Mtodo
Orden de
Complejidad
Mtodo
230
Orden de
Complejidad
El mtodo front() retorna un objeto de la cola, el objeto que retorna en caso de encontrarse es
el elemento que esta en el frente de la cola. Si la cola se encuentra vaca, se muestra un
mensaje de advertencia indicando esta situacin.
Mtodo
Anlisis del
Orden de
Complejidad
El mtodo size() retorna un valor entero, este valor entero determina la cantidad de elementos
que tiene la cola.
Mtodo
Anlisis del
Orden de
Complejidad
El mtodo dequeue() elimina el ultimo elemento del frente de la cola y lo retorna, inicialmente
verifica si la cola contiene o no elementos, en caso de estar la cola vaca, muestra un mensaje
de advertencia indicando la situacin, en caso contrario, actualiza la posicin del ndice
mediante f = (f+1) % n y se retorna el elemento de la posicin en la cual se encontraba el ndice
inicialmente.
Mtodo
231
Orden de
Complejidad
4.5.2
Orden de
Complejidad
Cola()
{
frente = new Nodo(null);
ultimo = new Nodo(null);
cantidad = 0;
}
El orden de complejidad para este mtodo es O(1).
El mtodo dequeue, elimina el prximo nodo candidato a salir de la cola, si la cola est vaca,
muestra un mensaje de advertencia indicando esta situacin, este mtodo retorna el dato del
nodo removido.
Mtodo
Orden de
Complejidad
Object dequeue()
{
Object dato = null;
if (frente.siguiente != null)
{
dato = frente.siguiente.info;
frente.siguiente =
frente.siguiente.siguiente;
cantidad--;
}
else
{
System.out.println("Cola vacia !!!");
}
return dato;
}
El orden de complejidad para este mtodo es O(1).
El mtodo queue agrega un nuevo nodo a la cola, recibe por parmetro el valor que ser
asignado al nodo.
232
Mtodo
Orden de
Complejidad
void queue(Object e)
{
Nodo n = new Nodo(e);
Nodo p = new Nodo();
if (frente.siguiente == null)
{
frente.siguiente = n;
ultimo.siguiente = n;}
else
{
ultimo.siguiente.siguiente = n;
ultimo.siguiente = n;
}
catidad++;
}
El orden de complejidad para este mtodo es O(1).
Mtodo
Orden de
Complejidad
Nodo top()
{
return frente.siguiente;
}
El orden de complejidad para este mtodo es O(1).
Mtodo
Orden de
Complejidad
Nodo ultimo()
{
return ultimo.siguiente;
}
El orden de complejidad para este mtodo es O(1).
Mtodo
Orden de
Complejidad
4.6
int longitud()
{
return cantidad;
}
El orden de complejidad para este mtodo es O(1).
Estructura ArrayList
233
Los ArrayList, son una de las muchas estructuras que crecen o disminuyen dinmicamente.
En los ArrayList nicamente se pueden almacenar objetos, no es posible almacenar en el
tipos primitivos de datos.
Algunos mtodos de los mtodos predefinidos de la clase ArrayList se muestran a
continuacin:
Teniendo en cuenta que los anteriores son mtodos predefinidos por el lenguaje de
programacin, la implementacin y anlisis de los mismos se realizar en un contexto de
aplicacin que se muestra en la siguiente seccin.
4.7
Se quiere construir una Aplicacin que maneje la informacin de los programas acadmicos de
una Universidad. Cada programa acadmico tiene nombre, cdigo, telfono y un nmero de
estudiantes. El cdigo de cada programa debe ser nico es por defecto la palabra clave para
su bsqueda.
En el programa de la Universidad se debe poder: (1) agregar un nuevo programa acadmico,
(2) mostrar la lista completa de los programas acadmicos, (3) buscar programa acadmico
por el cdigo, (4) mostrar el nombre de los programas que tengan ms de 350 estudiantes.
234
DESCRIPCIN
Es la clase principal del problema.
Contiene la informacin de cada programa acadmico.
b. Diagrama de clases.
A continuacin se muestra el diagrama de clases para el caso de estudio.
235
236
Orden de
Complejidad
public Universidad()
{
misProgramas = new ArrayList<Programa>();
}
El orden de complejidad para este mtodo es O(1).
Mtodo
Orden de
Complejidad
Este mtodo una arreglo de cadenas con la informacin de todos los programas acadmicos.
Para esta operacin utiliza el mtodo predefinido get(i), en el cual i es el ndice por medio del
cual se accede a cada programa.
Mtodo
Orden de
Complejidad
}
El orden de complejidad del mtodo se analiza asumiendo que el
ArrayList contiene n elementos. Por lo tanto se necesita de un ciclo
que permita recorrer la totalidad del mismo, y su orden de
complejidad es O(n).
237
Mtodo
Orden de
Complejidad
Mtodo
Orden de
Complejidad
ACTIVIDAD
El mtodo remove(objeto) permite eliminar un objeto de la estructura contenedora. Escriba
un mtodo que permita eliminar todos los programas acadmicos cuya cantidad de estudiantes
sea inferior a 98.
238
239
240
5.1
Introduccin
En este captulo se mostrarn las tcnicas bsicas que pueden ser usadas para la optimizacin
de cdigo. En captulos anteriores se han mostrado algunas tcnicas que son de utilizada para
el anlisis y solucin de problemas de programacin. Adicional a estas tcnicas se incorpora la
optimizacin de cdigo es cual es un tema que correctamente aplicado puede ayudar a
maximizar la eficiencia en trminos de tiempo de ejecucin de un programa.
Con el propsito de analizar los aspectos relacionados con las pruebas al cdigo. Java dispone
del Framework JUnit para la realizacin y automatizacin de pruebas y el cual se explicar
mediante un ejemplo de aplicacin.
Finalmente en este captulo se mostrarn los conceptos bsicos de los problemas asociados a
los lmites de la lgica, los cuales son conocidos como los problemas clase P y clase NP.
5.2
Tcnicas de Optimizacin
El objetivo de las tcnicas de optimizacin es mejorar el cdigo fuente para que nos d un
rendimiento mayor. Muchas de estas tcnicas vienen a compensar ciertas ineficiencias que
aparecen en el cdigo fuente. Las optimizaciones en realidad proporcionan mejoras, pero no
aseguran el xito de la aplicacin. Algunas optimizaciones que se pueden aplicar a los ciclos
son:
Desenvolvimiento de ciclos (loop unrolling).
Reduccin de esfuerzo.
Tipos de variables
Fusin de ciclos (loop jamming).
5.2.1
Desenvolvimiento de ciclos
Esta tcnica de optimizacin consiste en desenvolver el cuerpo del ciclo dos o ms veces
incrementando los saltos de ciclo, con el fin de mejorar el reso de registros, minimizar
recurrencias y de exponer ms paralelismo a nivel instruccin. El nmero de desenvolvimiento
es determinado automticamente por el compilador o bien por el programador mediante el
empleo de directivas (Garca, Delgado, & Castaeda, 2000).
Cuando se encuentra que la cantidad de iteraciones del ciclo es pequea y constante, esta
tcnica se puede utilizar. Por ejemplo, si se tiene el siguiente cdigo.
Para este caso inicialmente se muestra un mtodo el cual contiene un cdigo que se va a
optimizar. En estos casos no se esta resolviendo un problema especifico se quiere hacer
nfasis en la aplicacin de la tcnica.
Mtodo
241
if (k % 13 == 0)
{
k = 0;
for (int j = 0 ; j < 6; j++)
{
solucion[j]= prueba[j]+5;
}
}
}
}
Mtodo
Se observa que el ciclo mas externo del mtodo ejemplo(), se elimina por el equivalente en el
cdigo, de forma tal que el acceso a cada ndice del arreglo se realiza directamente. El
algoritmo primer mtodo es menos eficiente que el que aparece optimizado. De forma
experimental, se puede afirmar que la correcta aplicacin de la tcnica mejora el tiempo de
ejecucin.
A continuacin se muestra otro ejemplo para mostrar la aplicacin de la tcnica de
desenvolvimiento. Por ejemplo si se tiene el siguiente fragmento de cdigo:
Mtodo
242
Mtodo
5.2.2
Reduccin de Esfuerzo
La tcnica de reduccin de esfuerzo (Strength Reduction), sugiere que una expresin puede
remplazarse por otra, siempre y cuando cumpla la misma funcin, siempre garantizando una
mejora en la eficiencia de su ejecucin. A continuacin se muestra un caso en el cual se aplica
esta tcnica.
Mtodo
243
Mtodo
5.2.3
Tipos de Variables
Se ejecuta la misma operacin pero con datos de tipo entero y reales. Adicionalmente el
concepto de tipo de dato se utiliza, entre otras cosas, para realizar las operaciones entre los
datos. As, para un mismo procesador, efectuar el producto de dos nmeros es mucho ms
lento si estos nmeros son de tipo real que si son de tipo entero; sin embargo ambos casos son
similares desde el punto de vista algortmico. A continuacin se muestra la implementacin
usando tipos de datos double.
Mtodo
Mtodo
244
ACTIVIDAD
Mtodo
5.2.4
Fusin de ciclos
Cuando en una implementacin se tienen ciclos que iteran la misma cantidad de veces, tal
como se muestra en el siguiente cuadro Dada esta situacin, se puede optimizar el cdigo,
aplicando la tcnica de la fusin de ciclos. Para este ejemplo, se puede observar que el tamao
de los tres arreglos definidos es igual. La operacin de lectura de los datos en cada uno de
ellos se realiza por medio de un ciclo que itera desde cero hasta 2500000.
Cuando se puede verificar que los ciclos iteran la misma cantidad de veces y estos se
encuentran concatenados, es posible unir todas las instrucciones en un solo ciclo. Esta
operacin de fusin mejora la ejecucin de las instrucciones en cuanto a su tiempo.
Mtodo
245
Mtodo
Otro ejemplo en el cual se muestra la fusin de ciclos. Para este caso se escribe un fragmento
de cdigo que permite realizar la suma de los elementos que se encuentran en la diagonal
secundaria de una matriz.
Cdigo
Cdigo
5.2.5
int s;
for(int i=0; i<tam;i++)
{
s=i;
resul=arreglo[i][s];
}
Expresiones redundantes
246
Mtodo
}
El mtodo optimizado aplicando la tcnica de expresiones redundantes se muestra a
continuacin.
Mtodo
5.2.6
Folding
Es una de las tcnicas de optimizacin ms y de uso mas sencillo, la cual hace referencia a
que en muchas ocasiones las expresiones pueden se simplificadas. Por ejemplo si se tiene la
expresin:
int i = 20 + 58 c;
El compilador de java directamente reemplaza los nmeros 20 y 58 por 78. Este caso se
extiende a las expresiones que impliquen todo tipo de operacin aritmtica.
Para aplicar esta tcnica es necesario que se apliquen conceptos fundamentales de
factorizacin y leyes aplicables a expresiones tales como la ley conmutativa y la ley asociativa.
Estas tcnicas se recomienda que se apliquen a los mtodos que contienen valores locales.
A continuacin se muestra un ejemplo al cual se le aplicar la tcnica de Folding.
public void ejemplo6()
{
int arreglo1[]= new int [3000000];
int i,k,lon,l,m,j;
lon = arreglo1.length;
Mtodo
for (i=0;i<lon;i++)
{
arreglo1[i]=(int)(Math.random()* 101);
}
247
k=8500;
l=15250;
m=450;
for (i=0;i<lon;i++)
{
j=arreglo1[i]*((k+l)*m)/150;
}
}
Del mtodo anterior se reemplazaron las expresiones k=8500; l=15250 y m=450, de
forma tal que se sustituy directamente por el valor resultante de aplicarlos en la formula. De
esa manera la tcnica muestra como queda el mtodo.
public void folding()
{
int arreglo1[]= new int [3000000];
int i,k,lon,l,m,j;
lon = arreglo1.length;
for (i=0;i<lon;i++)
{
arreglo1[i]=(int)(Math.random()* 101);
}
for (i=0;i<lon;i++)
{
j=arreglo1[i]*71250;
}
Mtodo
ACTIVIDAD
Dado el siguiente fragmento de cdigo, aplique todas las tcnicas posibles para optimizar el
cdigo.
int arreglo[]= new int [5000000];
int arreglo1[]= new int [5000000];
int a[]= {10,20,30,40,50,60};
int longi=arreglo.length, i, m=0,w, k=50,l=25,m=50;
for (i=0;i<longi;i++)
{
arreglo[i]= a[m++]+arreglo1[i]*Math.pow(i,2)+
Math.pow(i,2)+1;
if(m==6)
{
m=0;
}
}
for (i=0;i<longi;i++)
{
w=Math.pow(a[i],6)+ 500;
}
248
for (i=0;i<long;i++)
{
arreglo1[i]= arreglo1[i]+m+k/m*l;
}
Dado el siguiente fragmento de cdigo, aplique todas las tcnicas posibles para optimizar el
cdigo.
a=16541;
b=24415;
c=86414;
for(int i=0; i<tam;i++)
{
arreglo[i]=(54*i)+((b+((int)Math.sqrt(b*b)+(4*a*c))/(2*a)));
}
Dado el siguiente fragmento de cdigo, aplique todas las tcnicas posibles para optimizar el
cdigo.
public void ejercicio()
{
int prueba[]= new int [900];
int solucion [] = new int [8];
int k = 0;
for (int i = 2; i < prueba.length; i++)
{
k++;
prueba[i]= (i*3) + 25;
if (k % 2 == 0)
{
k = 13;
for (int j = 4 ; j < 11; j++)
{
solucion[j]= prueba[j]+Math.pow(prueba[j],2);
}
}
}
}
5.3
El Diseo por contrato es una metodologa que se basa en la idea de tener claramente definido
lo que se tiene en la entrada y lo que se debe proporcionar como resultado. A este conjunto de
trminos lo denominaremos contrato entre las partes. En general, puede afirmarse que el
contrato es un acuerdo formal, en el que se expresan las obligaciones y derechos de los
participantes. Por lo tanto si ocurre algn error nos remitiremos al contrato para poder
determinar las responsabilidades. Tenga en cuenta que para asignar responsabilidades se
puede apoyar en la tcnica del experto (el dueo de la informacin es el responsable de ella) o
la tcnica de descomposicin por requerimientos (descomponer un requerimiento funcional en
subproblemas para poder satisfacer el requerimiento completo) (Villalobos & Casallas, 2006).
Considere el siguiente mtodo:
public void
direccion)
agregarEstudiante(String
249
cdigo,
String
nombre,
String
La precondicin expresa las restricciones necesarias para que la operacin funcione de forma
adecuada.
El resultado de la ejecucin del mtodo (denominado postcondicin) debe ser:
Se agreg al estudiante.
Se produjo un error y no se pudo efectuar la operacin de agregar.
La postcondicin se define como las condiciones que deben ser ciertas cuando termina la
ejecucin del mtodo.
Se considera entonces que la precondicin son las condiciones impuestas para que se d el
desarrollo del mtodo, mientras que la postcondicin se considera como los compromisos
aceptados.
Es muy importante realizar una adecuada documentacin a los contratos, esto se logra
haciendo uso de javadoc. Tenga en cuenta que en general, se deben agregar los comentarios
a cada uno de los mtodos, que componen un programa.
/**
* Estos son comentarios javadoc
*/
Cuando se usan comentarios javadoc, se puede especificar la versin, fecha de creacin,
autor.
* @ version 1.0
* @ created Nov-2007
* @ author Carlos Perez
Para que eclipse nos ahorre un poco de trabajo con la generacin de la documentacin javadoc
se debe digitar /** y presionar la tecla enter.
Ya enfocndonos en el contrato, la documentacin debe tener la siguiente estructura:
/**
* Este mtodo permite agregar un nuevo estudiante a un curso de
* programacin
* <b>pre: </b> El array donde se guardan los estudiantes no es null.
* <b>post: </b> Se ha agregado un nuevo estudiante.
* @ param cdigo. Cdigo estudiante. codigo!=null, !codigo.equals("");
* @ param nombre. Nombre estudiante. nombre!=null, !nombre.equals("");
* @ param direccin. Direccin estudiante direccion!=null,!direccion.
* equals("");
* @throws Exception si un estudiante tiene el mismo cdigo genera una
* excepcin
*/
250
251
5.4
Java dispone del Framework JUnit para la realizacin y automatizacin de pruebas. Las
pruebas permiten verificar el funcionamiento de los mtodos de la clase, para determinar si
funcionan como se espera. Es decir, permiten para identificar posibles errores y revelar el
grado de cumplimiento en relacin a las especificaciones que inicialmente se plantearon para el
sistema.
La realizacin de pruebas es fundamental a la hora de garantizar la calidad del software
construido. Para crear una clase de prueba es necesario ubicarse en el paquete test, el cual
debi crear previamente, luego dar clic sobre l y seleccionar JUnit Test Case.
Para mostrar el uso de JUnit se tendr en consideracin el caso de estudio para un estudiante.
A continuacin se muestra la descripcin del problema.
Se desea crear una aplicacin para manejar la informacin de un estudiante. Un estudiante
tiene un cdigo, un nombre y una nota definitiva. Se debe permitir crear un nuevo estudiante,
dar una bonificacin de una dcima en la nota definitiva y devolver el cdigo del estudiante.
El diagrama de clases correspondiente es:
252
En Class under Test se debe presionar el botn Browse y luego se debe escribir el nombre de
la clase a la que se le va a hacer el test. A continuacin dar clic en Ok.
253
setUpBeforeClass: Este mtodo ser ejecutado al inicio del lanzamiento de todas las
pruebas. nicamente puede tenerse un mtodo con esta opcin. Se utiliza en general
para inicializar atributos que son comunes a todas las pruebas.
tearDownAfterClass: nicamente puede haber un mtodo con esta marca. Se ejecuta
una sla vez cuando ha finalizado la ejecucin de todas las pruebas.
tearDown: Se ejecuta despus de ejecutar todas las pruebas de esta clase. Este
mtodo se sustituye por la anotacin @After. Esta etiqueta efecta todo lo contrario de
la etiqueta @Before.
setUp: Se invoca antes de ejecutar cada prueba. Este mtodo se sustituy por la
anotacin @Before
Test: Se le coloca @Test a la prueba que se va a ejecutar
Ignore: El mtodo que tenga esta marca no ser ejecutado.
setCodigo(String)
setNombre(String)
setNota(double)
calcularBonificacion()
Mtodo
254
{
fail("Not yet implemented");
}
@Test
public void testSetNota()
{
fail("Not yet implemented");
}
@Test
public void testCalcularBonificacion()
{
fail("Not yet implemented");
}
}
A continuacin se debe usar la siguiente clase para verificar que los mtodos de la clase
Estudiante estn correctamente implementados. Es necesario modificar el cdigo para que
quede de la siguiente forma:
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
public class EstudianteTest
{
private Estudiante miEstudiante;
/** Construye un nuevo estudiante*/
@Before
public void setupEscenario1( )
{
miEstudiante=new Estudiante();
miEstudiante.setCodigo("123");
miEstudiante.setNombre("Juan");
miEstudiante.setNota(3);
}
/** Prueba de los mtodos setCodigo*/
Mtodo
@Test
public void testSetCodigo(){
assertEquals( "El codigo es
invlido.", "123",
miEstudiante.getCodigo() );
}
@Test
public void testSetNombre() {
assertEquals( "El nombre es
invlido.", "Juan",
miEstudiante.getNombre());
}
@Test
public void testSetNota() {
assertEquals( "La nota es
incorrecta.", 3.0,
miEstudiante.getNota(),1 );
}
255
@Test
public void testCalcularBonifiacion()
{
assertEquals( "La nota definitiva con
bonificacin es incorrecta.", 3.1,
miEstudiante.calcularBonifcacion(),1 )
}
}
5.5
Lmites de la Lgica
Como ltima seccin de este libro se plantea una clasificacin de los problemas segn el tipo
de algoritmo. Se describirn los conceptos fundamentales de los algoritmos de clase P, clase
NP y NP completos.
5.5.1
Clase P
Los algoritmos de la clase P son conocidos como aquellos algoritmos cuyo tiempo de ejecucin
y complejidad computacional se encuentra en un orden polinmico. Con base en lo analizado
en este libro se puede afirmar que los algoritmos con tiempo de ejecucin polinmico son aun
considerados como eficientes y por lo tanto son tratables y manejables en la prctica.
Algunos ejemplos de problemas y soluciones que se encuentran en la clase P, son los
siguientes:
5.5.2
Clase NP
Problema de aprendizaje
Problemas complejos con Grafos
Coloreado de Grafos
El problema del Agente Viajero
Programacin automtica de Tareas
256
BIBLIOGRAFA
Aho, A., & Ullman, J. (1995). Foundations of Computer Science. Computer Science Press,
1995.
Aho, A., Ullman, J., & Hopcrof, J. (1994). The Design and Analysis of Computer. AddisonWesley.
Baldwin, D., & Scragg, G. (2004). Algorithms & Data Structures. Massachusetts: Computer
Engineering Series.
Bedoya, O. (2008). Estructura de Datos y Algoritmia. Cali, Valle, Colombia.
Besembel, I. (2006). Diseo y Anlisis de Algoritmos. Recuperado el 10 de 10 de 2011
Bohquez, J. (2006). Diseo Efectivo de Programas Correctos. Bogot: Lemoine Editores.
Brassard, G., & Bratley, P. (1997). Fundamentos de Algoritmia. Madrid: Prentice Hall.
Cardona, S., Jaramillo, S., & Carmona, P. (2007). Anlisis de Algoritmos en Java. Armenia:
Elizcom.
Cardona, S., Jaramillo, S., & Villegas, M. (2008). Introduccin a la Programacin en Java .
Armenia: Elizcom.
Colmenares, J. (2006). Grafos. Recuperado el 10 de 11 de 2011, de
http://www.ica.luz.ve/juancol/eda/grafos/grafos.html
Cormen, T., Leiserson, C., Rivest, R., & Stein, C. (2001). Introduction to Algorithms.
Dunfermline, FIF, United Kingdom: The MIT Press.
Di Mare, A. (1998). Convenciones de Programacin para Pascal. Recuperado el 1 de 10 de
2011, de http://www.di-mare.com/adolfo/p/convpas.htm
Garca, A., Delgado, J., & Castaeda, S. (2000). Metodologas de Optimizacin en
CICESE2000. Recuperado el 1 de 9 de 2011, de
http://telematica.cicese.mx/computo/super/cicese2000/optimiza/
Goodrich, M. T., & Tamassia, R. (2002). Estructuras de datos y algoritmos. Cecsa.
Grimaldi, R. (1998). Matemtica discreta y combinatoria. Addison Wesley Longman.
Guerequeta, R., & Vallecillo, A. (2000). Tcnicas de Diseo de Algoritmos . Mlaga: Servicio de
Publicaciones de la Universidad de Mlaga.
Hernndez, G. (2004). Grafos. Madrid, Espaa.
Hernndez, L. (2004). Anlisis de Algoritmos y Complejidad Computacional. Recuperado el 10
de 11 de 2011, de http://www.geocities.ws/leoher314/algorit.htm
Iparraguirre, J. (2009). Algoritmos para caminos mnimos. Lima, Per.
257
258