Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
NDICE
ALGORITMOS Y LENGUAJES
ALGORITMOS Y LENGUAJES
TRATAMIENTO
Datos
Resultados
Figura 1.1
El hombre puede pensar de forma precisa sobre problemas simples: por el contrario, en
el esfuerzo que realiza para entender problemas complicados, necesita concentrarse en
un pequeo nmero de propiedades que cree esenciales para su propsito e ignora todos
los dems aspectos. En cierto sentido, su eficacia para resolver problemas, reside en la
mxima "divide y vencers".
Una vez que entiende un problema en trminos de un nmero limitado de aspectos,
procede a analizar cada uno de ellos separadamente, con ms detalle. Es normal que sea
necesario repetir este proceso, con lo que el problema original aparece como una
jerarqua de abstracciones relacionadas a diferentes niveles de detalles. El conjunto de
conexiones entre componentes, a un nivel dado de detalle, define la estructura del
problema a ese nivel.
Los mecanismos de abstraccin y de reconocimiento de la estructura subyacente se usan
en todas las disciplinas intelectuales, para presentar los conocimientos en una forma fcil
de entender y de recordar. Se aplica pues un mecanismo de anlisis descendente del
problema (top-down) o de refinamiento por pasos sucesivos que ser objeto de nuestra
atencin posteriormente.
ALGORITMOS Y LENGUAJES
ALGORITMOS Y LENGUAJES
Paso 2.
Paso 3.
Programa:
La expresin de ese algoritmo en un lenguaje de programacin. De esta forma
queda perfectamente comprensible para el computador.
Proceso
Hacer un postre
Algoritmo
Receta
Hacer un vestido
Partitura musical
Instrucciones de
ensamblaje
Figura 1.2 Ejemplos de algoritmos prcticos en nuestra vida cotidiana
ALGORITMOS Y LENGUAJES
este
Realmente
bruta
para
nuestro
que
existen
ya
Problema 2. Cmo hacer Procedimiento. Tome 10.000 Comentario. Observe que hemos
10.000.000 de pts.?
procedimiento
algoritmo
pts.
b) pierda todo el dinero.
no
porque
(!desgraciadamente
a) rena los 10.000.000 de
para
Problema 3. Rellenar una Algoritmo. Tome una pala y Comentario. Este algoritmo es
zanja de tierra.
simple
no
tiene
ALGORITMOS Y LENGUAJES
Paso b:
Hacer z = 1
Paso b:
Calcular z2
Paso c:
Paso d:
este procedimiento es un caso especial del mtodo de Newton-Raphson (ver Figura 1.4).
De esta forma se obtendr una secuencia de puntos z0, zl, z2, .... que, finalmente
converger a la solucin z con la precisin que se desee.
E1 procedimiento anterior tiene en cada paso la definicin precisa requerida por un
algoritmo. Mas an, siempre que se aplica a un nmero real no negativo x, se obtendr
la solucin correcta en un numero finito de pasos. Sin embargo, siempre que se aplica a
un nmero negativo, se estar recalculando indefinidamente z sin que por ello se
reconozca lo intil de esta tarea. Esto es tpico de una clase de mtodos llamados semialgoritmos: pararn en un nmero finito de pasos si el problema planteado tiene
solucin, pero no terminar necesariamente en caso contrario.
Para transformar el mtodo dado en un algoritmo, se debe hacer una cosa: aadir un
paso 0;
Paso 0:
10
ALGORITMOS Y LENGUAJES
f(z)
f(z)
z
(z , f(z ))
0
valor buscado
parbola
f(z) = z2 - x
f(z)
z0
z1
z1 z
Figura 1.4 Ilustracin del mtodo de Newton -Raphson para el clculo de la raz
cuadrada positiva de un nmero x > 0. En trminos matemticos se trata de determinar
el nmero real z > 0 tal que: f(z) = z 2 - x = 0
11
Incluso procesos que pueden ser realizados por un computador pueden no terminar
nunca, como por ejemplo:
Controlar las seales de trfico
Control de pacientes en una unidad de cuidados intensivos
12
ALGORITMOS Y LENGUAJES
Adems muchas palabras tienen diferentes acepciones o significados que solo se pueden
resolver considerando la situacin del contexto en que se producen. Incluso un anlisis
gramatical correcto depende del significado de las palabras que a veces se emplean en un
13
sentido metafrico que hace que la interpretacin que da el receptor tome en cuenta la
entonacin con que dicha frase se pronuncia.
A pesar de estas dificultades, se han conseguido algunos avances en la comprensin de
lenguajes naturales mediante computador. Como los lenguajes naturales son demasiados
complejos para que un computador pueda entenderlos, los algoritmos que se van a
ejecutar en estas mquinas deben de escribirse de una forma mucho mas simple.
Recordemos que un algoritmo expresado de esta manera se denomina "un programa" y
que un programa est escrito utilizando un lenguaje de programacin. Desde la aparicin
de los computadores, se han propuesto multitud de lenguajes de programacin pensados
con el fin de resolver categoras de problemas y describir de una manera clara y precisa
los programas. Algunos de los lenguajes de programacin ms conocidos son: Fortran,
Pascal, C, C++, Java, Cobol, Algol, etc. La razn de que existan tantos lenguajes de
programacin es triple:
a) La programacin de computadores es una actividad relativamente reciente, y
las ideas acerca de cmo hacer mejor las cosas estn an en continua
evolucin. As cuando surgen nuevas ideas aparecen a su vez nuevos lenguajes
de programacin.
b) Los computadores se utilizan para una gran variedad de objetivos. Esto implica
que los algoritmos utilizados son de una naturaleza diversa y no pueden
expresarse de una forma cmoda en un nico lenguaje de programacin. Esto
ha llevado consigo el desarrollo de lenguajes de programacin de propsito
especial que permitan expresar algoritmos que surjan en campos de aplicacin
especficos. As, por ejemplo, los algoritmos utilizados en gestin comercial
son completamente diferentes de los requeridos en clculos cientficos o
incluso de los utilizados para controlar una planta industrial.
Consecuentemente, se han desarrollado diferentes lenguajes de programacin
para expresar estas diferentes clases de algoritmos (Cobol, Fortran, C).
c) Existe una tendencia natural e inevitable por parte de los especialistas en
Informtica de estar continuamente "descubriendo Amrica". Es la creencia de
que las "propias ideas" son mejores que las de los dems, an en el supuesto de
que no sean originales.
14
ALGORITMOS Y LENGUAJES
Por analoga con los lenguajes naturales, cada lenguaje de programacin tiene su propio
vocabulario y sus propias reglas gramaticales que dictan cmo se debe de utilizar este.
En la mayor parte de los casos, el vocabulario consta de ciertos smbolos matemticos y
de unas pocas palabras en ingls (ya que casi todos los lenguajes de programacin de uso
extendido son de procedencia sajona y principalmente norteamericana), y las reglas
gramaticales son bastante simples para permitir que el computador pueda interpretar los
programas. A causa de la diferencia tanto en su vocabulario como en su gramtica, los
lenguajes de programacin naturalmente difieren en las formas de expresin permitida,
por ejemplo uno de los pasos en un algoritmo de contabilidad se podra expresar en
Cobol como:
MULTIPLY precio BY cantidad GIVING coste
y en Pascal como:
coste := precio * cantidad
Ambas formas de expresin significan la misma cosa; es decir una instruccin para
multiplicar un nmero llamado "precio" por un nmero llamado "cantidad" para dar
como resultado un nmero llamado "coste".
Los diseadores de lenguajes de programacin intentan conseguir algunos objetivos,
entre los cuales los ms importantes son los siguientes:
1) El lenguaje debe permitir la expresin fcil y concisa de algoritmos en el rea
de aplicacin para la cual se disea.
2) El lenguaje debe resultar comprensible al computador.
3) Los programas escritos en el lenguaje deberan ser rpidamente asimilables por
el ser humano, de manera que se puedan modificar y corregir fcilmente
cuando sea necesario.
4) El lenguaje debera minimizar el potencial de error en la transformacin de un
algoritmo en un programa.
5) Debera ser fcil de demostrar mediante el examen de un programa, que su
ejecucin verdaderamente llevar a cabo el proceso que se desea.
15
Resulta obvio que estos objetivos no son todos mtuamente compatibles. Por ejemplo, la
condicin de las expresiones puede ir contra la comprensin de las mismas (por el uso de
acrnimos), mientras que un lenguaje que se disea de forma que sea fcilmente
comprensible por el hombre puede no resultarlo para el computador (cualquier lenguaje
natural es un ejemplo extremo).
En lo que sigue aparecern algoritmos de muy diversas clases que fundamentalmente
queremos que sean comprensibles al lector no tanto como al computador. Por esta razn
no vamos a utilizar un lenguaje de programacin formal para expresar los algoritmos. Sin
embargo con el soporte de cualquier lenguaje de programacin como herramienta (por
ejemplo, Pascal) podr darse cuenta que la transcripcin a un lenguaje es una tarea
mucho ms sencilla cuando se ha comprendido la estructura del algoritmo.
16
ALGORITMOS Y LENGUAJES
es que dos nmeros llamados "precio" y "cantidad" tienen que multiplicarse para dar
un tercer nmero llamado "coste".
El significado de formas particulares de expresiones en un lenguaje se llama la semntica
del lenguaje. Los lenguajes de programacin se disean de forma que tanto su sintaxis
como su semntica sean relativamente simples y de que un programa se pueda analizar
sintcticamente sin hacer referencia a la semntica. Esto est en abierta oposicin con los
lenguajes naturales en los que la sintaxis y la semntica son muy complejas y a menudo
estn muy interrelacionadas.
En lenguajes naturales es posible escribir sentencias que son sintcticamente correctas
pero que carecen de significado. Por ejemplo:
17
y
escriba el nombre del decimotercer mes del ao
18
ALGORITMOS Y LENGUAJES
19
Este algoritmo es sintcticamente correcto (es una sentencia en castellano correcta y que
tiene sentido). No obstante, produce un resultado errneo; hay un error lgico en la
omisin del 2 como factor.
Un procesador no puede detectar errores lgicos ya que no tiene idea de qu proceso
desea describir el algoritmo. Los errores lgicos se pueden detectar nicamente
comparando el proceso deseado con el proceso realmente efectuado. Veamos a
continuacin que pasos se deben tomar para en la medida de lo posible evitar los errores
lgicos.
cul tienda giro?) y nos enve a una calle equivocada. Al menos en este caso el
procesador es humano, con sentido comn, probablemente suficiente, para reconocer el
error y actuar en consonancia; los computadores, desgraciadamente, no estn equipados
con tales recursos.
Otro fallo comn de los algoritmos es que su ejecucin normalmente realiza el proceso
deseado, pero bajo ciertas circunstancias (no previstas o pasadas por alto por el
diseador) no lo hace. Como ejemplo, consideremos el siguiente algoritmo que describe
cmo calcular el tiempo de vuelo de un avin a partir del libro de horarios de una
compaa area:
20
ALGORITMOS Y LENGUAJES
El algoritmo normalmente dar el resultado correcto, pero fallar si los puntos de partida
y de llegada estn en zonas horarias diferentes.
La moraleja de estos ejemplos es que el diseador de un algoritmo debe tomar gran
cuidado de que este describa de forma precisa al proceso deseado y de que han sido
consideradas todas las circunstancias posibles.
Si el proceso es complicado, entonces la tarea del diseador es realmente difcil, y tendr
muy pocas probabilidades de xito, a menos de que adopte un procedimiento
rigurosamente metdico. A continuacin se describe un enfoque de este tipo conocido
como refinamiento por pasos sucesivos (anlisis descendente).
La idea de base es dividir el proceso en una serie de pasos, donde cada uno de los cuales
se puede describir por un algoritmo que es ms pequeo y ms simple que el proceso
entero. Debido a la mayor simplicidad de estos subalgoritmos, el diseador tiene una idea
ms clara de cmo construirlos y puede por lo tanto precisarlos con ms detalle que si
intenta manejar el algoritmo completo como un todo. Los subalgoritmos pueden a su vez
estructurarse en partes ms pequeas que se expresan con mayor detalle y precisin. El
refinamiento del algoritmo continua de esta manera hasta que cada paso esta
suficientemente detallado y preciso como para permitir su ejecucin por el procesador
que lo va a realizar.
Como ejemplo, supongamos un robot que queremos que acte como nuestro sirviente
domstico y al que hay que especificarle un algoritmo que describa como hacer una taza
de caf instantneo. Una versin inicial del algoritmo podra ser:
1) hervir agua
2) poner caf en la taza
3) aadir agua a la taza
21
1) hervir agua
anlogamente
2) poner caf en la taza
se puede refinar a:
2.1) abrir el tarro del caf
2.2) extraer una cucharada de caf
2.3) volcar la cucharada en la taza
2.4) cerrar el tarro del caf
y
3) aadir agua a la taza
en
3.1) verter agua de la cafetera en la taza hasta que se llene
22
ALGORITMOS Y LENGUAJES
1.1.2)
abrir el grifo
1.1.3)
1.1.4)
cerrar el grifo
1.2)
1.3.1)
1.4)
conectar la cafetera
esperar hasta que suene el avisador de la cafetera
desconectar la cafetera
2.1.2)
2.2)
2.3)
2.4.1)
2.4.2)
23
Algoritmo original
1) Hervir agua
1er Refinamiento
2 Refinamiento (final)
Figura 1.5 Refinamiento del algoritmo para hacer una taza de caf
Las lneas que estn encerradas entre llaves son simplemente comentarios para ayudar al
lector: no son pasos ejecutables en el algoritmo, y por lo tanto el robot los ignora. Cada
comentario describe la funcin de la parte del algoritmo que le sigue.
Cuando se utiliza este procedimiento de refinamiento, el diseador de un algoritmo debe
por supuesto conocer dnde parar; esto es, debe saber cundo un paso particular en el
algoritmo est suficientemente claro como para no necesitar ms refinamiento. Esto por
supuesto significa que debe saber que clase de pasos puede interpretar el procesador. En
nuestro ejemplo hemos supuesto que el robot puede interpretar
conectar la cafetera
24
ALGORITMOS Y LENGUAJES
1.8 SECUENCIA
El algoritmo de hacer caf es muy directo, ya que consiste en una serie de pasos simples
que se ejecutan uno despus de otro. Decimos que tal algoritmo es una secuencia de
pasos, que verifica:
1) Los pasos se ejecutan uno cada vez.
2) Cada paso se ejecuta exactamente una sola vez; ninguno se repite y ninguno se
omite.
3) El orden en el que se ejecutan los pasos es el mismo en el que se escriben.
4) La terminacin del ltimo paso implica la terminacin del algoritmo.
En lo que sigue convenimos que los pasos sucesivos en una secuencia se escribirn en
lneas sucesivas.
25
1.9 SELECCIN
Acabamos de ver que cuando un algoritmo es solamente una secuencia no hay
posibilidad de modificar su ejecucin. As en el ejemplo del robot no podamos tratar el
caso de que el tarro de caf estuviese vaco; lo que se necesita es la capacidad para
ejecutar un paso tal como:
obtener un nuevo tarro de la alacena
si el tarro actual est vaco y en otro caso omitir este paso.
2.1.2)
2.1.3)
quitar la tapa del tarro
El paso crucial es el paso 2.1.2 que expresa tanto la accin a seleccionar (obtener un
nuevo tarro de la alacena) y la condicin (el tarro est vaco) bajo la cul se realiza la
seleccin. El paso 2.1.2 es un caso particular de un paso de la forma general:
si condicin
26
ALGORITMOS Y LENGUAJES
entonces accin
ya que:
si condicin
entonces accin
si condicin
entonces accin
27
si no no hacer nada
son equivalentes. Sin embargo y siempre que sea posible utilizaremos la forma
simplificada.
Como un ejemplo ms del uso de la seleccin presentamos un algoritmo para
aproximarnos a un conjunto de seales de trfico:
Un algoritmo algo mejor, que permite la posibilidad de que las seales estn fuera de
servicio es:
si no hay seal
entonces proseguir con gran cautela
si no si seal est en rojo o en mbar
entonces parar
si no proseguir
Este algoritmo contiene dos ocurrencias de seleccin, la segunda de las cuales est
anidada dentro de la primera y se ejecuta solamente si el semforo est operativo.
Obsrvese como el uso del sangrado hace bastante claro al lector que pasos en el
algoritmo son parte de cada seleccin. Sin sangrado el algoritmo sera mucho ms difcil
de comprender:
si no hay seal
entonces proseguir con gran cautela
si no si seal est en rojo o en mbar
28
ALGORITMOS Y LENGUAJES
entonces parar
si no proseguir
Otro ejemplo de seleccin anidada surge en el siguiente algoritmo, que describe cmo
determinar el mayor de tres nmeros dados con un procesador que en cada instante solo
puede comparar dos de ellos. Si los nmeros se llaman x, y y z, una primera versin del
algoritmo es:
si x > y
entonces escoger entre "x" y "z"
si no escoger entre "y" y "z"
Obsrvese como el sangrado hace otra vez claro qu pasos del algoritmo son partes de
cada una de las tres selecciones. (El lector que todava dude del valor del sangrado
podra escribirlo sin ello y se dar cuenta de la diferencia).
La potencia de la seleccin es que permite al procesador seguir diferentes caminos a
travs de un algoritmo de acuerdo con la circunstancias. Las selecciones anidadas
29
permiten que el nmero de caminos sea arbitrario. Sin seleccin sera imposible escribir
algoritmos de cualquier significacin prctica.
1.10 ITERACIN
Consideremos el proceso de localizar la direccin de una persona, dado su nombre, a
partir de una lista de nombres y direcciones. Un posible algoritmo es:
Considerar el primer nombre en la lista
S1
S1
S1
El problema con este algoritmo (aparte de salirnos del papel por el margen derecho) es
que su autor no sabe cundo parar de escribir.
De forma ms precisa no sabemos cuntas veces escribir el conjunto de acciones Sl para
estar seguros de que se encuentra el nombre. Un problema anlogo surge en el algoritmo
siguiente, que describe cmo calcular el primer numero primo que es mayor que un
nmero dado de comienzo (que se supone que es un entero positivo)
30
ALGORITMOS Y LENGUAJES
sumar 1
comprobar el nmero para ver si es primo
si el nmero es primo
entonces escribirlo
S2
si no sumar 1
comprobar el nmero para ver si es primo
si el nmero es primo
entonces escribirlo
si no sumar 1
................
Otra vez no est claro cuntas veces hay que escribir la secuencia S2 para asegurar que
el procesador produce un nmero primo. Por ejemplo, se necesita escribir S2 solamente
una vez si el nmero de comienzo es el 4, y cuatro veces si es 13, pero cuntas veces si
el nmero inicial es 7.394.485?
Estos ejemplos demuestran que la secuencia y la seleccin no son suficientes por s
mismas para expresar algoritmos cuya longitud vara segn las circunstancias. Lo que se
requiere es un medio de repetir ciertas acciones en un algoritmo un nmero arbitrario de
veces. Para hacer esto introduciremos las palabras, repetir y hasta en los algoritmos. De
esta forma el primer algoritmo de esta seccin se puede reescribir como:
considerar el primer nombre en la lista
repetir
si este nombre es el dado
entonces extraer la direccin correspondiente
si no considerar el siguiente nombre en la lista
hasta que se encuentre el nombre dado o se acabe la lista
31
que significa que la parte del algoritmo entre las palabras repetir y hasta se ejecuta
repetidamente hasta que la condicin especificada despus de hasta es cierta.
En el primero de los algoritmos lo que se repite es la inspeccin de nombres sucesivos en
la lista; la repeticin cesa cuando se localiza el nombre que se busca o se termina la lista.
En el segundo la repeticin se aplica a la comprobacin de nmeros sucesivos para ver si
son primos y se acaba cuando se encuentra el primero.
La ocurrencia de una iteracin se suele llamar un bucle y la parte del algoritmo que se
repite (la parte entre repetir y hasta) se conoce como el cuerpo del bucle. La condicin
que ocurre despus de hasta se denomina la condicin de terminacin.
La potencialidad de la iteracin es que permite que un proceso de duracin
indeterminada sea descrito por un algoritmo de longitud finita. Esta potencia conlleva un
cierto grado de responsabilidad; ya que hay que asegurar que la iteracin
verdaderamente acaba. En el algoritmo del numero primo, la iteracin finaliza porque
siempre existe un numero primo mayor que uno dado. En el otro algoritmo, la iteracin
tambin alcanza un final porque la condicin de terminacin "que se encuentre el nombre
dado o que se acabe la lista'' finalmente se hace cierta. Obsrvese, sin embargo, que la
omisin de la segunda parte de la condicin de terminacin ("o se acabe la lista") es
potencialmente desastrosa, puesto que si el nombre que se busca no est presente el
procesador no sabr qu hacer al final de la lista. Los fallos de especificar correctamente
32
ALGORITMOS Y LENGUAJES
Como un ejemplo adicional de iteracin consideramos otra vez el algoritmo del nmero
primo. El bucle de este algoritmo contiene el paso:
comprobar el nmero para ver si es primo
El primer paso claramente involucra una iteracin, en la que el primo potencial se divide
por los sucesivos posibles factores comenzando por 2. La iteracin puede terminar o
cuando una de las divisiones es exacta (en cuyo caso se demuestra que primo potencial
no es primo), o cuando el probable factor es igual al primo potencial (en cuyo caso el
primo potencial realmente es primo). De hecho no hay necesidad de prolongar la
iteracin hasta el punto en el que el posible factor es igual al primo potencial; razonando
un poco se ve que es suficiente ir nicamente hasta la raz cuadrada del primo potencial.
El algoritmo quedara entonces de la forma siguiente
33
v(primo potencial)
Este algoritmo contiene dos bucles, uno anidado dentro del otro. El lazo externo se
ejecuta una vez para cada primo potencial, mientras que el lazo interno se ejecuta una
vez para cada posible factor de un primo potencial. ambos bucles son esenciales en el
algoritmo.
34
ALGORITMOS Y LENGUAJES
Este algoritmo parece correcto, pero contiene un error serio que resulta aparente si la
lista solamente tiene un elemento. En este caso el procesador no sabr qu hacer al final
de la lista tan pronto como ejecuta el cuerpo del bucle por primera vez. Por supuesto que
la condicin de terminacin "que la lista se acaba" se coloca para evitar que esto
suceda, pero en este caso es ineficaz ya que el procesador no comprueba la condicin de
terminacin hasta que ha ejecutado el cuerpo al menos una vez. Lo que se requiere es
una forma de colocar la condicin de terminacin al comienzo del bucle en lugar de al
35
El cuerpo del bucle comprende todo lo que est sangrado debajo de mientras y la
condicin de terminacin aparece antes del cuerpo entre mientras y hacer. La forma
general de este tipo de bucles es:
mientras condicin hacer
cuerpo del bucle
que indica que el cuerpo del bucle se ejecuta repetidamente mientras la "condicin" es
cierta. Como la condicin se comprueba antes de que se ejecute el cuerpo este tipo de
bucle se llama "pre-comprobado" y el tipo de bucle con repetir se denomina "postcomprobado".
Debido a las diferentes posiciones de la condicin de terminacin el cuerpo de un bucle
"post-comprobado" se ejecuta siempre al menos una vez, mientras que el cuerpo de un
bucle "pre-comprobado" puede no ejecutarse ninguna vez.
Para consolidar las ideas acerca de la iteracin que hemos presentado examinemos
brevemente un algoritmo muy antiguo: el algoritmo de Euclides, desarrollado para
determinar el mximo comn divisor (MCD) de dos enteros positivos.
El algoritmo de Euclides se basa en la siguiente relacin:
36
si y > 0
MCD (x,y) = x
si y = 0
ALGORITMOS Y LENGUAJES
donde x e y son dos enteros no negativos cualesquiera. Para ilustrar el uso de la relacin
anterior consideremos el problema de determinar el MCD de 24 y 9:
MCD (24, 9) = MCD (9, 6) = MCD (6, 3) = MCD (3, 0) =
Este algoritmo ejemplifica un tipo de iteracin que tiene la siguiente forma general:
repetir N veces
37
donde N es cualquier entero positivo arbitrario, y el cuerpo del bucle se sangra debajo
de repetir. Como el nmero de repeticiones se define de antemano este tipo de
iteracin se conoce como "iteracin definida" en oposicin a la anterior "iteracin
indefinida" en la que el nmero de repeticiones depende de lo que acontece cuando se
ejecuta el bucle.
La duracin de la iteracin definida est determinada a la entrada del bucle y la
terminacin est garantizada. La iteracin indefinida, por otra parte, depende de que
eventualmente se haga cierta la condicin de terminacin.
38
ALGORITMOS Y LENGUAJES
Lista Inicial
1 Pasada
2 Pasada
3 Pasada
(4 cambios)
(3 cambios)
(2 cambios)
Juan
Juan
Felipe
Arturo
Luis
Felipe
Arturo
Felipe
Felipe
Arturo
Juan
Jos
Arturo
Luis
Jos
Juan
Samuel
Jos
Luis
Luis
Jos
Mara
Mara
Mara
Mara
Samuel
Samuel
Samuel
Observar que se utiliza un bucle pre-comprobado con preferencia a uno postcomprobado, ya que el procesador puede tener la suerte de encontrarse que la lista est
ordenada y no hay nada que hacer. (Esta decisin la revisaremos posteriormente cuando
refinemos el algoritmo).
Podemos refinar el algoritmo como sigue:
39
Si antes de entrar en el bucle se sabe el nmero de nombres (por ejemplo N), entonces el
bucle indefinido repetir se puede reemplazar por uno definido ya que hay exactamente
N-l pares de nombres adyacentes a examinar. Por lo tanto el algoritmo completo se
puede escribir:
mientras lista no est clasificada hacer
comenzar en el primer nombre de la lista
repetir N-l veces
si nombre debe estar detrs de su sucesor alfabticamente
entonces cambiar el nombre y su sucesor
considerar el siguiente nombre en la lista
Este algoritmo resulta adecuado a condicin de que el procesador sea capaz de decir (en
la 1 lnea) si la lista est clasificada. Si el procesador es incapaz de esto, la condicin de
terminacin en la lnea 1 necesita un mayor refinamiento. Una forma de decirle si la lista
est ya ordenada es recordar si se necesit cambiar algn nombre durante la ltima
pasada. Si no, todos los nombres deben estar ya en su posicin correcta y la lista est por
lo tanto ordenada. Obsrvese que al menos se requiere una pasada sobre la lista para ver
si est ya ordenada; as pues el bucle pre-comprobado de nuestra ltima versin del
algoritmo no resulta necesario y se puede reemplazar por un bucle post-comprobado.
Con estos refinamientos resulta el siguiente algoritmo:
repetir
comenzar en el primer nombre de la lista
repetir N - 1 veces
40
ALGORITMOS Y LENGUAJES
41
estas construcciones con otras dos que, aunque no son estrictamente necesarias, s que
resultan convenientes.
1.12 ACTIVIDADES
1. Describa por medio de un algoritmo la explicacin de una leccin de su eleccin a sus
alumnos.
2. Refine el algoritmo anteri or por pasos sucesivos.
3. Exprese el algoritmo anterior utilizando nicamente las estructuras de secuencia,
seleccin e iteraccin.
42
ALGORITMOS Y LENGUAJES
2.1 MODULARIDAD
Hemos visto en el tema anterior como se pueden desarrollar algoritmos mediante un
proceso de refinamiento por pasos sucesivos. En cada etapa el algoritmo se divide en
componentes ms pequeos que se pueden especificar con mayor detalle. El refinamiento
termina cuando cada componente se expresa de forma tal que el procesador que va a
ejecutarlo puede interpretarlo.
A menudo los componentes que surgen son bastante independientes del algoritmo
principal en el sentido de que se pueden disear sin considerar el contexto en que se
utilizan. Tales componentes se pueden hacer por personas diferentes de las que realizan
el algoritmo principal y pueden posiblemente utilizarse en otros problemas diferentes. Se
pueden considerar as como componentes "enchufables" que una vez diseados es
posible incorporarlos en cualquier algoritmo que los necesite
A modo de ilustracin consideraremos la tarea de disear ciertos algoritmos que van a
ejecutarse por un robot simple. La funcin del robot es dibujar figuras; para lograr su
objetivo est equipado con ruedas que le permiten moverse sobre una hoja de papel, y
tiene una pluma que puede apoyar sobre el papel cuando necesita dibujar una lnea.
El robot puede interpretar y ejecutar el siguiente repertorio de rdenes bsicas:
mover (x)
izquierda (x)
derecha (x)
elevar pluma
bajar pluma
Supongamos que se desea que el robot dibuje dos cuadrados concntricos tal como se
muestra en la Figura 2.1. Inicialmente el robot se encuentra en el centro del cuadrado
(punto X) apuntando en la direccin que indica la flecha.
43
moverse al punto A
Paso 2
Paso 3
moverse al punto B
Paso 4
20 cm
10 cm
44
ALGORITMOS Y LENGUAJES
Para que este modulo sea til con generalidad debe ser capaz de dibujar un cuadrado de
cualquier tamao. Cuando se llama al mdulo, debe de indicarse el tamao especfico
que se desea. As, en el algoritmo anterior podramos escribir:
dibujar-cuadrado (10)
dibujar-cuadrado (20)
un
en
cuadrado
el
de
sentido
lado
tamao
antihorario
cm.
El
cuadrado
comenzando
desde
se
la
"tamao" es un parmetro formal del mdulo: se utiliza en el cuerpo del mdulo para
definir cun grande ser el cuadrado. Cuando se llama al mdulo, el parmetro actual
10 ( 20) proporciona un valor especfico para "tamao", y determina as su dimensin
en esta opcin particular.
La forma genrica que utilizaremos para escribir mdulos es:
mdulo nombre del mdulo (parmetros formales)
{especificacin del proceso que describe el mdulo}
cuerpo del mdulo
45
Esto se interpreta por el procesador como un directivo para ejecutar el cuerpo del
mdulo especificado, con los parmetros formales del mdulo reemplazados por los
parmetros actuales de la llamada. Los parmetros formales de un mdulo representan la
informacin que el mdulo necesita cuando se le llama.
Los parmetros actuales son los elementos de informacin proporcionados por una
llamada particular; estas informaciones toman el lugar de los parmetros formales cuando
se ejecuta el mdulo. Es obvio que debern existir el mismo nmero de parmetros
formales y actuales. Un algoritmo que se construye a partir de una serie de mdulos se
llama modular. Utilizando el mdulo dibujar-cuadrado podemos refinar nuestro
algoritmo de dibujar dos cuadrados concntricos como sigue:
izquierda (45)
mover ( 50 )
{moverse al punto A}
izquierda (135)
dibujar-cuadrado (10)
derecha (135)
mover ( 50 )
{moverse al punto B}
izquierda 135)
dibujar-cuadrado ( 20 ) {dibujar el cuadrado externo}
Obsrvese que todos los pasos en este algoritmo son llamadas a mdulos No hemos
dado los algoritmos para los mdulos mover, izquierda y derecha, porque hemos
supuesto que son suficientemente simples para que el robot sea capaz de interpretar la
correspondiente llamada. Si este no es el caso, entonces cada mdulo necesita definirse
en trminos de instrucciones ms simples que el robot pueda interpretar. As, por
ejemplo, el mdulo mover se podra definir como:
mdulo mover (x)
Mueve el robot x cm hacia adelante dejando inalterada su
orientacin.
La pluma no se eleva ni se baja
Asignar x al nmero de rotaciones requeridas por las ruedas
(longitud de la rueda)
46
ALGORITMOS Y LENGUAJES
Esta definicin de mover supone que el robot puede hacer divisiones y sabe cmo girar
sus ruedas. Es importante darse cuenta que el algoritmo de dibujar dos cuadrados
concntricos no necesita saber cmo trabaja el mdulo dibujar-cuadrado; todo lo que
debe conocer es el efecto de ejecutarlo. En otras palabras, no es necesario que conozca
el cuerpo del mdulo, sino solamente la especificacin en su encabezamiento. De esta
forma se puede realizar una separacin clara de los dos problemas de diseo: el diseo
del algoritmo inicial y el de dibujar-cuadrado. Esto reduce la complejidad del proceso
de diseo y conduce por lo tanto a una realizacin ms rpida y fiable.
La potencia de la utilizacin de mdulos se puede ilustrar ms an considerando un
enfoque diferente del mdulo dibujar-cuadrado. Como un cuadrado es simplemente
un caso especial de un polgono regular podra ser ventajoso disear un mdulo para
dibujar polgonos regulares y a continuacin llamarlo con los parmetros actuales
apropiados siempre que se requiera un cuadrado.
Un mdulo para dibujar polgono es:
mdulo dibujar-polgono (tamao, N)
{Dibuja un polgono de N lados con una longitud de tamao
cm. El primer lado se dibuja de acuerdo con la orientacin
actual
del
robot.
El
robot
vuelve
su
posicin
47
Mdulos para dibujar un pentgono, hexgono, etc. se pueden escribir con igual
facilidad. Obsrvese que la nueva versin de dibujar-cuadrado no requiere ninguna
modificacin del algoritmo propuesto para dibujar dos cuadrados concntricos o
cualquier otro algoritmo que lo llame
Las ventajas de utilizar mdulos se pueden resumir como sigue:
1) Los mdulos se adecuan de forma natural en el procedimiento de refinamiento
por pasos sucesivos, dando un diseo de tipo descendente
2) Un mdulo es un componente autocontenido de cualquier algoritmo mayor que
lo llama. El diseo del mdulo y del algoritmo que lo llama se pueden
considerar separadamente, simplificando as el proceso de diseo. Como el
diseo de algoritmos es normalmente bastante difcil, cualquier simplificacin
es bienvenida. Los beneficios de la simplificacin son un diseo ms rpido y
una menor probabilidad de error.
3) Para incorporar un mdulo en un algoritmo es necesario conocer solamente lo
que el mdulo hace y no como lo hace. Lo que un mdulo hace puede ser
especificado de modo conveniente en un comentario en su encabezamiento.
4) De la misma forma que los mdulos simplifican el diseo de algoritmos,
tambin simplifican la comprensin de los mismos. La facilidad de
comprensin es muy importante si, como a menudo sucede, un algoritmo tiene
que modificarse (particularmente por personas distintas a sus autores).
5) Una vez que se ha diseado un mdulo se puede incorporar en cualquier
algoritmo que lo necesite. Es por lo tanto posible construir una "biblioteca" de
48
ALGORITMOS Y LENGUAJES
2.2 RECURSIN
Supongamos que deseamos expresar un algoritmo para calcular el producto de los N
primeros nmeros enteros (el factorial de N, N!). Una solucin sera
obtener valor de N
asignar a producto el valor 1
repetir para cada entero de 1 a N
multiplicar producto por entero
escribir producto
Este algoritmo emplea un bucle en el que los sucesivos nmeros enteros de 1 a N se iban
multiplicando. Un enfoque alternativo es utilizar el hecho de que el factorial de N es
simplemente el producto de N por el factorial de N-1.
factorial (N) =
N factorial (N - 1)
Esto es cierto para cualquier N que es mayor que 1. Ms an, factorial (1) = 1. De
aqu un posible algoritmo para calcular el factorial de N se expresa en el mdulo
siguiente:
mdulo factorial (N)
{Calcula el factorial de N para cualquier entero N > 0}
si N = 1
entonces la respuesta es 1
si no multiplicar N por factorial (N - l)
La ltima lnea del mdulo se tiene que ejecutar otra vez pero con los parmetros
actuales con un valor de una unidad menor. La Figura 2.2 ilustra la ejecucin del mdulo
cuando N = 3. Se observa como el clculo de factorial(3) contiene el clculo de
factorial(2) que a su vez necesita factorial(1). Las tres llamadas a la funcin
factorial representan las tres ejecuciones del mdulo que se necesitan.
49
50
ALGORITMOS Y LENGUAJES
Paso 1
Paso 2
Paso 3
El algoritmo es claramente recursivo, puesto que describe cmo invertir una secuencia
de letras en funcin de como invertir una secuencia de letras ligeramente ms corta. En
cada llamada recursiva se quita una letra de la secuencia a invertir, simplificando as
progresivamente la entrada del algoritmo.
invertir "roma"
si "roma" contiene una letra
entonces .......
si no quitar la letra "r"
invertir "oma"
si "oma" contiene una letra
entonces .......
si no quitar la letra "o"
invertir "ma"
si "ma" contiene una letra
entonces .......
si no quitar la letra "o"
invertir "a"
si "a" contiene una letra
entonces
escribirla
si no .......
aadir "m"
aadir "o"
aadir "r"
am
amo
amor
En el caso lmite, cuando la secuencia tiene solamente una letra, se proporciona una
rutina de escape de forma que para invertir una nica letra slo se necesita escribirla. El
algoritmo completo para invertir una secuencia de letras es:
51
La Figura 2.3 ilustra la ejecucin del mdulo cuando la entrada es la palabra roma. Se
observan las sucesivas llamadas al mdulo, y la salida acumulativa de cada llamada se
muestra a la derecha de la llamada correspondiente.
Los dos algoritmos recursivos que hemos visto se pueden reemplazar por dos algoritmos
iterativos, lo que sugiere que la recursin es simplemente una iteracin expresada de otra
forma. En cierto sentido esta afirmacin es cierta y puede demostrarse que para
cualquier algoritmo que utiliza recursin existe uno equivalente expresado en forma
iterativa. Sin embargo, un algoritmo recursivo para describir un proceso particular es
mucho ms conciso que su contrapartida iterativa y muy a menudo es bastante ms
sencillo de obtener y comprender.
Veamos otros dos ejemplos.
El primero es un algoritmo recursivo que es ms conciso que su equivalente iterativo. Es
una versin recursiva del algoritmo de Euclides para determinar el mximo comn
divisor (MCD) de dos nmeros enteros positivos; la versin iterativa de este algoritmo ya
la hemos explicado. Recordemos que:
MCD (x,y) = MCD (y, resto de x/y)
52
ALGORITMOS Y LENGUAJES
Obsrvese que la ejecucin recursiva del algoritmo termina cuando y se reduce a cero, en
cuyo caso el resultado es x. La Figura 2.4 ilustra la ejecucin del algoritmo para
determinar el MCD de 24 y 9.
Calcular MCD(24, 9)
si 9 = 0
entonces .........
si no calcular MCD (9, 6)
si 6 = 0
entonces .........
si no calcular MCD (6, 3)
si 3 = 0
entonces .........
si no calcular MCD (3, 0)
si 0 = 0
entonces
la respuesta es 3
si no .........
Figura 2.4 Clculo del MCD de 24 y 9
El segundo ejemplo es una tarea para la que es ms fcil proponer un algoritmo recursivo
que uno iterativo. El ejemplo se conoce popularmente como las "Torres de Hanoi". De
acuerdo con la leyenda una orden de monjes budistas en Hanoi ha estado ocupada
durante muchos aos en la tarea siguiente: Los monjes tienen tres barras verticales y un
conjunto de 64 discos circulares de diferentes tamaos; cada disco tiene un agujero en el
centro que le permite deslizarse por cualquiera de las barras. Inicialmente los discos
estaban todos colocados en una nica barra, uno encima de otro en orden de mayor a
menor tamao, formando una torre tal como se muestra en la Figura 2.5.
La tarea que los monjes se haban fijado era transferir esta torre original a una de las
otras barras, moviendo solamente un disco cada vez y asegurando que nunca un disco
descansa encima de uno de menor tamao. Como la estrategia de mover los discos no es
obvia, y un falso movimiento poda echar a perder muchos aos de trabajo, lo monjes
necesitaban claramente seguir fijamente un algoritmo que describe como lograr su
objetivo. Tal algoritmo se puede desarrollar como sigue:
53
64 discos
Supongamos que la barra que soporta la torre original se llama A, la barra a la que se va
a mover la torre es B y la otra C. Dadas las reglas que gobiernan el movimiento de los
discos, es obvio que la nica forma por la cual el disco del fondo de la torre original se
puede mover para formar la base de la nueva torre es quitar los otros 63 discos.
El nico sitio para poner estos 63 discos es la tercera barra, de manera que un algoritmo
para transferir la torre completa de la barra A la barra B es:
transferir los primeros 63 discos de la barra A a la C
mover el ltimo disco de la barra A a la B
transferir los 63 discos de la barra C a la B
Este algoritmo describe la tarea de transferir 64 discos entre dos barras en funcin de la
tarea de transferir 63 discos entre dos barras. Anlogamente, la tarea de transferir 63
discos entre dos barras se puede describir en trminos de la transferencia de 62 discos
entre dos barras, etc. Generalizando, un algoritmo para transferir N discos desde una
barra llamada "fuente" a una barra llamada "destino" (dada una tercera barra llamada
"espacio de trabajo") es:
transferir N - 1 discos desde "fuente" a "espacio de trabajo"
mover 1 disco desde "fuente" a "destino"
transferir N - 1 desde "espacio de trabajo" a "destino"
54
ALGORITMOS Y LENGUAJES
cuando solamente hay un nico disco para transferirse entre barras: en este caso todo lo
que hay que hacer es cogerlo y llevarlo a su sitio.
Un algoritmo completo para transferir N discos desde " fuente" a "destino" es:
mdulo mover-torre (N, fuente, destino, espacio de trabajo)
{mueve una torre de N discos desde el disco "fuente" al
disco "destino", utilizando el disco "espacio de trabajo"}
si N =
Cunto tiempo le llevara a los monjes realizar su tarea? La ejecucin del algoritmo con
N = 64 resulta en dos ejecuciones con N = 63, cada uno de los cuales necesita dos
ejecuciones con N = 62, etc. De este razonamiento se sigue que la transferencia de la
torre completa requiere 264 - 1 ejecuciones del algoritmo. Como durante cada ejecucin
se mueve un disco, el nmero total de movimientos es 264 - 1. Si los monjes pudieran
mover un disco cada segundo y nunca cometiesen un error, el tiempo tomado para
transferir la torre completa sera de 600.000.000.000 aos!. Ms an se puede probar
que no existe un algoritmo mas rpido que el que acabamos de presentar.
La Figura 2.6 ilustra la ejecucin de este mdulo cuando la torre original contiene
solamente 3 discos y se van a transferir de la barra "A" a la barra " B".
transferir 3 discos de "A" a "B"
si 3 = 1
entonces .........
si no transferir 2 discos de "A" a "C"
si 2 = 1
entonces .........
si no transferir 1 disco de "A" a "B"
si 1 = 1
entonces mover disco de "A" a "B"
si no .........
mover disco de "A" a "C"
55
"C"
si 1 = 1
entonces mover disco de "B" a "C"
si no .........
mover disco de "A" a "B"
transferir 2 discos de "C" a
"B"
si 2 = 1
entonces .........
si no transferir 1 disco de "C" a "A"
si 1 = 1
entonces mover disco de "C" a "A"
si no .........
mover disco de "C" a "B"
transferir 1 disco de "A" a
"B"
si 1 = 1
entonces mover disco de "A" a "B"
si no .........
Figura 2.6 Ejecucin del algoritmo de las torres de Hanoi con 3 discos
En estos momentos el lector puede estar formndose una idea de cul es la estrategia
para formular algoritmos recursivos.
El primer elemento de la estrategia es la determinacin de cmo el proceso a realizar se
puede expresar en trmino de procesos similares que difieren del original solamente por
tener una entrada que es en algn sentido ms simple (por ejemplo, un nmero ms
pequeo o una secuencia ms corta).
El segundo elemento es asegurarse que hay un caso lmite en el cul la entrada es tan
simple que el proceso se puede ejecutar sin necesidad de recurrir a ms llamadas
recursivas. El caso lmite entonces acta como una rutina de escape de la recursin. Esta
estrategia es la que hemos aplicado a todos los ejemplos anteriores.
Vamos a aplicarla para finalizar al desarrollo de un algoritmo recursivo para clasificar
una lista de nombres en orden alfabtico (este mismo algoritmo lo hemos desarrollado en
una versin iterativa en el tema anterior).
56
ALGORITMOS Y LENGUAJES
Es fcil ver que las llamadas recursivas pueden cesar cuando la parte que se va a ordenar
se reduce a un nico nombre en cuyo caso no hay nada que hacer. De aqu que el
algoritmo para una lista de N nombres es:
mdulo ordenar (lista)
{Ordena la lista dada de N nombres en orden alfabtico}
si N > 1
entonces
La accin del algoritmo sobre una lista de siete nombres (la misma que utilizamos para
ilustrar el algoritmo de ordenacin iterativo) se muestra en la Figura 2.7.
Juan
Juan
Luis
Felipe
Arturo
Samuel
Jos
Mara
Juan
Luis
Felipe
Arturo
Samuel
Jos
Mara
Juan
Luis
Felipe
Arturo
Samuel
Jos
Luis
Felipe
Arturo
Samuel
Jos
Juan
Luis
Arturo
Felipe
Jos
Samuel
Arturo
Felipe
Juan
Luis
Jos
Mara
Samuel
Arturo
Felipe
Jos
Juan
Luis
Mara
Samuel
Mara
Figura 2.7 Acciones del algoritmo de ordenacin recursiva
La ltima lnea del algoritmo necesita un refinamiento antes de que la pueda ejecutar la
mayora de los procesadores.
57
2.3 PARALELISMO
Cada uno de los algoritmos que hemos visto hasta aqu se han construido bajo la
hiptesis de que solamente hay disponible un procesador para ejecutarlo. Esta hiptesis
est justificada para la mayora de los computadores actuales. Sin embargo los avances
recientes en la tecnologa han hecho posible fabricar ciertos procesadores muy baratos y
es por lo tanto econmicamente posible asignar algunos procesadores a una nica tarea.
Una de las ventajas potenciales de hacerlo as es que la tarea se puede completar ms
rpidamente que si se utiliza un nico procesador.
Esta mejora en velocidad se puede conseguir solamente si se puede dividir el proceso en
subprocesos que ejecutan cada uno de los procesadores disponibles. Esto implica que el
algoritmo que describe el proceso total se debe particionar en una serie de componentes,
cada uno de los cuales define el subproceso realizado por un procesador individual. Los
componentes del algoritmo se ejecutan simultneamente por sus respectivos
procesadores, de forma que el tiempo tomado para ejecutar el algoritmo no es mayor
que el necesitado para completar su componente ms lenta. Esta forma de ejecucin se
llama paralelismo o concurrencia y un algoritmo cuyos componentes se pueden
ejecutar de esta forma se conoce como un algoritmo paralelo (en oposicin a los
algoritmos secuenciales cuyos pasos se ejecutan uno cada vez)
Como un ejemplo simple de un algoritmo paralelo consideraremos el proceso de restar
una lista de los precios de compras para varios artculos de una lista con los precios de
ventas de los mismos. El resultado ser una lista de los beneficios (o prdidas) de cada
artculo. Si hay N artculos, un algoritmo secuencial simple es:
mdulo beneficio-secuencial
{Calcula una lista de beneficios a partir de las listas de
precios de compra y venta}
comenzar con el primer elemento de cada lista
repetir N veces
restar precio de compra del precio de venta
colocar la respuesta en la lista de beneficios
considerar el prximo artculo en cada lista
La mayor parte del tiempo gastado en ejecutar este algoritmo se pasa en el cuerpo del
bucle. Como el cuerpo se ejecuta N veces, el tiempo necesitado para ejecutar el algoritmo
58
ALGORITMOS Y LENGUAJES
Tambin en este caso la mayor parte del tiempo para ejecutar este algoritmo se pasa
dentro del bucle. As pues, el tiempo de ejecucin es proporcional a N.
La base de un algoritmo paralelo se puede ver en la Figura 2.8 que demuestra como se
pueden sumar por parejas los nmeros en la fila. La primera etapa en el algoritmo es
59
agrupar los nmeros por parejas y calcular sus sumas. Las sumas se pueden hacer en
paralelo, a condicin de que el numero de procesadores disponibles es al menos de N/2
(de forma ms precisa, la parte entera de N/2).
3
11
13
15
28
Figura 2.8 Suma de nmeros por parejas
Las sumas resultantes pueden otra vez sumarse por parejas, en esta etapa solamente se
necesitan N/4 procesadores. La suma en paralelo de parejas de nmeros contina hasta
que resulta una suma simple. Como el nmero de parejas a sumar se reduce a la mitad en
cada etapa, el nmero de etapas necesarias es log2N. El nmero de procesadores
necesitados en cada etapa es tambin la mitad de la etapa anterior, por lo que el nmero
mximo de N/2 lo ser en la primera etapa.
Si los procesadores se numeran de 1 a N/2 y los nmeros a sumar en la fila se
representan por num[l], num[2], ......, num[N], el algoritmo ejecutado por el procesador
i-simo es:
mdulo suma-paralela(i)
{Algoritmo de suma ejecutada por el procesador i-simo}
repetir log2 N veces
asignar a num[i] el valor num[2i - 1] + num[2i]
La ejecucin paralela de este algoritmo por todos los procesadores se ilustra en la Figura
2.9. Obsrvese como las sumas en etapas sucesiva (se muestran con una lnea por
debajo) se acumulan a la izquierda de la fila, el resto queda sin modificar.
60
ALGORITMOS Y LENGUAJES
fila original
11
15
13
28
13
Como la salida de cada etapa forma la entrada a la siguiente, ninguna etapa puede
comenzar hasta que ha finalizado la etapa previa. Esto implica que todos los
procesadores deben operar con la misma velocidad o al menos esperar antes de
comenzar ejecuciones sucesivas de los cuerpos de sus bucles repetir. Es decir, los
procesadores deben sincronizarse entre s.
Como todos los procesadores operan sncronamente el tiempo empleado para sumar la
fila completa de nmeros es el mismo que el tomado por cada procesador para ejecutar
el algoritmo suma-paralela. Este tiempo es proporcional a log2N, por lo que el algoritmo
paralelo es ms rpido que el secuencial por un factor de N/log2N. La implicacin
prctica es que se pueden obtener aumentos de velocidad de 10 a 100 para valores de N
entre 100 y 1000.
Como ejemplo final de paralelismo desarrollaremos un algoritmo de ordenacin en
paralelo que hace uso del algoritmo anterior de suma-paralela. Supongamos que
deseamos ordenar una lista de N nombres en orden alfabtico (problema que ya hemos
venido tratando). De lo que ya sabemos la esencia de la ordenacin es la comparacin (y
posible intercambio) de parejas de nombres. En ese algoritmo, que fue diseado para un
nico procesador, las comparaciones eran necesariamente realizadas una cada vez.
Dado un nmero suficiente de procesadores, una manera obvia de acelerar el proceso de
ordenacin es efectuar todas las comparaciones al tiempo, esto es, comparar
simultneamente cada nombre de la lista con los restantes, determinando as para cada
uno cuntos le preceden alfabticamente. Como hay N nombres a comparar con todos los
otros, el nmero de procesadores que se necesitan es N2.
Durante la primera fase del proceso de ordenacin la tarea de cada procesador es
comparar dos nombres, registrando el resultando en uno de los cuadrados de una rejilla
61
Todos los procesadores realizan este algoritmo en paralelo, cada uno utilizando
diferentes valores de i y j. La matriz resultante para la lista:
Juan, Luis, Samuel, Felipe, Arturo, Jos, Mara
Juan
Luis
Felipe
Arturo
Samuel
Jos
Mara
Posicin
Juan
Luis
Samuel
Felipe
Arturo
Jos
Mara
Al final de esta fase el nmero de 1's en la fila i-sima de la matriz indica cuantos
nombres (incluyendo l mismo) preceden alfabticamente al nombre i-simo en la lista.
Esto a su vez indica dnde debera estar en la lista ya ordenada el nombre i-simo. Por
62
ALGORITMOS Y LENGUAJES
ejemplo, la matriz de la Figura 2.10 tiene cinco 1's en la segunda fila, indicando que
cinco nombres (incluyendo a l mismo) preceden al nombre correspondiente en la lista
original (Luis), y por lo tanto que Luis debera ocupar el quinto lugar en la lista
ordenada. Estamos suponiendo por simplicidad que todos los nombres son diferentes; si
este no es el caso el algoritmo necesita una ligera modificacin para tratar la posibilidad
de nombres idnticos.
Por lo tanto la segunda fase del algoritmo consiste en sumar el nmero de 1's en cada fila
de la matriz, determinando as la posicin correcta de cada nombre en la lista. La suma
de cada fila se puede realizar por medio del algoritmo paralelo ya desarrollado, cada fila
requiere N/2 procesadores y un tiempo de clculo proporcional a log2N.
Las sumas resultantes de la segunda fase del algoritmo se utilizan para determinar la
posicin de cada nombre en la lista ordenada. Si la suma de la fila i-sima es k, entonces
el nombre i-simo en la lista original deber ocupar la posicin k-sima en la lista
ordenada. La fase final del algoritmo es por lo tanto simplemente mover cada nombre a
su posicin correcta en la lista ordenada. Utilizando N procesadores todos los nombres se
pueden mover en paralelo, de forma que el tiempo tomado para ejecutar esta fase no es
mayor que el necesitado para mover un nombre simple, y es independiente de N.
La nica fase del algoritmo cuyo tiempo de ejecucin depende de N es la segunda, con
una duracin proporcional a log2N , de donde el tiempo para el algoritmo completo
podemos decir tambin que es proporcional a log2N. Este valor se puede comparar con
el algoritmo secuencial dado anteriormente; por ejemplo, los tiempos de ejecucin de los
algoritmos de ordenacin de las secciones 1.7 (del Tema 1) y 2.1 son proporcionales a
N2 y Nlog2N respectivamente. La diferencia dramtica en velocidad entre los algoritmos
secuencial y paralelo se puede ver en la Figura 2.11 que tabula los valores de log2N,
Nlog2N y N2 para distintos valores de N.
Por supuesto, el incremento en velocidad no es sin coste. El algoritmo de ordenacin
secuencial utiliza solamente un nico procesador, mientras el algoritmo paralelo que
acabamos de describir requiere N2/2 procesadores. Es posible lograr el mismo aumento
de velocidad utilizando solamente Nlog2N procesadores. Sin embargo en la actualidad no
se conoce ninguna forma de hacerlo con menos procesadores. As pues el mejor
algoritmo paralelo conocido da un incremento de velocidad de N veces al costo de un
aumento de Nlog2N en el nmero de procesadores.
63
log2N
Nlog2N
N2
10
0,000003 seg.
0,00003 seg.
0,0001 seg.
100
0,000007 seg.
0,0007 seg.
0,01 seg.
1000
0,00001 seg.
0,01 seg.
1 seg.
10000
0,000013 seg.
0,13 seg.
1,7 min.
100000
0,000017 seg.
1,7 seg.
2,8 horas
2.4 ACTIVIDADES
1. Describa un algoritmo de su eleccin que utilice el concepto de modularidad.
2. Describa un algoritmo de su eleccin que utilice el concepto de recursin.
3. Describa un algoritmo de su eleccin que utilice el concepto de paralelismo.
64
ALGORITMOS Y LENGUAJES
3.1 INTRODUCCIN
Los dos temas anteriores se han concentrado sobre las estructuras de control; esto es,
sobre las construcciones que se pueden utilizar para controlar el orden y circunstancias
en las cuales se ejecutan los pasos individuales de un algoritmo. La eleccin de las
estructuras de control apropiadas (secuencia, seleccin o iteracin) es una parte esencial
del desarrollo de un algoritmo, pero no se puede realizar este sin considerar las
informaciones o datos que el algoritmo manipula.
En general, los datos manipulados por un algoritmo no son simplemente una coleccin
arbitraria de elementos no relacionados, sino que consisten en grupos de informacin que
estn de alguna forma relacionados unos con otros. Como ejemplo, consideremos un
algoritmo que se utiliza para el mantenimiento de la informacin personal de los
empleados de un compaa. Los datos manipulados por el algoritmo consisten en
nombres, direcciones, edades, puestos de trabajos etc.
Estos elementos de datos no son meramente una masa amorfa de informacin, sino que
poseen relaciones lgicas entre si. Una relacin obvia entre un nombre particular y su
direccin, edad y puesto de trabajo es que todos estos elementos describen a la misma
persona.
Personal administrativo
Joaqun Snchez
27
Lpez de Hoyos 34
Gerente
42
Mara Prez
65
Joaqun
Snchez
Lpez de
Hoyos 34
42
Mara
Prez
Princesa 17
27
Gerente
Personal
administrativo
Benjamn Embajadores 23
Gonzlez
Tornero
Los datos pueden por lo tanto verse no como una jungla de elementos sin relacionar (tal
como se muestra en la Figura 3.1), sino como una coleccin de registros, cada uno de lo
cuales contiene toda la informacin respecto a un empleado particular (ver Figura 3.2).
Jos
Lpez
Juan
Director General
Lesmes Comercializacin
Presidente
Figura 3.3 Relacin lgica entre registros que reflejan la estructura de una compaa
Estos registros pueden as mismo tener conexiones lgicas entre ellos reflejando las
relaciones que existen entre las personas que describen. Por ejemplo, determinados
empleados (y por lo tanto los registros que los describen) pueden estar relacionados por
la condicin de estar trabajando en la mima seccin de la compaa o un empleado puedo
estar relacionado a algn otro en virtud de ser su supervisor inmediato (ver Figura 3.3).
Los datos que se organizan para reflejar las relaciones lgicas entre sus elementos se
66
ALGORITMOS Y LENGUAJES
dicen que estn estructurados; los datos elementales y sus relaciones todos
conjuntamente forman una estructura de datos.
67
en el tema anterior. Cada nmero se identifica por su posicin (1), (2), .... ,
(N) en la fila, de una forma anloga con el uso de subndices en matemticas.
2. Una cola es una secuencia de longitud variable en la que los elementos se
aaden siempre en un extremo y se extraen por el otro extremo. Se sigue pues
que el orden en que los elementos se quitan es el mismo que en el que se
aaden. Una cola es una estructura de datos particularmente til para elementos
que van a ser manipulados sobre la base de que el primero que llega es el
primero en ser atendido.
3. Una pila es una secuencia de longitud variable en la cual los elementos se
aaden y se extraen por el mismo extremo. As el orden en el que los
elementos se eliminan es el inverso de como llegan. (Una pila de platos es un
ejemplo sencillo que refleja este tipo de estructura; el ltimo plato colocado en
la pila es el primero que tiene que ser extrado de ella).
Otro tipo de estructura de datos es el rbol, un ejemplo del cual se muestra en la Figura
3.4 (los rboles en informtica crecen hacia abajo!).
68
ALGORITMOS Y LENGUAJES
Oracin
Sintagma
Nominal
Sintagma
Predicativo
Sintagma
Nominal
Sintagma
Preposicional
Sintagma
Nominal
Determinante Nombre
Mi
hermano
el
lee
peridico
en
la
cama
dibuja-polgono
mover
calcular nmero de
vueltas necesitadas
girar a izquierda
Figura 3.5 rbol de los sucesivos refinamientos del mdulo dibuja -cuadrado del tema 2
69
70
ALGORITMOS Y LENGUAJES
Algoritmo
Estructura
de datos
de entrada
Estructura
de datos
intermedia
Estructura
de datos
de salida
71
disponibles y se pueden volver a usar. Por lo tanto, cuando A ( D) se hacen tan grandes
como L (apuntando al final de la lista) en el siguiente incremento lo volvemos a poner a
1. De esta forma D persigue a A alrededor de la lista. Surgen condiciones de error si D
alcanza e intenta pasar a A (intento de extraer elementos no almacenados) o si A se hace
tan grande que alcanza a D (intento de poner ms de L - 1 elementos en la cola. Por
qu solamente L - 1?).
3.3.2 Listas enlazadas
La mayor dificultad en utilizar bloques contiguos de memoria para el almacenamiento de
listas es que las adiciones y las supresiones en la mitad de la misma son difciles y
debemos poner una acotacin fija al tamao de la lista. Si tenemos solamente una lista,
podemos siempre asignar toda la memoria disponible a ella, pero esto es malgastarla ya
que (en cualquier momento) podemos estar utilizando solamente una pequea parte de
esa memoria. Si tenemos algunas listas, debemos asignar algn lmite a cada una de ellas.
Sin embargo, hay otra forma de parcelar la memoria que permite mucha mayor
flexibilidad. En este esquema, cada nodo dentro de una lista contiene, adems del
elemento almacenado, la direccin (o subndice) del prximo elemento en la lista. Cada
nodo se puede almacenar en una posicin arbitraria de la memoria. No obstante si
almacenamos en un registro donde est el primer nodo, todos los otros se pueden
encontrar siguiendo el camino a lo largo de estos punteros. El primer nodo nos dice
donde est el segundo nodo, el segundo donde est el tercero, etc. (comparar las Figuras
3.7, 3.8 y 3.9). En el esquema secuencial mantenamos ndices independientes de la lista
para decirnos donde estbamos buscando en la lista. Para una lista enlazada,
almacenamos punteros a posiciones de memoria que contienen las direcciones de los
nodos bajo consideracin.
72
ALGORITMOS Y LENGUAJES
Direccin
Nombre
1043
LISTA[1]
+253
1044
LISTA[2]
-16
1045
LISTA[3]
1046
LISTA[4]
+37
1047
LISTA[5]
+172
1048
LISTA[6]
-3
En la Figura 3.8 el smbolo representa el puntero nulo y significa que se est al final de
la lista.
Direccin
Dato
Puntero
2013
-3
2014
+37
3108
2378
+253
3107
Puntero
de lista
Direccin
Dato
Puntero
2404
2014
3107
-16
2404
3108
+172
2013
2378
Figura 3.8 Lista almacenada de forma arbitraria en memoria con enlace entre los elementos
73
2378
Direccin
2378
+253
3107
3107
-16
2404
2404
2014
2014
+37
3108
3108
+172
2013
2013
-3
Dato
Puntero
de lista
Puntero
Figura 3.9 La misma lista enlazada de la Figura 3.8, con los nodos apareciendo en el
orden en que lo hacen en la lista en lugar de por su posicin en memoria.
En el esquema secuencial, habramos tenido que mover todos los nodos ms all del
nodo k un lugar hacia arriba para llenar el hueco dejado por la supresin del nodo k (ver
Figura 3.11).
Por otra parte, operaciones tales como encontrar el nodo j-simo son mucho ms lentas
en una lista enlazada. En la lista secuencial, simplemente habramos accedido a LISTA
(j). En el esquema enlazado, debemos comenzar en el primer nodo y seguir los punteros
74
ALGORITMOS Y LENGUAJES
2378
Direccin
2378
+253
3107
3107
-16
2404
2404
2014
2014
+37
3108
3108
+172
2013
2013
-3
Dato
Puntero
de lista
Puntero
Figura 3.10 Lista enlazada de las Figuras 3.8 y 3.9 pero con el tercer nodo suprimido
75
Direccin
Nombre
1043
LISTA[1]
+253
1044
LISTA[2]
-16
1045
LISTA[3]
+37
1046
LISTA[4]
+172
1047
LISTA[5]
-3
1048
LISTA[6]
Figura 3.11 La misma lista secuencial de la Figura 3.7 pero con el tercer elemento de la
lista suprimido y todos los elementos restantes movidos u n lugar hacia arriba
Hay ocasiones, sin embargo, que se desea mantener una lista enlazada de un tamao fijo
y hacerla sin asignacin dinmica (por ejemplo, cuando sabemos que una lista nunca va a
necesitar tener ms de n nodos de longitud, y que la mayor parte del tiempo su tamao
no ser mucho menor que n). En tales casos nos gustara que nuestros punteros fueran
capaces de ir de forma conveniente desde el ltimo nodo de la lista hacia atrs al
primero.
Una forma sencilla de realizar esto es enlazar el ltimo nodo con el primero. Esto, en
efecto, completa un crculo de nodos, cada uno apuntando al siguiente. Una estructura
de este tipo se denomina una lista circular (si en la Figura 3.8 el campo "puntero" de la
posicin 2.013 contuviese 2.378 en lugar de la lista sera circular).
Una generalizacin simple de la lista enlazada es la lista doblemente enlazada, donde
cada nodo contiene un puntero a su sucesor (como antes) y otro a su predecesor. En una
lista circular doblemente enlazada, no solamente el ltimo nodo apunta hacia el
primero, sino tambin de forma inversa (ver Figura 3.12). Cuales son las ventajas y
desventajas de las listas doblemente enlazadas?.
76
ALGORITMOS Y LENGUAJES
Puntero
de lista
Puntero
de lista
Puntero de
lista izquierdo
Puntero
de lista
Puntero de
lista derecho
77
Figura 3.13 muestra dos rboles binarios ordenados alfabticamente; en la Figura 3.13b,
por ejemplo, Juan sigue alfabticamente a cada nombre de su subrbol izquierdo y
precede a todos los nombres en su subrbol derecho. Lo mismo se aplica a cualquier otro
nodo en el rbol. Obsrvese que no todos los nodos necesitan tener completas las dos
ramas; el nmero de ramas depende de la distribucin alfabtica de los nombres en el
rbol y de la forma en que se construy el rbol (que vamos a exponer a continuacin).
Juan
Felipe
Juan
Luis
Felipe
Arturo
Luis
Samuel
Jos
Mara
a)
b)
78
ALGORITMOS Y LENGUAJES
un
rbol
binario
ordenado
partir
de
una
El proceso de aadir un nombre al rbol (la ltima lnea del algoritmo anterior) se puede
describir mediante un mdulo recursivo. Si todava no existe el rbol (est vaco) se crea
un nuevo rbol con el nombre como su raiz y nico nodo. Si el rbol existe el nombre
que se aade se compara con el nombre en la raz. Si precede alfabticamente al nombre
que hay en la raz entonces se debe aadir al subrbol izquierdo, en otro caso se debe
aadir al subrbol derecho. El mdulo para aadir un nombre es:
mdulo aadir-nombre (nombre, A)
{aade nombre al rbol binario ordenado A}
si A est vaco
entonces crear un nuevo subrbol que tenga como raz nombre
si no si nombre precede al nombre de la raz de A
entonces aadir-nombre (nombre, subrbol izquierdo A)
si no aadir-nombre (nombre, subrbol derecho A)
Obsrvese que la recursin eventualmente cesa puesto que el rbol que es el parmetro
actual del mdulo se hace ms pequeo con las sucesivas llamadas. Cuando se hace tan
pequeo como para estar vaco se aade el nuevo nombre como raz (y nico nodo) de
un nuevo subrbol y termina. En la Figura 3.14 se muestra la adicin del nombre Jos a
un rbol construido parcialmente. En sucesivas llamadas recursivas de aadir-nombre
Jos se aade al subrbol izquierdo de Juan y al subrbol derecho de Felipe. Como
este ltimo subrbol est vaco se crea un nuevo subrbol con Jos como su nico nodo.
Juan
Felipe
Arturo
Luis
Jos
Samuel
79
un
rbol
binario
ordenado
partir
de
una
lista de nombres L}
comenzar al principio de L
mientras L tenga nombre hacer
aadir-nombre (prximo nombre, A )
todos
los
nodos
del
rbol
binario
en
orden
de
izquierda a derecha}
si A no est vaco
entonces
80
ALGORITMOS Y LENGUAJES
3.5 ACTIVIDADES
1. Elija un conjunto de datos que se puedan tratar favorablemente con una estruct ura de
array.
2. Elija un conjunto de datos que se puedan tratar favorablemente con una estructura de
cola.
3. Elija un conjunto de datos que se puedan tratar favorablemente con una estructura de
pila.
4. Elija un conjunto de datos que se puedan tratar favorablemente con una estructura de
rbol.
5. Algoritmo de insercin de un elemento en una cola .
6. Algoritmo de insercin de un elemento en una pila .
81
82
ALGORITMOS Y LENGUAJES
83
CDIGO ASCII
Valor Carcter
decimal
NUL
0
SOH
1
STX
2
ETX
3
EOT
4
ENQ
5
ACK
6
BEL
7
BS
8
HT
9
LF
10
VT
11
FF
12
CR
13
SO
14
SI
15
DLE
16
DC1
17
DC2
18
DC3
19
DC4
20
NAK
21
SYN
22
ETB
23
CAN
24
EM
25
SUB
26
ESC
27
FS
28
GS
29
RS
30
US
31
84
Valor Carcter
decimal
32
!
33
34
#
35
$
36
%
37
&
38
'
39
(
40
)
41
*
42
+
43
,
44
45
.
46
/
47
0
48
1
49
2
50
3
51
4
52
5
53
6
54
7
55
8
56
9
57
:
58
;
59
<
60
=
61
>
62
?
63
Valor Carcter
decimal
@
64
A
65
B
66
C
67
D
68
E
69
F
70
G
71
H
72
I
73
J
74
K
75
L
76
M
77
N
78
O
79
P
80
Q
81
R
82
S
83
T
84
U
85
V
86
W
87
X
88
Y
89
Z
90
[
91
\
92
]
93
^
94
_
95
Valor Carcter
decimal
`
96
a
97
b
98
c
99
d
100
e
101
f
102
g
103
h
104
i
105
j
106
k
107
l
108
m
109
n
110
o
111
p
112
q
113
r
114
s
115
t
116
u
117
v
118
w
119
x
120
y
121
z
122
{
123
|
124
}
125
~
126
127
DEL
ALGORITMOS Y LENGUAJES
Valor Carcter
decimal
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
Valor Carcter
decimal
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
Valor Carcter
decimal
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
Valor Carcter
decimal
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
85
CDIGO ASCII
86