Sei sulla pagina 1di 81

Apuntes de algoritmos

Apuntes de algoritmos

Contenido

1. Algoritmos y Programas ............................................................... 3


1.1. Computadoras y lenguaje de programación ......................................................3
1.2. Resolución de problemas...................................................................................5
1.3. Datos ..................................................................................................................8
1.4. Representación de algoritmos .........................................................................13
2. Estructura general de un programa........................................... 17
2.1. Estructura general de un algoritmo en pseudocódigo .....................................17
2.2. Operación de asignación .................................................................................17
2.3. Conversión de tipos .........................................................................................19
2.4. Contadores.......................................................................................................20
2.5. Acumuladores ..................................................................................................21
2.6. Interruptores .....................................................................................................21
3. Estructura general de un programa........................................... 22
3.1. Programación estructurada ..............................................................................22
3.2. Estructura secuencial .......................................................................................22
3.3. Estructura selectiva ..........................................................................................23
3.4. Estructura repetitiva .........................................................................................24
3.5. Estructura anidada ...........................................................................................27
4. Subalgoritmos, funciones y procedimientos............................ 29
4.1. Programación modular .....................................................................................29
4.2. Funciones.........................................................................................................29
4.3. Procedimientos.................................................................................................30
4.4. Estructura general de un algoritmo ..................................................................32
4.5. Parámetros de los subalgoritmos.....................................................................32
4.6. Variables locales y globales .............................................................................34
5. Tipos de datos estructurados .................................................... 35
5.1. Datos estructurados .........................................................................................35
5.2. Arreglos ............................................................................................................35
5.3. Registros ..........................................................................................................39
5.4. Cadenas de caracteres ....................................................................................40
6. Introducción a la programación orientada a objetos............... 43
6.1. Objeto...............................................................................................................43
6.2. Clase ................................................................................................................44
6.3. Relación entre clase y objeto ...........................................................................44
6.4. Atributos ...........................................................................................................45
6.5. Métodos............................................................................................................45
6.6. Mensaje............................................................................................................46

1
Apuntes de algoritmos

6.7. Diagrama de clases .........................................................................................46


6.8. Relaciones entre clases ...................................................................................47
7. Fundamentos del enfoque orientado a objeto.......................... 50
7.1. Abstracción.......................................................................................................50
7.2. Encapsulamiento (ocultamiento de información) .............................................50
7.3. Modularidad......................................................................................................51
7.4. Herencia ...........................................................................................................51
7.5. Polimorfismo.....................................................................................................51
8. Ejemplos....................................................................................... 53
8.1. Expresiones......................................................................................................53
8.2. Diagramas de flujo ...........................................................................................53
8.3. Estructuras de selección ..................................................................................54
8.4. Estructuras de repetición .................................................................................56
8.5. Funciones y procedimientos ............................................................................58
8.6. Arreglos ............................................................................................................62
8.7. Registros ..........................................................................................................67
8.8. Cadenas ...........................................................................................................70
8.9. Definición de una clase ....................................................................................73
8.10. Asociación (ver algoritmo del Ejemplo 8.9.)...................................................74
8.11. Herencia, clase abstracta y asociación..........................................................75
8.12. Polimorfismo, herencia, clase abstracta y asociación ...................................77
Bibliografía ....................................................................................... 81

2
Apuntes de algoritmos

1. Algoritmos y Programas

1.1. Computadoras y lenguaje de programación

1.1.1. Computador u ordenador


Dispositivo electrónico utilizado para procesar datos en forma automática y obtener resultados los cuales
pueden a su vez ser organizados y analizados para producir información. El computador está conformado
por una parte física llamada hardware y por una parte lógica o de programas llamada software.

1.1.2. Datos
Es una representación de hechos, conceptos o instrucciones, organizados de manera que se puedan
procesar, interpretar o comunicar por medios humanos o automáticas. Los datos, son por ejemplo,
representaciones de las características de una persona, objeto, concepto o hecho.
Los datos se pueden introducir en el computador como entrada y se procesan para producir resultados e
información de salida.

1.1.3. Hardware
Es el conjunto de componentes físicas que forman un computador.
Como ejemplo tenemos los chips de los procesadores (CPU, procesadores matemáticos, procesadores de
video), las tarjetas (la tarjeta madre, las tarjetas de memoria como la memoria RAM, las tarjetas de video,
red, sonido), las unidades de almacenamiento (disco duro, disquete, cd, dvd, pen drive), los dispositivos
periféricos (ratón, teclado, monitor, impresora)

1.1.4. Software
Son los programas que permiten utilizar los recursos del computador. Programación, soporte lógico, parte
no-mecánica o no-física de un sistema. Es un conjunto de programas y procedimientos que se incluyen en
un computador o equipo con el fin de hacer posible el su uso eficaz de dicha máquina. Son las instrucciones
responsables de que el hardware (la máquina) realice su tarea.
Como ejemplo tenemos los sistemas operativos, el software de aplicación, el software utilitario y los
lenguajes de programación.

Sistema operativo
Software básico encargado de controlar diferentes procesos en el computador mediante tres grandes
funciones:
• Coordinar y manipular el hardware del computador: como los procesadores, la memoria, las impresoras,
las unidades de almacenamiento, el monitor, el teclado o el ratón;
• Organizar los archivos en diversos dispositivos de almacenamiento, como discos flexibles, discos duros,
Cds.
• Gestionar los errores de hardware y la pérdida de datos.

Software de aplicación
Programa informático diseñado para facilitar al usuario la realización de un determinado tipo de trabajo.
Algunas son aplicaciones desarrolladas “a la medida” que ofrecen una gran potencia y soluciones eficientes
ya que están exclusivamente diseñadas para resolver un problema específico. Son ejemplos de este tipo de

3
Apuntes de algoritmos

software los programas que realizan tareas concretas como manejo de nómina, análisis de estadísticas,
manejo de almacén, etc.

Software utilitario
Son programas que facilitan el uso del computador como herramienta para solucionar actividades generales
como la edición de textos o la digitalización de materiales. En muchos casos los programas utilitarios son
agrupados en paquetes integrados de software, por ejemplo el Microsoft Office o el OpenOffice, donde se
ofrece soluciones más generales, pero se incluyen varias aplicaciones (procesador de textos, de hoja de
cálculo, manejador de base de datos, correo electrónico, visor de imágenes, etc.).

Lenguajes de programación
Sirven para escribir programas que permitan la comunicación usuario/máquina y la soluciones de problemas
utilizando las ventajas, poder de cálculo, procesamiento y almacenamiento del computador.

Diferencias entre los tipos software


El software de aplicación se diferencia de un sistema operativo (que hace funcionar al ordenador), de una
utilidad (que realiza tareas de mantenimiento o de uso general) y de un lenguaje (con el cual se crean los
programas informáticos), en que suele resultar una solución informática para la automatización de tareas en
un área determinada (procesamiento de texto, edición de imágenes, estadística, manejo de
correspondencia, etc.).

1.1.5. Estructura funcional de un computador (arquitectura Von Neumann)


La arquitectura Von Neumann se refiere a las arquitecturas de computadoras que utilizan el mismo
dispositivo de almacenamiento para las instrucciones y para los datos (a diferencia de la arquitectura
Harvard). El término se acuñó en el año 1945, escrito por el conocido matemático John Von Neumann, que
propuso el concepto de programa almacenado.

Los ordenadores con arquitectura Von Neumann constan de las siguientes partes:

Memoria principal
Es el subsistema donde se almacenan temporalmente los datos e instrucciones que son utilizados por el
computador. Esta información está representada en una codificación binaria de 0 y 1. La memoria se divide
en celdas, donde cada celda tiene una dirección única, de tal forma que el contenido de ellas puede ser
buscado, extraído y utilizado.

4
Apuntes de algoritmos

Unidad central de proceso (CPU o Procesador)


Es el subsistema encargado de extraer las instrucciones y los datos en la memoria principal para realizar los
tratamientos u operaciones correspondientes. Está conformado por la Unidad de control y la Unidad lógico-
aritmética
• Unidad de control (UC). Se encarga de:
- Obtener de la memoria la próxima instrucción a utilizar o ejecutar.
- Decodificar la instrucción para determinar qué debe hacerse.
- Según la decodificación hecha, enviar el comando apropiado a la ALU, memoria o controlador de
entrada/salida para que realice la tarea.
• Unidad lógico-aritmética (ALU). Se encarga de realizar las operaciones aritméticas y comparaciones.

Dispositivo de entrada/salida
Es el subsistema que permite al computador interactuar con otros dispositivos, comunicarse con el mundo
exterior y almacenar los datos y programas en unidades permanentes, por ejemplo, el disco duro.
Está conformado por:
• Bus o unidades de intercambio. Permiten comunicar información entre los componentes del sistema,
los periféricos y el mundo exterior.
• Memoria secundaria. Permite conservar datos y programas en forma permanente, aún luego de apagar
el computador.
• Periféricos. Son dispositivos utilizados para suministrar información entre el computador y el exterior
(monitor, teclado, ratón, tarjeta de red, impresoras, tarjetas de memoria, escáner, etc.).

1.2. Resolución de problemas

1.2.1. Algoritmo (algorithm)


Es un conjunto bien definido de procedimientos lógicos o matemáticos que se pueden seguir para resolver
un problema en un número finito de pasos.
Es una lista finita de pasos que plantean una solución a un problema, preferiblemente pasos los más cortos
y simples posibles. Para un mismo problema pueden existir muchos algoritmos que conducen a su solución.
La elección del mejor algoritmo está guiada por criterios de eficiencia y eficacia, entre otras características
deseables. Elementos de un algoritmo:
• Datos de entrada.
• Proceso o pasos que resuelven el problema.
• Datos de salida.

Características de un algoritmo
• Un algoritmo debe ser preciso e indicar el orden de realización de cada paso.
• El resultado del algoritmo debe estar definido. Si se sigue un algoritmo dos veces con los mismos datos
de entrada, se debe obtener el mismo resultado cada vez.
• Un algoritmo debe ser finito. Si se sigue un algoritmo, se debe terminar en algún momento, es decir, se
debe tener un número finito de pasos.

5
Apuntes de algoritmos

1.2.2. Pseudocódigo
En un algoritmo expresado de manera más formal. Se utiliza como una representación intermedia, antes de
traducirlo o codificarlo con un lenguaje de programación. En las clases de Algoritmo utilizaremos el
pseudocódigo para expresar las soluciones algorítmicas creadas.

1.2.3. Lenguaje de programación


En computación es cualquier lenguaje artificial que puede utilizarse para definir una secuencia de
instrucciones, a fin de que puedan ser procesadas por un computador.
Conjunto de caracteres, reglas, palabras y operaciones con significados previamente asignados y que
permiten escribir programas.
La definición de un lenguaje de programación cubre tres aspectos:
• Léxico. Define los símbolos que sirven para la redacción de un programa y las reglas para la formación
de palabras en el lenguaje. Por ejemplo, 10 es un número entero.
• Sintaxis. Conjunto de reglas que permiten organizar las palabras del lenguaje en frases, por ejemplo, la
operación de división se define como Dividendo/Divisor.
• Semántica. Define las reglas que dan sentido a una frase.
Los principales tipos de lenguajes de programación utilizados en la actualidad son:
• Lenguajes de máquina.
• Lenguajes de bajo nivel y traductores (lenguaje ensamblador, compiladores, intérpretes).
• Lenguajes de alto nivel (C, C++, C#, Visual Basic, Java, Turbo Pascal, Prolog, JavaScript, VBScript,
PHP, VB.Net, Fortran, Delphi, etc.).

1.2.4. Programa
En Computación, es el conjunto de instrucciones que definen la secuencia de eventos que un computador
debe ejecutar para llevar a cabo una tarea, realizando cálculos y suministrando resultados.
Grupo de instrucciones compuestas con la finalidad de resolver un problema específico mediante el uso de
un computador. Un programa está codificado en un lenguaje que la máquina es capaz de entender y
procesar.
Es la traducción de un algoritmo o de un pseudocódigo utilizando un lenguaje de programación.

1.2.5. Programación
Proceso que comprende el análisis del problema, diseño de la solución, escritura o desarrollo del programa,
prueba del programa y su corrección.
Es la disciplina de la Computación que trata el desarrollo de programas.

1.2.6. Aspectos que miden la calidad en un programa


Algunos aspectos que se consideran para medir la calidad de un programa, también llamados características
deseables en un programa, son:
• Legibilidad
• Robustez
• Eficacia
• Eficiencia
• Adaptabilidad

6
Apuntes de algoritmos

• Portabilidad
• Reusabilidad del software

1.2.7. Capacidad de abstracción


Mecanismo intelectual principal en la actividad de la programación, el cual durante la etapa de análisis del
problema permite la separación de los aspectos relevantes de los irrelevantes en el contexto estudiado. Por
ejemplo, si el problema consiste en determinar cuál es la persona más alta del salón, lo relevante es la
estatura de cada persona, y no color de ojos, talla de calzado, etc.

1.2.8. Enfoques para solucionar un problema


• Programación modular. Consiste en dividir el problema original en diversos subproblemas que se
pueden resolver por separado, para después recomponer los resultados y obtener la solución al
problema.
• Enfoque divide y vencerás. consiste en resolver un problema a partir de la solución de subproblemas
del mismo tipo, pero de menor tamaño. Si los subproblemas son todavía relativamente grandes se
aplicará de nuevo esta técnica hasta alcanzar subproblemas lo suficientemente pequeños para ser
solucionados directamente.
• Diseño descendente (top-down). Consisten en diseñar los algoritmos en etapas, yendo de los
conceptos generales a los detalles. Ejemplo, para el problema de indicar los pasos para ver una película
en el cine se podría considerar en un primer nivel los siguientes pasos:
 Ir al cine.
 Comprar una entrada.
 Ver la película.
 Regresar a casa.
Luego cada uno de estos pasos puede subdividirse en otros niveles donde las instrucciones sean cada
vez más específicas.

1.2.9. Fases en la resolución de problemas


Resolver problemas a través de un computador se basa principalmente en analizar, diseñar, escribir y
ejecutar un programa con pasos orientados a solucionar el problema. Podemos considerar como fases de
resolución de un problema las siguientes:
• Análisis del problema
• Diseño del algoritmo, utilizando pseudocódigo.
• Codificación, traducción del algoritmo a un lenguaje de programación, esto nos permite crear el
programa.
• Ejecución del código del programa.
• Verificación del programa.
• Documentación.
• Depuración de errores.
• Mantenimiento y mejora del programa.

1.2.10. Ciclo de vida de desarrollo del software


• Análisis. El problema se analiza teniendo en cuanta los requerimientos o necesidades expresadas por el
cliente, la empresa o las personas que utilizaran el programa.

7
Apuntes de algoritmos

• Diseño. Una vez analizado el problema se diseña una solución que conduce a un algoritmo general que
resuelve los elementos más significativos del programa. Este algoritmo puede ser escrito utilizando
pseudocódigo.
• Codificación (implementación). La solución expresada en pseudocódigo se traduce a un programa que
el computador pueda procesar utilizando un lenguaje de programación de alto nivel.
• Compilación, ejecución y verificación. El programa se ejecuta (corre) y se verifica para eliminar
errores de programación o de lógica.
• Documentación. Se agrega al código del programa línea de texto que ayudan al programador y a las
personas que a futuro harán mantenimiento al software a entender su estructura y comportamiento. La
documentación también incluye escribir informes en donde se describe cómo se realizaron las diferentes
fases del ciclo de vida del software (en especial los procesos de análisis, diseño, codificación y prueba),
se agregan manuales de usuario y de referencia, así como normas para el mantenimiento.
• Depuración y mantenimiento. El programa se actualiza y modifica en la medida en que sea necesario
de manera que cumpla con las necesidades de los usuarios las cuales también cambian en el tiempo.

1.3. Datos

1.3.1. Dato
Diferentes entidades u objetos de información con que trabaja un programa. Determina el conjunto de
valores que la entidad puede almacenar, los operadores y las operaciones definidos sobre ellos.
Los datos tienen 3 características:
• Un nombre que los diferencia del resto.
• Un tipo que nos determina las operaciones que podemos hacer con ese dato.
• Un valor que puede variar o no a lo largo de la operación.

1.3.2. Tipo de dato


Define el conjunto de valores que un elemento o un objeto (una variable, constante, expresión o función) de
dicho tipo puede asumir y las operaciones asociadas a tales valores.
Es un conjunto de entidades o de objetos y las operaciones definidas sobre ellos.
Los datos pueden ser:
• Simples. Un elemento.
• Compuestos. Varios elementos.
Los tipos pueden ser:
• Estándar. Que vienen en el sistema por defecto.
• No estándar. Son los que crea el usuario.
Los tipos simples más importantes son:
• Numéricos
 Entero. Subconjunto finito del conjunto matemático de los números enteros. No tiene parte decimal.
El rango de los valores depende del tamaño que se les da en memoria.
 Real. Subconjunto finito del conjunto matemático de los números reales. Llevan signo y parte
decimal. Se almacenan en 4 Bytes (dependiendo de los modificadores). Si se utilizan números reales
muy grandes, se puede usar notación científica que se divide en mantisa, base y exponente; tal que
el valor se obtiene multiplicando la mantisa por la base elevada al exponente.

8
Apuntes de algoritmos

• Lógicos o booleanos. Aquel que sólo puede tomar uno de los dos valores, verdadero o falso (1/0).
• Carácter. Abarca al conjunto finito y ordenado de caracteres que reconoce la computadora (letras,
dígitos, caracteres especiales, ASCII).
• Cadena o String. Conjunto de caracteres, que van a estar entre “”.
En algunos lenguajes se definen tipos especiales de fecha y hora, sobre todo en los más modernos.

1.3.3. Posible clasificación de los tipos de datos


• Tipos de datos primitivos o elementales: tipos básicos incluidos en cada lenguaje de programación.
En el lenguaje de programación Java, también son llamados tipos integrados.
• Tipos de datos estructurados: tipos basados o construidos a partir de tipos de datos primitivos (por
ejemplo, arreglo, registro, archivo, conjunto).
• Tipos de datos abstractos (TDA): tipos de datos definidos por el usuario y las operaciones abstractas
aplicadas sobre ellos. Los TDA apoyan el concepto de ocultamiento de la información. Esconden los
detalles de la representación y permiten el acceso a los objetos sólo a través de sus operaciones, son
ejemplos las representaciones de los TDA Lista, Cola, Pila, Árbol y la representación que hace el
Enfoque Orientado a Objeto mediante atributos y métodos.

Esquemas de organización de los tipos de datos


Esquema 1 Número de Tipo de componentes
componentes
- Entero, Real (numéricos)
1 Elemental - Carácter, Cadenas de caracteres (caracteres)
- Lógico (boléanos)
Homogéneos (todos los elementos iguales)
Tipos de datos
- Arreglos
n Estructurado - Archivos
Heterogéneos (aceptan elementos distintos)
- Registros

Esquema 2 - Entero
- Real
Estándar
- Carácter
- Lógico (boléanos)
- Arreglo (Vector, Matriz, Cubo)
- Registro
Tipos de datos Estáticos
- Archivo (Fichero)
- Cadena de caracteres
- Lista (y las variaciones pila, cola, dipolo)
- Lista enlazada
Dinámicos
- Árbol
- Grafo

1.3.4. Constante
Tienen un valor fijo que se le da cuando se define la constante y que ya no puede ser modificado durante la
ejecución. Pueden ser numéricos, lógicos, carácter o cadena.
Las constantes pueden llevar asociados un nombre o no, si no lo llevan, se llaman literales. Su valor hay que
darlo al definir la constante y ya no puede cambiar a lo largo de la ejecución, y en cuanto al tipo,

9
Apuntes de algoritmos

dependiendo de los lenguajes en algunos hay que ponerlo, y en otros no hace falta ponerlo porque toma el
tipo del dato que se le asigna.
const
<nombre_de_constante> = <valor>
Ejemplo:
const
PI = 3.1415

1.3.5. Variable
Nombre asignado a una entidad que puede adquirir un valor cualquiera dentro de un conjunto de valores. Es
decir, una entidad cuyo valor puede cambiar a lo largo del programa.
En un programa de computador se puede asumir que una variable es una posición de memoria donde los
valores asignados pueden ser reemplazados o cambiados por otros valores durante la ejecución del
programa.
Antes de usar una variable hay que definirla o declararla, al hacerlo hay que dar su nombre y su tipo. El
nombre que le damos tiene que ser un nombre significativo, va a ser un conjunto de caracteres que
dependiendo del lenguaje hay restricciones. Tiene que empezar por una letra, y el tamaño depende del
lenguaje.
• Identificador. Palabra que no es propia del lenguaje.
• El valor de la variable si al declararla no se la inicializa, en algunos lenguajes toma una por defecto. En
cualquier caso el valor de la variable se debe inicializar o ir variarlo a lo largo de la ejecución.
var
<tipo_de_dato> : <lista_identificadores_de_variables>
Ejemplo:
var
entero : mayor, menor
real : precio
lógico : encontrado
La ventaja de usar constantes con nombre es que en cualquier lugar donde quiera que vaya la constante,
basta con poner su nombre y luego el compilador lo sustituirá por su valor.
Al detectar una variable o una constante con nombre, automáticamente se reserva en memoria espacio para
guardar esa variable o constante. El espacio reservado depende del tipo de la variable.

1.3.6. Operaciones de los tipos de datos elementales


• Operación. Acción por medio de la cual se obtiene un resultado de un operando. Ejemplos: sumar,
dividir, unir, restar.
• Operando. número, texto, valor lógico, variable o constante sobre la cual es ejecutada una operación.
• Operador. símbolo que indica la operación que se ha de efectuar con el operando, por ejemplo, + /
- * >= = <> <= =

1.3.7. Expresiones
Son combinaciones de constantes, variables, símbolos de operación, paréntesis y nombres de funciones o
acciones. Cada expresión toma un valor que se determina considerando los valores de las variables,
constantes y operaciones implicadas.

10
Apuntes de algoritmos

Una expresión consta de operandos y operadores.


Según sea el tipo de datos que manipulan, las expresiones se pueden clasificar en Aritméticas, Lógicas o
Carácter. Así tenemos:

Numéricas: Operadores aritméticos


Son los que se utilizan en las expresiones numéricas (una combinación de variables y/o constantes
numéricas con operadores aritméticos y que al evaluarla devuelve un valor numérico.
+, -, *, /
Operación resto: Lo que devuelve es el resto de una división entera.
5 mod 3 = 2
División entera: Nos devuelve el cociente de una división entera (en la que no se sacan decimales).
5 div 3 = 1
Potencia:
5 ^ 2 = 25 ó 5 ** 2 = 25.
Todos estos operadores son binarios (el operador se sitúa en medio), el menos también puede ser unario
(lleva un único operando) y significa signo negativo.

Reglas de precedencia
El problema es cuando una expresión entera según como la evalúe pueda dar diferentes valores.
7 * 3 + 4  25
La solución es aplicar prioridad entre los operadores, de modo que ante la posibilidad de usar varios siempre
aplicaremos primero el de mayor prioridad.
Cada lenguaje puede establecer sus propias reglas de prioridad o precedencia de operadores. Si no nos
acordamos, siempre podemos poner ( ).
• ^ ó **
• * / div mod
• + -
Entre dos operaciones que tienen la misma precedencia para resolver la ambigüedad, hay que usar la regla
de la asociatividad. La más normal es la de la asociatividad a izquierdas (primero lo de la izquierda).

Expresiones lógicas: Operadores relacionales y lógicos


Una expresión lógica es aquella que sólo puede devolver dos valores (Verdadero o Falso). Los valores que
pueden aparecer en una expresión lógica son de 2 tipos: lógicos y relacionales.
La particularidad de las expresiones lógicas es que mientras en una expresión numérica por devolver un
valor numérico los operandos solo pueden ser números, en una expresión lógica los operandos no tienen
porque ser booleanos aunque se devuelva un valor booleano. Esto es lo que ocurre cuando en la expresión
lógica utilizamos operadores relacionales con lo cual se obtienen valores lógicos o booleanos a partir de
otros que no lo son.
En cambio cuando los operadores son lógicos los operandos obligatoriamente también tienen que ser
lógicos.
Operadores relacionales
<, >, =, <>, <=, >=
< Operando1> operador < Operando2>
5 > 3  Verdadero

11
Apuntes de algoritmos

¿Cómo se evalúa una expresión relacional?


• Primero se evalúa el primer operando y se sustituye por su valor.
• Luego se evalúa el segundo operando y se sustituye por su valor.
• Finalmente se aplica el operador relacional y se devuelve el valor booleano correspondiente.
((3 * 2) + 1 – 5 ^ 2) < (2 - 1)
-18 < 1  Verdadero
El problema del tipo real:
Desde la informática, los números reales son finitos, ya que tenemos un máximo de cifras decimales.
Cuando trabajamos con un =, matemáticamente da un valor exacto, pero informaticamente no es exacto.
1 / 5 * 5 = 1
1.0 / 5.0 * 5.0 <> 1.0
Soluciones:
• La que nos aporte el propio lenguaje de programación. Se considera un valor de error.
• Trabajar con números enteros siempre que sea posible.
• Utilizar las comparaciones <> en vez de <= => si es posible.
• Si hay que preguntar por igual, cambiar la condición utilizando valores absolutos y un valor mínimo de
error.
• Si la diferencia < 0.00000001 y ABS (A - B) < min; son iguales.

Operadores lógicos
El problema es que a veces queremos preguntar o evaluar por más de una condición al mismo tiempo y para
esto están los operadores lógicos.
Y
O
No
Y, O, son operadores binarios (necesitan 2 operandos de tipo lógico).
Operando 1 Operador Operando 2
El No es unario, se coloca primero el No, y después el operando.
El resultado es lógico y depende de:

Operando 1 Operando 2 Y O
V V V V
V F F V
F V F V
F F F F
El No niega:

Operando No
V F
F V

12
Apuntes de algoritmos

1.3.8. Precedencia
Prioridad definida entre los operadores. Indica en qué orden debe aplicarse diferentes operaciones sobre un
conjunto de valores. Permiten aplicar los operadores en el orden correcto.
• ( )
• ** No
• div mod / * Y
• + - O
• < > = <= >= <>
De mayor prioridad a menor prioridad. En caso de haber operadores del mismo nivel en una expresión, se
evalúan en orden de aparición de izquierda a derecha.
En expresiones donde se combinen operadores se evalúa primero los aritméticos, luego los relacionales y
de último los operadores lógicos.

1.3.9. Funciones internas


Son funciones matemáticas diferentes de las operaciones básicas pero que se incorporan al lenguaje y que
se consideran estándar. Dependen del lenguaje. Normalmente se encuentran en la librería de matemáticas
del lenguaje de programación.

Función Descripción Tipo de argumento Resultado


abs (x) Valor absoluto de x Entero o real Igual que el argumento
arctan (x) Arcotangente de x Entero o real Real
cos (x) Coseno de x Entero o real Real
sen (x) Seno de x Entero o real Real
ent (x) Entero de x Real Entero
exp (x) E elevado a x Entero o real Real
ln (x) Logaritmo natural de x Entero o real Real
log10 (x) Logaritmo base 10 de x Entero o real Real
redondeo (x) Redondea x al entero más próximo Real Entero
trunc (x) Parte entera de x Real Entero
cuadrado (x) Cuadrado de x Entero o real Igual que el argumento
raiz2 (x) Raíz cuadrada de x Entero o real Real

1.4. Representación de algoritmos


Un algoritmos puede ser escrito en castellano narrativo, pero esta descripción suele ser demasiado extenso y,
además, ambigua. Para representar un algoritmo se utilizar algún método que permita independizar dicho
algoritmo de los lenguajes de programación y, al mismo tiempo, que sea fácilmente codificable.
Los métodos más usuales para la representación de algoritmos son:
• Diagramas de flujo
• Diagramas N-S (Nassi-Schneiderman)
• Pseudocódigo.

13
Apuntes de algoritmos

1.4.1. Diagramas de flujo


Es una notación gráfica para implementar algoritmos. Se basa en la utilización de unos símbolos gráficos
que se denominan cajas, en las que se escribe las acciones que tiene que realizar el algoritmo.
Las cajas están conectadas entre sí por líneas y eso nos indica el orden en el que tenemos que ejecutar las
acciones.
En todo algoritmo siempre habrá una caja de inicio y otra de fin, para el principio y final del algoritmo.

Símbolo Función
Líneas de flujo. Una línea con una flecha que sirve para conectar los símbolos
del diagrama y la flecha indica la secuencia en la que se van a ejecutar las
acciones.

Principio y fin. Dentro del símbolo ira la palabra inicio o fin del algoritmo.

Proceso. Indica la acción que tiene que realizar la computadora. Dentro


escribimos la acción.

Entrada y salida. Dentro colocaremos las acciones de lectura y escritura

Condición. Dentro se va a colocar una condición. Sirve para representar


estructuras selectivas y repetitivas

Comentario. Es una aclaración para entender mejor el código, pero no es parte


de este, no se ejecuta.

Ejemplo: Obtener el área de un rectángulo.

inicio

base

altura

area = base * altura

area

fin

14
Apuntes de algoritmos

1.4.2. Diagramas N-S (Nassi-Schneiderman)


Los diagramas Nassi-Schneiderman, denominados así por sus inventores, son herramientas de
programación que favorece la programación estructurada y reúne características gráficas propias de
diagrama de flujo y lingüísticas propias de los pseudocódigos. Consta de una serie de cajas contiguas que
se leerán siempre de arriba-abajo y se documentarán de la forma adecuada.
En los diagramas N-S las tres estructuras básicas de la programación estructurada, secuencial, selectiva y
repetitiva, encuentran su representación propia.
Ejemplo: Hallar el producto de varios números positivos introducidos por teclado y el proceso termina
cuando se meta un número negativo.

inicio

p  1

leer num

mientras num >= 0

p  p*num

leer num
escribir p

fin

1.4.3. Pseudocódigo
Es un lenguaje de especificación de algoritmos, pero muy parecido a cualquier lenguaje de programación,
por lo que luego su traducción al lenguaje es muy sencillo, pero con la ventaja de que no se rige por las
normas de un lenguaje en particular. Nos centramos más en la lógica del problema.
El pseudocódigo también va a utilizar una serie de palabras clave o palabras especiales que va indicando lo
que significa el algoritmo.
algoritmo <identificador_algoritmo>
// declaraciones, sentencias no ejecutables
inicio
// acciones, sentencias ejecutables tanto simples como estructuradas
fin
• Comentarios. Sirven para documentar el algoritmo y en ellos se escriben anotaciones generalmente
sobre su funcionamiento.
// comentario de una línea
{ comentario que ocupa más
de una línea }
• Palabras reservadas. Son las palabras que tienen un significado especial, como inicio y fin. En lugar de
las palabras reservadas no deben usarse otras similares, aunque no se distingue entre mayúscula y
minúsculas.
inicio, fin
si, entonces, si_no, fin_si
según_sea, hacer, fin_según

15
Apuntes de algoritmos

mientras, fin_mientras
desde, hasta, incremento, decremento, fin_desde, etc.
• Identificadores. Son los nombres que se dan a las constantes, variables, procedimientos u otros
objetivos que manipula el algoritmo.
Ejemplo: Obtener el área de un rectángulo.
algoritmo area_rectangulo
entero : base, altura, area
inicio
leer(base)
leer(altura)
area  base * altura
escribir(area)
fin
Ejemplo: Hallar el producto de varios números positivos introducidos por teclado y el proceso termina
cuando se meta un número negativo.
algoritmo producto_positivos
entero : p, num
inicio
p  1
leer(num)
mientras (mun >= 0) hacer
p  p * num
leer(num)
fin_mientras
escribir(p)
fin

16
Apuntes de algoritmos

2. Estructura general de un programa

2.1. Estructura general de un algoritmo en pseudocódigo


El pseudocódigo es la herramienta más adecuada para la representación de algoritmos. El algoritmo en
pseudocódigo debe tener una estructura muy clara y similar a un programa, de modo que facilite al máximo su
posterior codificación. Interesa por lo tanto conocer las secciones en las que se divide un programa-.
• La cabecera. Contiene el nombre del programa.
• El cuerpo. Tiene a su vez 2 partes:
 Bloque de declaraciones. Se definen o declaran las constantes con nombre, los tipos de datos
definidos por el usuario y las variables.
 Bloque de instrucciones. Contiene las acciones a ejecutar para la obtención de los resultados. Las
instrucciones o acciones básicas a colocar en este bloque se podrían clasificar del siguiente modo:
o Inicio y fin. La primera instrucción de este bloque será siempre la de inicio y la última la de fin.
o Asignación. Dar un valor a una variable.
o Lectura / escritura. Introducir o sacar información por dispositivos E/S.
o Instrucciones de bifurcación. Alteran El orden de ejecución del programa. Salto a otra instrucción
que no es la siguiente.
// cabecera
algoritmo <nombre_del_algoritmo>

// bloque de declaraciones
const
<listado_constantes>
var
<listado_variables>
entero : var1, var2

// bloque de instrucciones
inicio // inicio del bloque de instrucciones

var1  0 // asignación

escribir(“ingresar un valor: ”) // escritura

leer(var2) // escritura

fin // fin del bloque de instrucciones

2.2. Operación de asignación


Es el modo de darle un valor a una variable, el cual puede ser una constante, otra variable o el resultado de una
expresión.
En pseudocódigo la operación de asignación se representa mediante el símbolo u operador  para la
asignación.
En el contexto de un lenguaje de programación, a la operación de asignación, se le llama instrucción o
sentencia de asignación.

17
Apuntes de algoritmos

Comportamiento: Modifica el estado de la variable.


La notación algorítmica (sintaxis) que utilizaremos para la asignación es:
<nombre_de_variable>  <constante_o_variable_o_expresión>
Ejemplo. Considerando la siguiente declaración de variables:
caracter : c1
entero : i
lógico : enc
// a continuación se asignará a la variable c1 el carácter ‘a’
c1  ‘a’
// Luego de la asignación, el valor de enc es Verdadero
enc  (1 > 0)
// Luego de la asignación, el valor de i es 10
i  5 + 15 div 3

Reglas de la asignación
Sea la expresión:
Operador de asignación

Izquierda Derecha
Variable a quien se asigna Expresión cuyo resultado se asigna

b  c*2,45
• Una variable en el lado derecho de una sentencia de asignación debe tener un valor antes de que la
sentencia de asignación se ejecute, en el ejemplo, a la variable c se le debe asignar un valor antes a fin de
que la expresión c*2.45 arroje un resultado. Hasta que en el algoritmo a una variable no se le asigna
(usando el operador = o a través de una lectura) se asume que no ha sido inicializada.
• En la izquierda de una sentencia de asignación sólo pueden existir variables y eventualmente una
constante, por lo tanto la expresión ValorNeto – Tasa = Interes * 3,15 es un error.

2.2.1. Operación de lectura o entrada simple (leer)


La operación de lectura o de entrada permite leer determinados valores y asignarlos a determinadas
constantes o variables.
Almacena en una variable un valor extraído desde un dispositivo externo, del cual hacemos abstracción
aunque generalmente es el teclado.
Los datos de entrada se introducen en el computador mediante dispositivos de entrada (teclado, pantalla,
unidades de disco, escáneres, entre otros). Los datos de salida pueden aparecer en un dispositivo de salida
(pantalla, impresora, cornetas, entre otros).
Comportamiento: Cambia el valor en la variable en cuestión.
Luego de leer un valor de un dispositivo externo, el valor de la variable cambia en forma similar a si se
hiciera una asignación y adopta el valor leído.
La notación algorítmica (sintaxis) que utilizaremos para la asignación es:
leer(<Nombre_de_variable>)
Ejemplo, sean las variables:
entero : i
caracter : c
Acciones de lectura:
leer(i)
leer(c)

18
Apuntes de algoritmos

2.2.2. Operación de escritura o salida simple (escribir)


Transmite un valor (constante, variable o evaluación de una expresión) a un dispositivo externo (que
haremos abstracción, aunque generalmente es el monitor) para ser mostrado al usuario.
Comportamiento: muestra resultados.
La notación algorítmica (sintaxis) que utilizaremos para la asignación es:
escribir(<Nombre_de_variable, constante_o_expresión>)
Ejemplo:
entero : i
i  4
// A la variable i se le asigna el valor 4
escribir(“El valor de la variable i es: ” + (i + 1))
// Luego de realizada la suma, se escribe el valor 5
Nota: los símbolos // (barra derecha barra derecha) se utilizarán para indicar un comentario en el
pseudocódigo.

2.3. Conversión de tipos


La conversión de tipos es el proceso de cambiar un valor de un tipo de dato a otro. Por ejemplo, la cadena
"1234" se puede convertir a un número entero, y a su vez, un tipo de dato real o entero se puede convertir al
tipo cadena.
Las conversiones de tipo pueden ser de ampliación o de restricción:
• Las conversiones de ampliación nunca producen desbordamiento y siempre son correctas, por ejemplo,
convertir del tipo entero a un conjunto más grande como el tipo real,
• Las conversiones de restricción suponen una posible pérdida de información y pueden producir errores,
por ejemplo, al convertir los datos reales a enteros, puede haber pérdida de información al eliminarse la
parte decimal.
Ambos tipos de conversión pueden ser explícitas o implícitas.
Las conversiones con pérdida de información tienen lugar cuando el tipo de datos original no tiene un análogo
en el tipo de destino de la conversión. Por ejemplo, la cadena "Pedro" no se puede convertir en un número. En
estos casos, algunos lenguajes de programación devuelven un valor predeterminado cuando se usa la función
de conversión de tipo, por ejemplo el valor NaN o el número cero, indicando con estos valores que la
conversión de tipos falló.
Algunos tipos de conversiones, como de una cadena a un número, tardan bastante tiempo. Cuantas menos
conversiones utilice el programa, más eficaz será.

2.3.1. Conversión implícita


La mayoría de las conversiones, como la asignación de un valor a una variable, se producen
automáticamente. El tipo de datos de la variable determina el tipo de datos de destino de la conversión de
expresión. En otros casos, la conversión implícita viene dada tanto por los tipos de datos como por los
operadores utilizados.

2.3.2. Conversión explícita


Para convertir explícitamente una expresión a un tipo de datos concreto, se utilizan funciones que se
asumen predefinidas y disponibles en el pseudocódigo, colocando entre paréntesis el dato, variable o
expresión que se va a convertir. Las conversiones explícitas requieren más escritura que las implícitas, pero

19
Apuntes de algoritmos

proporcionan más seguridad con respecto a los resultados. Además, las conversiones explícitas pueden
controlar conversiones con pérdida de información.
El comportamiento de la conversión explícita depende del tipo de datos originales y del tipo de datos de
destino.
En el ejemplo siguiente se muestra conversiones de datos implícitas y explícitas, usando valores entero,
cadena, caracter y real.
// Se declaran las variables indicando su tipo de dato
entero : i
real : d
caracter : c
cadena : pal

// A la variable i se le asigna el valor entero 5


i  5
// A la variable real d se le asigna el entero 5,
d  i
{ Hay conversión implícita de datos cambiando el valor a 5,0 porque d es
un real. }

// A la variable c se le asigna el carácter ‘a’


c  ‘a’
pal  “los árboles” + c
{ A la variable pal se le asigna la unión de una cadena y un carácter,
aquí el operador + significa concatenación y no la suma algebraica. }

i  aEntero(d)
{ El valor de la variable d es convertido explícitamente de real a
entero, asignando a la variable i, la parte entera del valor de d (5 en
lugar de 5,0) }

c  aCaracter(i)
{ Se convierte explícitamente el tipo de dato de la variable i,
transformando el valor entero 5 al carácter ‘5’ }

2.4. Contadores
Un contador es una variable cuyo valor se incrementa o decrementa en una cantidad constante cada vez que
se produce un determinado suceso o acción. Los contadores se utilizan en estructuras repetitivas con la
finalidad de contar sucesos o acciones internas del bucle.
Con los contadores se debe realizar una operación de inicialización y, posteriormente, las sucesivas de
incremento o decremento del contador.
La inicialización consiste en asignarle al contador un valor. Se situará antes y fuera del bucle.
<nombre_del_contador>  <valor_de_inicialización>
En cuanto a los incrementos o decrementos del contador, puesto que la operación de asignación admite que la
variable que recibe el valor final de una expresión intervenga en la misma, se realizarán a través de este tipo de
instrucciones de asignación, de la siguiente forma:
<nombre_del_contador>  <nombre_del_contador> + <valor_constante>
dicho <valor_constante> podrá ser positivo o negativo. Esta instrucción se colocará ene el interior del bucle.

20
Apuntes de algoritmos

2.5. Acumuladores
Son variables cuyo valor se incrementa o decrementa en una cantidad determinada. Necesitan operaciones de:
• Inicialización:
<nombre_del_acumulador>  <valor_de_inicialización>
• Acumulación:
<nombre_del_acumulador>  <nombre_del_acumulador> + <nombre_variable>
Hay que tener en cuenta que la siguiente también sería una operación de acumulación:
<nombre_del_acumulador>  <nombre_del_acumulador> + <valor>

2.6. Interruptores
Un interruptor o bandera (switch) es una variable que puede tomar los valores verdad y falso a lo largo de la
ejecución de un programa, comunicando así información de una parte a otra del mismo. Pueden ser utilizados
para el control de bucles y estructuras de selectivas. En este caso también es frecuente que la variable que
recibe el valor final de una expresión intervenga en la misma, por ejemplo:
En primer lugar el interruptor se inicializa a verdad o falso
<nombre_del_interruptor>  <valor_de_inicialización>
En determinadas condiciones el interruptor conmuta
<nombre_del_interruptor>  no <valor_del_interruptor>

21
Apuntes de algoritmos

3. Estructura general de un programa

3.1. Programación estructurada


La programación estructurada es un conjunto de técnicas para desarrollar algoritmos fáciles de escribir,
verificar, leer y modificar. La programación estructurada utiliza:
• Diseño descendente. Consiste en diseñar los algoritmos en etapas, yendo de los conceptos generales a
los de detalle. El diseño descendente se verá completado y ampliado con el modular.
• Recursos abstractos. En cada descomposición de una acción compleja se supone que todas las partes
resultantes están ya resueltas, posponiendo su realización para el siguiente refinamiento.
• Estructuras básicas. Los algoritmos deberán ser escritos utilizando únicamente tres tipos de estructuras
básicas (secuencial, selectiva, repetitiva).
Para que la programación sea estructurada, los programas han de ser propios. Un programa se define como
propio si cumple las siguientes características:
• Tiene un solo punto de entrada y uno de salida.
• Toda acción del algoritmo es accesible, es decir, existe al menos un camino que va desde el inicio hasta el
fin del algoritmo, se puede seguir y pasa a través de dicha acción.
• No posee lazos o bucles infinitos.

3.2. Estructura secuencial


Consiste en presentar un conjunto de instrucciones en un orden. Las instrucciones se realizan en el mismo
orden en que son escritas. El símbolo; se utiliza para separar una instrucción de otra.
<instrucción 1>
<instrucción 2>
...
<instrucción n>
Comportamiento. Representa las acciones del algoritmo y el orden en que se realizarán.
Las instrucciones (<instrucciones 1> a la <instrucciones n>) no solo tienen que ser operaciones
básicas, también pueden ser llamadas a acciones o funciones que realizan un procedimiento, estructuras de
control de programa (selección y repetición), las cuales serán explicadas en próximos temas.
Ejemplo:
algoritmo ejemplo
{ Secuenciamiento de instrucciones que inicializa un número, lo incrementa en 1
y lo eleva a la 5ta potencia }
var
entero : i
inicio
i  1 // en este momento i tiene el valor de 1
i  i + 1 // en este momento i tiene el valor de 2
i  i ** 5 // en este momento i tiene el valor de 32
escribir(“El valor fin de la variable i es: ” + i) // se escribe un mensaje
fin // Fin de la secuencia de instrucciones

22
Apuntes de algoritmos

3.3. Estructura selectiva


Una estructura selectiva es aquella en que se ejecutan unas acciones u otras según se cumpla o no una
determinada condición.

3.3.1. Simple
En el condicional simple se evalúa la condición y si ésta da como resultado verdad se ejecuta una
determinada acción o grupo de acciones; en caso contrario se saltan dichos grupos de acciones.
Recomendación.: utilizar indentación o sangría para mostrar los niveles de anidación en las instrucciones.
si <condición> entonces
acción
fin_si

no si
condición

acción

3.3.2. Doble
Cuando el resultado de evaluar una condición es verdad se ejecutará una determinada acción o grupo de
acciones y si el resultado es falso se ejecutará otra acción o grupo de acciones diferentes.
Recomendación: utilizar indentación o sangría en los algoritmos y códigos.
si <condición> entonces
acción 1
si_no
acción 2
fin_si

no si
condición

acción 2 acción 1

23
Apuntes de algoritmos

3.3.3. Múltiple
Se evalúa una condición o expresión que puede tomar n valores. Según el valor que la expresión tenga en
cada momento se ejecutan las acciones correspondientes al valor.
Las acciones asociadas al valor si_no se ejecutan cuando la expresión no toma ninguno de los valores que
aparecen antes.
El valor con el que se compara la expresión, va a depender de los lenguajes, de lo que sea ese valor. En
general ese valor puede ser un valor constante, un rango de valores o incluso otra condición.
según_sea <expresión> hacer
<lista1> : acción 1
<lista2> : acción 2
...
[ si_no
acción ]
fin_según

no
expresión acción

lista1 lista2

acción 1 acción 2

3.4. Estructura repetitiva


Un bucle, lazo, ciclo o loop (en inglés) es un segmento de algoritmo o programa (una secuencia de
instrucciones) que se repiten un determinado número de veces mientras se cumple una determinada condición,
en otras palabras, un bucle o ciclo es un conjunto de instrucciones que se repiten mientras una condición es
verdadera o existe.
A cada repetición del conjunto de acciones se denomina iteración.
Para que un bucle no se repita indefinidamente debe tener una condición de parada o de fin. Esta condición de
parada o de fin se verifica cada vez que se hace una iteración. El ciclo llega a su fin cuando la condición de
parada se hace verdadera.
La condición de parada puede estar al principio de la estructura repetitiva o al final.
Al igual que las estructuras de selección simple o compuesta, en un algoritmo pueden utilizarse varios ciclos.
Estos ciclos pueden ser independientes (una a continuación de otro) o anidados (ciclos dentro de ciclos).
Para representar los bucles o lazos utilizaremos en el curso las estructuras de control Mientras, Hacer-
mientras, Repetir-hasta y Desde.

24
Apuntes de algoritmos

Los ciclos o procesos repetitivos de instrucciones son procedimientos fundamentales en el uso de las
computadoras y por lo tanto en muchos algoritmos y programas.
Vamos a utilizar ciclos cuando:
• Necesitemos repetir instrucciones un determinado número de veces, mientras se cumpla una condición,
mientras un hecho sea verdadero o hasta cuando se alcance un determinado valor o condición.
• Cuando necesitemos contar un determinado número de elementos o de acciones, por ejemplo contar las
sílabas de un texto, los elementos de una secuencia que verifican una determinada condición o contar el
número de personas que cumplen ciertas características. En este caso se incluirán contadores dentro del
bucle.
• Los contadores son variables (generalmente de tipo entero) que tienen un valor inicial y que se incrementan
o decrementan en un valor constante cada vez que ocurre una iteración. Cuando los contadores se
decrementan se habla de descontar, en lugar de contar.
• También usaremos ciclos cuando necesitemos acumuladores determinados valores cada vez que se realiza
una iteración. Los acumuladores también son variables (generalmente de tipo entero, real o cadena), que
almacenan valores variables resultantes de las operaciones que se realizan en cada ciclo.
• Por ejemplo, podemos usar para ir sumando los precios de varios vehículos y luego calcular el precio
promedio general (con una variable acumulador de tipo real), para calcular la potencia o el factorial de un
número a través de multiplicaciones sucesivas (un acumulador de tipo entero o real) o para ir agregando a
una cadena de caracteres, letras o sílabas que construirán un mensaje (una variable acumulador del tipo
cadena)

3.4.1. Mientras
Es una estructura iterativa que permite verificar la condición de entrada al ciclo antes del cuerpo de
instrucciones a repetir.
Como la evaluación de la condición de entrada se realiza al inicio del bloque Mientras, puede ocurrir que las
instrucciones del ciclo no se realicen ni siquiera 1 vez, a diferencia del Repetir-hasta, donde el bloque de
instrucciones se realiza al menos 1 vez porque la condición de parada se verifica al final. Las instrucciones
del Mientras se pueden realizar 0 o más veces antes de que se cumpla la condición de terminar el ciclo.
El conjunto de instrucciones dentro del Mientras se ejecuta cuando la condición de entrada del principio se
cumple (es verdadera). Dicho de otro modo, el ciclo de instrucciones dentro del Mientras se va a detener
cuando la condición se haga falsa.
Se recomienda usar la estructura Mientras tienes que verificar la condición de entrada al inicio y si se
cumple, entonces, entrar al ciclo y realizar sus instrucciones.
mientras <expresión_lógica> hacer
acción
fin_mientras

no
condición

si

acción

25
Apuntes de algoritmos

3.4.2. Hacer-mientras
El bucle Hacer-mientras es análogo al bucle Mientras desde el punto de vista de que el cuerpo del bucle se
ejecuta una y otra vez mientras la condición es verdadera. La diferencia entre ellos consiste en que las
sentencias del cuerpo del bucle Hacer-mientras, se ejecutan al menos una vez antes que se evalúe la
expresión lógica.
hacer
acción
mientras <expresión_lógica>

acción

si no
condición

3.4.3. Repetir-hasta
Ejecuta un bloque de instrucciones varias veces hasta que se cumple la condición que es verificada al final
del bucle.
Las instrucciones dentro del ciclo Repetir-hasta se van a realizar mientras la condición de parada evaluada
al final sea falsa. Dicho de otro modo, el ciclo se va a detener cuando la condición de parada se haga
verdadera.
Se recomienda usar la estructura Repetir-hasta cuando las instrucciones del ciclo se pueden realizar al
menos 1 vez antes de comprobar la condición de parada.
repetir
acción
hasta_que <expresión_lógica>

acción

no si
condición

3.4.4. Desde
Es una estructura iterativa que es controlada por una variable (llamada también variable índice), la cual se
incrementa o decrementa hasta llegar a un valor límite o valor final que representa la condición de parada.

26
Apuntes de algoritmos

La estructura Desde comienzan con un valor inicial de la variable índice, las acciones especificadas para el
ciclo se ejecutan un número determinado de veces, a menos, que el valor inicial de la variable índice sea
mayor que el valor límite que se quiere alcanzar.
El incremento o decremento de la variable índice suele ser de 1 en 1, salvo cuando se indica lo contrario. La
variable índice suele ser de tipo entero y se utilizan comúnmente nombres como i, j o k (no importa si en
mayúsculas o minúsculas)
Se recomienda usar la estructura Desde cuando se conoce el número de veces que se deben ejecutar las
instrucciones del ciclo, es decir, en los casos en que el número de iteraciones es fijo y conocido.
desde v  v1 hasta vf [incremento | decremento incr] hacer
acción
fin_desde

valor_inicial

no
condición

si

incremento o
acción
decremento

3.4.5. Observaciones
Observa que para el Mientras, Hacer-mientras y Repetir-hasta se debe incluir en el cuerpo de
instrucciones una acción donde se actualice la o las variables que usas en la condición de parada. Por el
contrario, en el Desde no es necesario incluir esta instrucción dado que en el encabezado de la instrucción
ya se incluye el incremento.
Comparación de bucles
• Mientras. El uso más frecuente es cuando la repetición no está controlada por contador; la condición
precede a cada repetición del bucle; el cuerpo del bucle puede no ser ejecutado. Se debe utilizar cuando
se desea saltar el bucle si la condición es falsa.
• Desde. Bucle de conteo, cuando el número de repeticiones se conoce por anticipado y puede ser
controlado por un contador; la condición precede a la ejecución del cuerpo del bucle.
• Hacer-mientras y repetir-hasta. Es adecuada para asegurar que al menos se ejecuta el bucle una vez.

3.5. Estructura anidada


Tanto las estructuras selectivas como los bucles se pueden anidar unos dentro de otros.

27
Apuntes de algoritmos

3.5.1. Anidación de condicionales


La ventaja de anidar sentencias condicionales, es que cuando una se cumple no hay por que mirar a las que
están debajo. Tenemos que tratar anidar la condición en la parte si_no en vez que en la parte entonces.
si <condición 1> Entonces
acción 1
si_no si <condición 2> entonces
acción 2
si_no si <condición 3> entonces
acción 3
fin_si
fin_si
fin_si
El case siempre equivale a una anidación de condicionales, pero no al revés.

3.5.2. Bucles anidados


Al igual que podemos colocar unas expresiones dentro de otras, unos bucles pueden estar dentro de otros,
pero nunca pueden cruzarse. Al anidar bucles hay que tener en cuenta que el bucle mas interno funciona
como una sentencia mas del bloque mas externo y por tanto en cada iteración del bucle mas externo se van
a ejecutar todas las iteraciones del bucle mas interno por cada iteración del mas externo.
Si el bucle mas externo se repite n veces y el mas interno se repite m veces, si por cada iteración del más
externo se repite el más interno, el número total de iteraciones será m*n.
Los bucles que se anidan pueden se de igual o distinto tipo.
desde i  1 hasta 8 hacer
desde j  1 hasta 5 hacer
escribir(“Profesor” + i + “introduzca su asignatura nº” + j)
leer(asignatura)
fin_desde
fin_desde

28
Apuntes de algoritmos

4. Subalgoritmos, funciones y procedimientos

4.1. Programación modular


Se basa en dividir el programa en partes llamadas módulos, que se analizan y codifican de forma independiente
y que realizan una determinada tarea que será en realidad una parte del problema total a resolver.
Cuando se trabaja de este modo, existirá un algoritmo principal o conductor que transferirá el control a los
distintos módulos o subalgoritmos, los cuales, cuando terminen su tarea, devolverán el control al algoritmo que
los llamó. Los módulos o subalgoritmos deben ser pequeños, seguirán todas las reglas de programación
estructurada y podrán ser representados con las herramientas de programación habituales.
El empleo de esta técnica facilita notoriamente el diseño de los programas. Algunas de las ventajas
significativas son:
• Varios programadores podrán trabajar simultáneamente en la confección de un algoritmo, repartiéndose las
distintas partes del mismo, ya que los módulos son independientes.
• Se podrá modificar un módulo sin afectar a los demás.
• Las tareas, subalgoritmos, sólo se escribirán una vez, aunque se necesiten en distintas ocasiones en el
cuerpo del programa.
Existen dos tipos de subalgoritmos: funciones y procedimientos.

4.2. Funciones
Desde el punto de vista matemático, una función es una operación que toma uno o varios operandos y devuelve
un resultado. Desde el punto de vista algorítmico, es un subalgoritmo que toma uno o varios parámetros como
entrada y devuelve, a la salida, un único resultado.
Como el resultado de la función es retornado al algoritmo principal, debe usarse una variable para almacenar
este resultado, es decir, en una variable del algoritmo principal se “captura” el valor retornado por la función.
Luego el valor almacenado en la variable puede ser utilizado por el algoritmo que llama a la función.

4.2.1. Declaración de una función


La estructura de una función es semejante a la de cualquier algoritmo. Tendrá una cabecera (con el nombre
y los parámetros) y un cuerpo (con la declaración de los parámetros de la función y las instrucciones).
<tipo_de dato> función <nombre_función> (lista_de_parámetros_formales)
[ var
declaraciones_locales ]
inicio
acciones
devolver(<expresión>)
fin_función
La lista de parámetros es la información que se le tiene que pasar a la función. Los parámetros, luego dentro
de la función, los podemos utilizar igual que si fueran variables locales definidas en la función y para cada
parámetro hay que poner su nombre y tipo.
El nombre de la función lo da al usuario y tiene que ser significativo.
En las variables locales se declaran las variables que se pueden usar dentro de la función.
Entre las acciones, tendrá que existir entre ellas una del tipo devolver(<expresión>). Esta sentencia
pondrá fin a la ejecución de la función y devolverá el valor de la función, es decir, como valor asociado al

29
Apuntes de algoritmos

nombre de mismo tipo que el tipo de datos que devuelve a la función, este valor por tanto tiene que ser del
mismo tipo que el tipo de datos que devuelve la función, que es el que habremos indicado al declarar la
función en la parte final de la cabecera.
No se permiten funciones que no devuelvan nada.
Los parámetros que aparecen en la declaración de la función se denominan parámetros formales, y los
parámetros que se utiliza cuando se llama a la función se denominan parámetros actuales o reales.

4.2.2. Llamado de una función


Para llamar a una función se pone el nombre de la función, y entre paréntesis los parámetros reales, que
podrán ser variables, expresiones, constantes, etc., pero siempre del mismo tipo que los parámetros
normales asociados.
<nombre_funcion>(parámetros_actuales)
La función puede ser llamada desde el algoritmo principal o desde cualquier otro subalgoritmo.
Para llamar a la función desde cualquier parte, implica el conocimiento previo de que ésta función existe.
A través de los parámetros reales de la llamada se proporciona a la función la información que necesita,
para ello, al hacer la llamada lo que se produce es una asociación automática entre parámetros reales y
parámetros formales. Esta asociación se realiza según el orden de la aparición y de izquierda y derecha.
La llamada a una función, siempre va a formar parte de una expresión, de cualquier expresión en la que en
el punto en la que se llama a la función, pudiera ir colocado cualquier valor del tipo de datos que devuelve la
función, esto se debe a que el valor que devuelve una función esta asociado a su nombre.
Ejemplo:
real función mitad(E entero : n)
var
real : m
inicio
m  n / 2
devolver(m)
fin_función

algoritmo calcular_mitad
var
entero : num
inicio
escribir(“Introduce un número para hallar su mitad”)
leer(num)
escribir(“La mitad de ” + num + “ es ” + mitad(num))
fin

4.3. Procedimientos
La definición de procedimientos permite asociar un nombre a un bloque de instrucciones. Luego podemos usar
ese nombre para indicar en algún punto de un algoritmo que vamos a utilizar ese bloque de instrucciones, pero
sin tener la necesidad de repetirlas, sólo invocando al procedimiento por su nombre.
Los procedimientos se caracterizan por no retornar valores al algoritmo que las llama. Sin embargo, aunque los
procedimientos no retornan valores, si pueden informar al algoritmo que las llamó (a veces llamado algoritmo
principal) de cambios realizados por sus instrucciones en algunos valores a través de una herramienta que se
llama pase de parámetros. Los parámetros permiten utilizar la misma secuencia de instrucciones con diferentes
datos de entrada. Utilizar parámetros es opcional.

30
Apuntes de algoritmos

Cuando entre las instrucciones de un algoritmo vemos el nombre de un procedimiento, decimos que estamos
llamando o invocando al procedimiento.
Los procedimientos facilitan la programación modular, es decir, tener bloques de instrucciones que escribimos
una vez pero que podemos llamar y utilizar muchas veces en varios algoritmos. Una vez terminada la ejecución
de un procedimiento, se retorna el control al punto de algoritmo donde se hizo la llamada, para continuar sus
instrucciones.

4.3.1. Declaración de procedimientos


La declaración de un procedimiento es similar a la de una función. Las pequeñas deferencias son debidas a
que el nombre del procedimiento no se encuentra asociado a ningún resultado. La declaración de un
procedimiento expresado en pseudocódigo es:
procedimiento <nombre_procedimiento> (lista_de_parámetros_formales)
[ var
declaraciones_locales ]
inicio
acciones
fin_procedimiento
Los parámetros que aparecen en la declaración del procedimiento se denominan parámetros formales, y los
parámetros que se utiliza cuando se llama al procedimiento se denominan parámetros actuales o reales.

4.3.2. Llamado de un procedimiento


Para llamar a un procedimiento se realiza con una instrucción llamar_a o bien directamente con el nombre
del procedimiento.
[ llamar_a ] <nombre_procedimiento>[(parámetros_actuales)]
El procedimiento puede ser llamado desde el algoritmo principal o desde cualquier otro subalgoritmo.
Ejemplo:
procedimiento mitad(E entero : n)
var
real : m
inicio
m  n / 2
escribir(“La mitad de ” + n + “ es ” + m)
fin_procedimiento

algoritmo calcular_mitad
var
entero : num
inicio
escribir(“Introduce un número para hallar su mitad”)
leer(num)
llamar_a mitad(num)
fin

4.3.3. Diferencias entre funciones y procedimientos:


• Una función devuelve un único valor y un procedimiento puede devolver 0, 1 ó N (a través de los
parámetros).
• Ninguno de los resultados devueltos por el procedimiento se asocian a su nombre como ocurría con la
función.
• Mientras que la llamada a una función forma siempre parte de una expresión, la llamada a un
procedimiento es una instrucción que por sí sola no necesita instrucciones.

31
Apuntes de algoritmos

4.4. Estructura general de un algoritmo


Aunque algunos lenguajes de programación exigen que los procedimientos y funciones se escriban antes de
realizar la llamada, por claridad en la escritura del pseudocódigo se escriben después del algoritmo principal.
// cabecera
algoritmo <nombre_del_algoritmo>

// bloque de declaraciones
const
<nombre_constantes> = valor1
var
<nombre_del_tipo> : <nombre_de_la_variable1> [, <nombre_de_la_variable2>, ... ]

// bloque de instrucciones
inicio // inicio del bloque de instrucciones

acción 1
acción 2

[ llamar_a ] <nombre_procedimiento>[(parámetros_actuales)]
{ la llamada a la función debe realizarse en una expresión bloque de
instrucciones }
escribir(<nombre_funcion>(parámetros_actuales))
...
acción N

fin // fin del bloque de instrucciones


<tipo_de dato> función <nombre_función> (lista_de_parámetros_formales)
[ var
declaraciones_locales ]
inicio
acciones
devolver(<expresión>)
fin_función
procedimiento <nombre_procedimiento> (lista_de_parámetros_formales)
[ var
declaraciones_locales ]
inicio
acciones
fin_procedimiento

4.5. Parámetros de los subalgoritmos

4.5.1. Tipo de parámetros


Las funciones y procedimientos manejan dos tipos de parámetros:
• Actuales. Son los valores indicados en la llamada a la función o procedimiento en el algoritmo principal.
Son los valores que se desean pasar desde el algoritmo principal a las instrucciones de la función o
procedimiento.
• Formales. Son los nombres dados a los parámetros en la definición formal de la función o
procedimiento. Con estos nombres se conocerán a los valores de los parámetros dentro de la función o
procedimiento y funcionan como variables locales dentro de ellos.

32
Apuntes de algoritmos

4.5.2. Tipo de correspondencia


Cuando un programa llama a un procedimiento o función se establece una correspondencia entre los
parámetros actuales y formales. Existen dos formas para establecer la correspondencia de parámetros:
• Posicional. En este caso se emparejan los parámetros formales y actuales por la posición que ocupan
(orden de declaración) y de izquierda a derecha. Para que se pueda realizar esta asociación, tiene que
haber el mismo número de parámetros formales y reales, y con el mismo tipo.
Ejemplo:
entero función suma(E entero : numeroA, numeroB)

escribir(suma(5, 8))
• Correspondencia por nombre explícito. Ahora en la llamada al subalgoritmo se pone explícitamente a
que parámetro formal corresponde cada actual.
Dado que la mayor parte de los lenguajes usan exclusivamente la correspondencia posicional, éste será
el método que se seguirá en el curso.

4.5.3. Clasificación de los parámetros


Al hablar de los procedimientos se decían que devuelven resultados al algoritmo principal a través de los
parámetros, pero que también pueden recibir información, desde el algoritmo principal, a través de ellos.
Esto conlleva a una clasificación de los parámetros:
• Entrada. Permite únicamente la transmisión de información desde el algoritmo llamador al subalgoritmo.
• Salida. Sólo devuelve resultados.
• Entrada/salida. Actúan en los dos sentidos, tanto mandando valores al subalgoritmo, devolviendo
resultados desde el subalgoritmo al algoritmo llamador.
En los algoritmos, se debe especificar, en la definición del subalgoritmo, el comportamiento de cada uno de
los parámetros. Para ello se empleará la siguiente terminología:
• E parámetro de entrada.
• S parámetro de salida.
• E/S parámetro de entrada/salida.

4.5.4. Pase de parámetros


Un procedimiento sólo podrá devolver resultados a través de los parámetros, de modo que al codificar el
algoritmo se ha de tener mucho cuidado con el paso de parámetros, siendo preciso conocer los métodos de

33
Apuntes de algoritmos

5. Tipos de datos estructurados

5.1. Datos estructurados


Es una herramienta mediante la cual es posible almacenar datos en la memoria del computador, permitiendo
guardar datos conformados por varios elementos y manipularlos en forma sencilla. Estas estructuras de datos
están formadas por más de un elemento, estos pueden ser todos del mismo tipo de dato (ED u homogénea
como los arreglos y los archivos) o de tipos de datos diferentes (ED heterogénea, como los registros y los
objetos).
Los datos de tipo estándar pueden ser organizados en diferentes estructuras de datos: estáticas y dinámicas.

Estructuras de datos estáticas


• Arreglos
• Registros
• Cadenas
• Conjuntos
• Archivos

Estructuras de datos dinámicas


• Listas
• Árboles
• Grafos

5.2. Arreglos
Estructuras de datos conformada por una sucesión de celdas, que permite almacenar en la memoria principal
del computador un conjunto finito de elementos (hay un número máximo conocido) que tienen el mismo tipo de
dato (son homogéneos).
Para hacer referencia a cualquiera de las celdas del arreglo es necesario el nombre del arreglo y el valor de uno
de los elementos perteneciente al conjunto de índices asignado, lo que permite tener acceso aleatorio.

5.2.1. Características básicas de los arreglos


• Homogéneo: los elementos del arreglo son todos del mismo tipo de dato.
• Ordenado: cada elemento del arreglo puede ser identificado por el índice que le corresponde. El índice
no es más que un entero que pertenece a un intervalo finito y determina la posición de cada elemento
dentro del arreglo.
• Acceso secuencial o directo: El acceso a cada elemento del arreglo se realiza recorriendo los
anteriores según el orden en que están almacenados o de manera directa (operación selectora),
indicando el valor del índice del elemento requerido.
• Sus elementos son tratados como variables simples: Una vez seleccionado algún elemento del
arreglo este puede ser utilizado en acciones de asignación, como parte de expresiones o como
parámetros al llamar a acciones o funciones como si se tratara de una variable del tipo de dato simple
declarado para todos los elementos del arreglo.

35
Apuntes de algoritmos

• Uso de índice: El índice es un valor de tipo entero (número entero o carácter con un código entero
equivalente) que determina la posición de cada elemento en el arreglo. La cantidad de índices determina
las dimensiones del arreglo. Así un arreglo unidimensional tiene un índice, un arreglo bidimensional tiene
dos índices y uno n-dimensional tiene n índices.

5.2.2. Vectores (arreglos unidimensionales)


Tipos de Datos Estructurados (TDE) donde todos sus elementos pertenecen al mismo tipo y existe una
correspondencia uno a uno de cada elemento con un subconjunto de los enteros (índices).

1 2 3 ... n-1 n ← índice


“ser” “hola” “oh” “ojo” “casa” “bien” ← contenido celda

Declaración de arreglos unidimensionales


• Declaración por variable. se declara la variable tipo arreglo como si se tratara de una variable de tipo
de dato simple.
La sintaxis a utilizar será:
var
array [<limite_inf>..<limite_sup>] de <tipo_de_dato> : <nombre_del_vector>
Ejemplo:
const
n = 51
var
array [1..5] de entero : arregloA
array [0..20] de real : arregloB, arregloC
array [7..14] de lógico : arregloD
array [-6..n] de caracter : arregloE
• Declaración por tipo: se realiza en dos pasos, se declara el arreglo como un nuevo tipo de dato y se le
asigna ese tipo a una o más variables.
La ventaja de esta clase de declaración reside en que no es necesario repetir todos los datos del arreglo
cada vez que se necesite uno, sino que se utilizan tantas variables como arreglos se necesiten y además
simplifica la escritura del algoritmo.
Para declarar un tipo, sólo hace falta anteceder a la especificación la palabra clave Tipo
La sintaxis a utilizar será:
tipo
array [<limite_inf>..<limite_sup>] de <tipo_de_dato> : <nombre_del_tipo>
var
<nombre_del_tipo> : <nombre_del_vector>
Ejemplo:
const
n = 51
tipo
array [1..5] de entero : vectorA
array [0..20] de real : vectorB
array [7..14] de lógico : vectorC
array [-6..n] de caracter : vectorD

36
Apuntes de algoritmos

var
vectorA : arregloA
vectorB : arregloB, arregloC
vectorC : arregloD
vectorD : arregloE
El número de elementos del vector vendrá dato por la fórmula:
<limite_sup> - <limite_inf> + 1

5.2.3. Arreglos bidimensionales (matrices o tablas)


Un arreglo bidimensional (tabla o matriz) es un arreglo que tiene dos índices. Para localizar o almacenar un
valor en el arreglo se deben especificar dos subíndices (dos posiciones), uno para la fila y otro para la
columna. Los diferentes tipos de índices no necesitan ser subrangos del mismo tipo.
1 2 ... . j
1 m[1, 1] m[1, 2] ... . ... .
2 m[2, 1] m[2, 2] ... . ... .
... . ... . ... . ... . ... .
i ... . ... . ... . m[i, j]

Declaración de arreglos bidimensionales


Al igual que en los arreglos unidimensionales, los arreglos bidimensionales también se pueden crear con
declaraciones de variable o de tipo, el cambio, es que se debe indicar dos intervalos de índices: uno para las
filas y otro para las columnas. Estos intervalos o subrangos no tienen que ser de la misma dimensión.
• Declaración por variable
La sintaxis a utilizar será:
var
array [li..ls, li..ls] de <tipo_de_dato> : <nombre_de_la_matriz>
Ejemplo:
const
n = 51
m = 28
var
array [1..5, 1..6] de entero : arregloA
array [0..20, 0..3] de real : arregloB, arregloC
array [7..14, 1..5] de lógico : arregloD
array [-6..n, m..n] de caracter : arregloE
• Declaración por tipo
La sintaxis a utilizar será:
tipo
array [li..ls, li..ls] de <tipo_de_dato> : <nombre_del_tipo>
var
<nombre_del_tipo> : <nombre_de_la_matriz>
Ejemplo:
const
n = 51
m = 28
tipo
array [1..5, 1..6] de entero : matrizA

37
Apuntes de algoritmos

array [0..20, 0..3] de real : matrizB


array [7..14, 1..5] de lógico : matrizC
array [-6..n, m..n] de caracter : matrizD
var
matrizA : arregloA
matrizB : arregloB, arregloC
matrizC : arregloD
matrizD : arregloE

5.2.4. Recorrido de todos lo elementos del arreglo


Esta operación se realiza cuando se utiliza una estructura de control iterativa para tratar todos y cada uno de
los elementos del arreglo de acuerdo al orden en que se almacenan. El tratamiento es el mismo para todo el
arreglo, y se aplica tanto cuando se desea leer el arreglo, buscar un elemento en un arreglo, listar todo el
contenido del mismo, y muchos otros.
El recorrido puede ser de manera ascendente (el más utilizado), partiendo del límite inferior hasta el superior
e incrementando en uno; o de manera descendente, partiendo del límite superior hasta el inferior y
decrementando en uno.
La estructura de control desde es la más conveniente para realizar de manera el recorrido, indicando solo el
limite inferior y superior, pues el incremento en uno del índice es automático. Sin embargo, si existiera
alguna condición adicional o si se necesita usar una condición lógica para finalizar el recorrido, no basta con
llegar al límite superior del índice, hay que cambiar de la estructura iterativa desde, y utilizar un mientras o
un repetir.
• Recorrido por filas
Supuestas las siguientes declaraciones:
const
f = <valor1>
c = <valor2>
tipo
array [1..f, 1..c] de real : matriz
var
matriz : m
y que todos los elementos de la matriz contienen información válida, escribir el pseudocódigo que se
visualice en primer lugar el contenido de los elementos de la primera fila, a continuación el contenido de
la segunda, etc.
desde i  1 hasta f hacer
desde j  1 hasta c hacer
escribir([i, j])
fin_desde
fin_desde
• Recorrido por columnas
Tal y como aparece a continuación, se mostrará el contenido de los elementos de la primera columna,
luego el de la segunda, etc.
desde j  1 hasta c hacer
desde i  1 hasta f hacer
escribir([i, j])
fin_desde
fin_desde
Para recorrer los elementos de una matriz de n dimensiones, se utilizará n estructuras repetitivas
anidadas.

38
Apuntes de algoritmos

5.2.5. Arreglos como parámetros


Los arreglos podrán ser pasados como parámetros, tanto a procedimientos como a funciones. Para ellos se
debe declarar algún parámetro formal del misto tipo que el arreglo que constituye el parámetro actual.
Ejemplo:
algoritmo paso_de_arreglos

const
f = 5
c = 7
tipo
array [1..f, 1..c] de real : arr
var
arr : a
entero : b
...
inicio
...
b  recibeArreglo(a)
...
fin

entero función recibeArreglo(E arr: m)


// Los parámetros actuales y los formales no necesitan coincidir en el nombre
inicio
...
...
fin_función

5.3. Registros
Estructura de datos formada por una colección finita de elementos llamados campos, no necesariamente
homogéneos (del mismo tipo) y que permiten almacenar una serie de datos relacionados entre sí bajo un
nombre y una estructura común.

5.3.1. Características básicas de los registros


• Permiten almacenar un grupo de elementos bajo un nombre y un estructura común
• Los elementos (campos) de un registro no tienen que ser homogéneos, de hecho, generalmente son de
diferentes tipos
• No están disponibles en todos los lenguajes de programación, razón por la cual muchas veces es
necesario simularlo o definirlo.
• Cada campo del registro se comporta como una variable simple, de manera que puede ser usado en una
expresión de asignación, como parte de otra expresión, en operaciones o como parámetro al invocar una
acción o función.

5.3.2. Declaración de registros


• Declaración por variable. se declara la variable de tipo registro identificándola a través de su nombre,
se indica la estructura del registro suministrando la definición de sus campos mediante sus tipos de dato
y sus nombres
La sintaxis a utilizar para declarar un registro será:

39
Apuntes de algoritmos

var
registro : <nombre_de_la_variable>
<tipo_de_dato1> : <nombre_de_campo1> [,<nombre_de_campo1>] [...]
<tipo_de_dato1> : <nombre_de_campo1> [,<nombre_de_campo1>] [...]
<tipo_de_dato1> : <nombre_de_campo1> [,<nombre_de_campo1>] [...]
fin_registro
• Declaración por tipo: Al igual que con los arreglos, para declarar un tipo de registro definido por el
usuario, se antecede a la especificación la palabra clave Tipo y luego se definen las variables del tipo. El
uso de la declaración por tipo facilita la declaración de variables con una estructura común, así como el
pase de parámetros.
tipo
registro : <nombre_del_tipo>
<tipo_de_dato1> : <nombre_de_campo1> [,<nombre_de_campo1>] [...]
<tipo_de_dato1> : <nombre_de_campo1> [,<nombre_de_campo1>] [...]
<tipo_de_dato1> : <nombre_de_campo1> [,<nombre_de_campo1>] [...]
fin_registro
Para declarar una variable de tipo registro:
var
<nombre_del_tipo> : <nombre_de_la_variable>
Para acceder a un determinado campo de un registro se utilizará, como suelen emplear la mayoría de los
lenguajes el nombre de la variable del tipo de registro unido por un punto al nombre del campo.
<nombre_de_la_variable>.<nombre_de_campo1>
Si los campos del registro fueran a su vez otros registros habrá que indicar:
<nombre_de_la_variable>.<nombre_de_campo1>.<nombre_de_campo_de_campo1>
Los datos de tipo registro se pueden pasar como parámetros tanto a procedimientos como a funciones.

5.3.3. Arreglos de registros


Los elementos de un arreglo pueden ser de cualquier tipo, por lo tanto es posible la construcción de arreglos
de registros.
Nombre ..Edad.. ..Edad..
“Ana” 28 a[1]
“Carlos” 36 a[2]
... ... ...
“Juan” 34 n[n]

Para acceder al campo nombre del 2do elemento del arreglo a se escribiría a[2].nombre. Por ejemplo:
escribir(a[2].nombre)
presentaría en consola la cadena Carlos.

5.4. Cadenas de caracteres


Es un conjunto de 0 ó más caracteres. Entre estos caracteres puede estar incluido el blanco.
En pseudocódigo, el blanco es el b. Las cadenas de caracteres se delimitan con dobles comillas “ ”, pero en
algunos lenguajes se delimitan con ‘ ’.
Las cadenas de caracteres se almacenan en posiciones contiguas de memoria.

40
Apuntes de algoritmos

La longitud de una cadena es el número de caracteres de la misma. Si hubiese algún carácter que se utilizara
como especial para señalar el fin de cadena, no se consideraría en la longitud.
Si una cadena tiene longitud 0, la llamamos cadena nula por lo que no tiene ningún carácter, pero esto no
quiere decir que no tenga ningún carácter válido, por que puede haber algún carácter especial no imprimible
que forme parte de la cadena.
Una subcadena es una cadena extraída de otra.

5.4.1. Datos de tipo caracter


• Constantes. Una constante de tipo cadena es un conjunto de 0 o más caracteres encerrados entre “ ”.
Si dentro de la cadena quiero poner como parte de la cadena las “, las pongo 2 veces. Esto depende del
lenguaje.
“Hola””Adios”  Hola”Adios
Una constante de tipo carácter es un solo carácter encerrado entre comillas simples.
• Variables. Hay que distinguir entre una variable de tipo carácter y una variable de tipo cadena, el
contenido de una variable de tipo cadena es un conjunto de 0 ó más caracteres encerrados entre “ ”,
mientras que una variable de tipo carácter es un solo carácter encerrado entre ‘ ’.

5.4.2. Formas de almacenamiento de cadenas en memoria


• Almacenamiento estático. La longitud de la cadena se tiene que definir antes de ser usada y siempre
va a tener esa longitud, almacenándose en posiciones contiguas de memoria. Si la cadena no ocupa
todo el espacio, el resto se rellena con blancos, y esos blancos se consideran parte de la cadena. Esto
es muy deficiente y no se usa casi en ningún lenguaje.
• Almacenamiento semiestático. Antes de usar la cadena, hay que declarar la longitud máxima que
puede tener y ese es el espacio que se reserva en memoria para almacenar la cadena, siempre en
posiciones contiguas. La longitud real de la cadena durante la ejecución puede variar aunque siempre
tiene que ser menor que el máximo de la cadena.
• Almacenamiento dinámico. No hay que definir la longitud de la cadena antes de usarla, ni siquiera la
máxima. Para esto, se utiliza la memoria dinámica, y para establecer el número de elementos de la
cadena usaremos listas enlazadas en las que cada nodo de la lista contara un carácter de la cadena y se
enlazaría mediante punteros. La información no tiene que estar almacenada en posiciones contiguas de
memoria.

5.4.3. Operaciones con cadenas


Al igual que con cualquier tipo de datos, podemos hacer operaciones de entrada y salida (leer y escribir).
var
cadena : cad
...
leer(cad)
escribir(cad)
Aparte de estas instrucciones, la mayor parte de los lenguajes permiten realizar operaciones especiales con
las variables de tipo cadena. La mayor parte de los lenguajes tienen operaciones de tratamiento de cadenas,
y esas operaciones vienen en librerías externas.
Las operaciones más usadas son:
• Longitud de una cadena. Es una función a la que se le pasa una cadena como parámetro y como
resultado devuelve su longitud.
entero función longitud(cadena : c)

41
Apuntes de algoritmos

• Comparación de cadenas. Esta operación se puede realizar porque lo que se va a comparar son los
valores ASCII asociados a cada carácter.
entero función comparación(cadena : c1, c2)
Esta función devuelve:
0 si c1 = c2
Un positivo si c1 > c2
Un negativo si c1 < c2
• Concatenación. Permite unir varias cadenas en una sola, manteniendo el orden de los caracteres que
se unen.
En pseudocódigo se usa el símbolo & ó +.
Ejemplo:
cadena1  “Hola”
cadena2  “Adios”
cadena3  cadena1 & “ ” + cadena2
escribir(cadena3)
por consola aparecerá “Hola Adios”
• Extracción de subcadenas. Extrae parte de una cadena.
cadena función subcadena(cadena : c; entero : ini[; entero : long])
Devuelve una subcadena de la cadena c formada por todos los caracteres a partir de la posición ini. Si
se incluye el argumento long, devuelve sólo los primeros long caracteres a partir de la posición ini.
• Posición. Una operación frecuente a realizar con cadenas es localizar si una determinada cadena forma
parte de otra cadena más grande o buscar la posición en que aparece un determinado carácter o
secuencia de caracteres de un texto. Estos problemas pueden resolverse con la función posición.
entero función posición(cadena : c, sc)
Devuelve la posición de la primera aparición de la subcadena sc en la cadena c.
• Conversión de cadenas a números. Es una función que se le pasa una cadena caracteres numéricos y
devuelve el número asociado.
entero función valor(cadena : c)
Convierte la cadena c a un valor numérico. Si el contenido de la cadena c no puede convertirse a un
valor numérico (contiene caracteres alfabéticos, signos de puntuación inválidos, etc.), devuelve 0
• Conversión de números a cadenas. Es una función a la que se le pasa un número y lo convierte a una
cadena.
cadena función cadena(entero : x)
Convierte a cadena el valor numérico x.
• Función que devuelve el carácter ASCII de un número
caracter función caracter(entero : x)
Devuelve el carácter correspondiente al código ASCII x.
• Función que devuelve el número asociado de un carácter ASCII:
entero función código(cadena : car)
Devuelve el código ASCII del carácter car.

42
Apuntes de algoritmos

6. Introducción a la programación orientada a


objetos
La programación Orientada a Objetos es una metodología que basa la estructura de los programas en torno a
los objetos.
Los lenguajes de POO ofrecen medios y herramientas para describir los objetos manipulados por un programa.
Más que describir cada objeto individualmente, estos lenguajes proveen una construcción (Clase) que describe
a un conjunto de objetos que poseen las mismas propiedades.

6.1. Objeto
Es una entidad (tangible o intangible) que posee características y acciones que realiza por sí solo o
interactuando con otros objetos.
Un objeto es una entidad caracterizada por sus atributos propios y cuyo comportamiento está determinado por
las acciones o funciones que pueden modificarlo, así como también las acciones que requiere de otros objetos.
Un objeto tiene identidad e inteligencia y constituye una unidad que oculta tanto datos como la descripción de
su manipulación. Puede ser definido como una encapsulación y una abstracción: una encapsulación de
atributos y servicios, y una abstracción del mundo real.
Para el contexto de la POO un objeto es una entidad que encapsula datos (atributos) y acciones o funciones
que los manejan (métodos). También para la POO un objeto se define como una instancia o particularización de
una clase.
Los objetos de interés durante el desarrollo de software no sólo son tomados de la vida real (objetos visibles o
tangibles), también pueden ser abstractos. En general son entidades que juegan un rol bien definido en el
dominio del problema. Un libro, una persona, un carro, un polígono, son apenas algunos ejemplos de objeto.
Cada objeto puede ser considerado como un proveedor de servicios utilizados por otros objetos que son sus
clientes. Cada objeto puede ser a al vez proveedor y cliente. De allí que un programa pueda ser visto como un
conjunto de relaciones entre proveedores clientes. Los servicios ofrecidos por los objetos son de dos tipos:
• Los datos, que llamamos atributos.
• Las acciones o funciones, que llamamos métodos.

Características generales
• Un objeto se identifica por un nombre o un identificador único que lo diferencia de los demás.
Ejemplo: el objeto Cuenta de Ahorros número 12345 es diferente al objeto Cuenta de Ahorros número
25789. En este caso el identificador que los hace únicos es el número de la cuenta.
• Un objeto posee estados. El estado de un objeto está determinado por los valores que poseen sus
atributos en un momento dado.
• Un objeto tiene un conjunto de métodos. El comportamiento general de los objetos dentro de un
sistema se describe o representa mediante sus operaciones o métodos. Los métodos se utilizarán para
obtener o cambiar el estado de los objetos, así como para proporcionar un medio de comunicación entre
objetos.
• Un objeto tiene un conjunto de atributos. Los atributos de un objeto contienen valores que determinan
el estado del objeto durante su tiempo de vida. Se implementan con variables, constantes y estructuras
de datos (similares a los campos de un registro).
• Los objetos soportan encapsulamiento. La estructura interna de un objeto normalmente está oculta a
los usuarios del mismo. Los datos del objeto están disponibles solo para ser manipulados por los propios
métodos del objeto. El único mecanismo que lo conecta con el mundo exterior es el paso de mensajes.

43
Apuntes de algoritmos

• Un objeto tiene un tiempo de vida dentro del programa o sistema que lo crea y utiliza. Para ser
utilizado en un algoritmo el objeto debe ser creado con una instrucción particular (New ó Nuevo) y al
finalizar su utilización es destruido con el uso de otra instrucción o de manera automática.

6.2. Clase
La clase es la unidad de modularidad en la POO. La tendencia natural del individuo es la de clasificar los
objetos según sus características comunes (clase). Por ejemplo, las personas que asisten a la universidad se
pueden clasificar (haciendo abstracción) en estudiante, docente, empleado e investigador.
La clase puede definirse como la agrupación o colección de objetos que comparten una estructura común y un
comportamiento común.
Es una plantilla que contiene la descripción general de una colección de objetos. Consta de atributos y métodos
que resumen las características y el comportamiento comunes de un conjunto de objetos.
Todo objeto (también llamado instancia de una clase), pertenece a alguna clase. Mientras un objeto es una
entidad concreta que existe en el tiempo y en el espacio, una clase representa solo una abstracción.
Todos aquellos objetos que pertenecen a la misma clase son descritos o comparten el mismo conjunto de
atributos y métodos. Todos los objetos de una clase tienen el mismo formato y comportamiento, son diferentes
únicamente en los valores que contienen sus atributos. Todos ellos responden a los mismos mensajes.

Características generales
Una clase es un nivel de abstracción alto. La clase permite describir un conjunto de características comunes
para los objetos que representa. Ejemplo: La clase Avión se puede utilizar para definir los atributos (tipo de
avión, distancia, altura, velocidad de crucero, capacidad, país de origen, etc.) y los métodos (calcular
posición en el vuelo, calcular velocidad de vuelo, estimar tiempo de llegada, despegar, aterrizar, volar, etc.)
de los objetos particulares Avión que representa.
• Un objeto es una instancia de una clase. Cada objeto concreto dentro de un sistema es miembro de
una clase específica y tiene el conjunto de atributos y métodos especificados en la misma.
• Las clases se relacionan entre sí mediante una jerarquía. Entre las clases se establecen diferentes
tipos de relaciones de herencia, en las cuales la clase hija (subclase) hereda los atributos y métodos de
la clase padre (superclase), además de incorporar sus propios atributos y métodos.
Ejemplos:
Superclase: Clase Avión
Subclases de Avión: Clase Avión Comercial, Avión de Combate, Avión de Transporte.
• Los nombres o identificadores de las clases deben colocarse en singular (clase Animal, clase Carro,
clase Alumno).

6.3. Relación entre clase y objeto


Algorítmicamente, las clases son descripciones netamente estáticas o plantillas que describen objetos. Su
rol es definir nuevos tipos conformados por atributos y operaciones.
Por el contrario, los objetos son instancias particulares de una clase. Las clases son una especie de molde
de fábrica, en base al cual son construidos los objetos. Durante la ejecución de un programa sólo existen los
objetos, no las clases.
La declaración de una variable de una clase NO crea el objeto.

44
Apuntes de algoritmos

La asociación siguiente: <nombre_clase> : <nombre_variable> (por ejemplo, Rectángulo : R), no


genera o no crea automáticamente un objeto Rectángulo. Sólo indica que R será una referencia o una variable
de objeto de la clase Rectángulo.
La creación de un objeto, debe ser indicada explícitamente por el programador, de forma análoga a como
inicializamos las variables con un valor dado, sólo que para los objetos se hace a través de un método
Constructor (ver punto Métodos).

6.4. Atributos
Son los datos o variables que caracterizan al objeto y cuyos valores en un momento dado indican su estado.
Un atributo es una característica de un objeto. Mediante los atributos se define información oculta dentro de un
objeto, la cual es manipulada solamente por los métodos definidos sobre dicho objeto
Un atributo consta de un nombre y un valor. Cada atributo está asociado a un tipo de dato, que puede ser
simple (entero, real, lógico, carácter, cadena) o estructurado (arreglo, registro, archivo, lista, etc.).
Los modos de acceso son:
• Público. Atributos (o Métodos) que son accesibles fuera de la clase. Pueden ser llamados por cualquier
clase, aun si no está relacionada con ella. Este modo de acceso también se puede representar con el
símbolo +.
• Privado. Atributos (o Métodos) que sólo son accesibles dentro de la implementación de la clase. También
se puede representar con el símbolo –.
• Protegido. Atributos (o Métodos) que son accesibles para la propia clase y sus clases hijas (subclases).
También se puede representar con el símbolo #.

6.5. Métodos
Son las operaciones (acciones o funciones) que se aplican sobre los objetos y que permiten crearlos, cambiar
su estado o consultar el valor de sus atributos.
Los métodos constituyen la secuencia de acciones que implementan las operaciones sobre los objetos. La
implementación de los métodos no es visible fuera de objeto.
Ejemplo: Un rectángulo es un objeto caracterizado por los atributos Largo y Ancho, y por varios métodos, entre
otros Calcular su área y Calcular su perímetro.

Características generales
• Cada método tiene un nombre, cero o más parámetros (por valor o por referencia) que recibe o devuelve
y un algoritmo con el desarrollo del mismo.
• En particular se destaca el método constructor, que no es más que el método que se ejecuta cuando el
objeto es creado. Este constructor tiene el mismo nombre de la clase/ objeto, recibe cero o más
parámetros y lo usual es que inicialicen los valores de los atributos del objeto.
• En lenguajes como Java y C++ se puede definir más de un método constructor, que normalmente se
diferencian entre sí por la cantidad de parámetros que reciben.
• Los métodos se ejecutan o activan cuando el objeto recibe un mensaje, enviado por un objeto o clase
externo al que lo contiene, o por el mismo objeto de manera local.

45
Apuntes de algoritmos

Creación de objetos y métodos constructores


Cada objeto o instancia de una clase debe ser creada explícitamente a través de un método u operación
especial denominado constructor. Los atributos de un objeto toman valores iniciales dados por el
constructor. Por convención el método constructor tiene el mismo nombre de la clase y no se le asocia un
modo de acceso (es público).
Algunos lenguajes proveen un método constructor por defecto para cada clase y/o permiten la definición de
más de un método constructor. En la notación algorítmica, definimos obligatoriamente un único método
constructor de la clase.

Método de destructores de objetos


Los objetos que ya no son utilizados en un programa, ocupan inútilmente espacio de memoria, que es
conveniente recuperar en un momento dado. Según el lenguaje de programación utilizado esta tarea es
dada al programador o es tratada automáticamente por el procesador o soporte de ejecución del lenguaje.
En la notación algorítmica NO tomaremos en cuenta ese problema de administración de memoria, por lo
tanto no definiremos formas para destruir objetos. En cambio al utilizar lenguajes de programación si
debemos conocer los métodos destructores suministrados por el lenguaje y utilizarlos a fin de eliminar
objetos una vez no sean útiles.

6.6. Mensaje
Es la petición de un objeto a otro para solicitar la ejecución de alguno de sus métodos o para obtener el valor de
un atributo público.
Estructuralmente, un mensaje consta de 3 partes:
• Identidad del receptor. Nombre del objeto que contiene el método a ejecutar.
• Nombre del método a ejecutar. Solo los métodos declarados públicos.
• Lista de Parámetros que recibe el método (cero o mas parámetros)
Cuando el objeto receptor recibe el mensaje, comienza la ejecución del algoritmo contenido dentro del método
invocado, recibiendo y/o devolviendo los valores de los parámetros correspondientes, si los tiene ya que son
opcionales:

6.7. Diagrama de clases


La representación gráfica de una o varias clases se hará mediante los denominados Diagramas de Clase. Para
los diagramas de clase se utilizará la notación que provee el Lenguaje de Modelación Unificado (UML, ver
www.omg.org), a saber:
• Las clases se denotan como rectángulos divididos en tres partes. La primera contiene el nombre de la
clase, la segunda contiene los atributos y la tercera los métodos.
• Los modificadores de acceso a datos y operaciones, a saber: público, protegido y privado; se representan
con los símbolos +, # y – respectivamente, al lado derecho del atributo. (+ público, # protegido, - privado).
En la figura se muestra el método “color” que no tiene ningún parámetro y retorna un valor entero y el método
“modificar_tamaño” que tiene un real como parámetro y no retorna nada (es una acción).

46
Apuntes de algoritmos

Notación: Ejemplo
Nombre Clase ventana
+ real : área
Atributos # lógico : visible
+ ventana(E real : a; E lógico : v)
Métodos + entero mostrarColor()
+ modificarTamaño(E real : porcentaje)

6.8. Relaciones entre clases


Las clases no se construyen para que trabajen de manera aislada, la idea es que ellas se puedan relacionar
entre sí, de manera que puedan compartir atributos y métodos sin necesidad de rescribirlos.
La posibilidad de establecer jerarquías entre las clases es una característica que diferencia esencialmente la
programación orientada a objetos de la programación tradicional, ello debido fundamentalmente a que permite
extender y reutilizar el código existente sin tener que rescribirlo cada vez que se necesite.
Los cuatro tipos de relaciones entre clases estudiados en este curso serán:
• Herencia (Generalización / Especialización o Es-un)
• Agregación (Todo / Parte o Forma-parte-de)
• Composición (Es parte elemental de)
• Asociación (entre otras, la relación Usa-a)
Existen otros tipos de relaciones:
• Realización.
• Dependencia.

6.8.1. Relación de herencia (generalización / especialización, es un)


Es un tipo de jerarquía de clases, en la que cada subclase contiene los atributos y métodos de una (herencia
simple) o más superclases (herencia múltiple).
Mediante la herencia las instancias de una clase hija (o subclase) pueden acceder tanto a los atributos como
a los métodos públicos y protegidos de la clase padre (o superclase).
Cada subclase o clase hija en la jerarquía es siempre una extensión (esto es, conjunto estrictamente más
grande) de la(s) superclase(s) o clase(s) padre(s) y además incorporar atributos y métodos propios, que a su
vez serán heredados por sus hijas.
• En la notación algorítmica se coloca el nombre de la clase padre después de la frase Hereda de del
encabezado de la clase y se usan sus atributos y métodos públicos o protegidos.
Ejemplo: clase alumno hereda_de persona
• En el diagrama de clases, la herencia se representa mediante una relación de
generalización/especificación, que se denota de la siguiente forma:

subclase superclase

clase hija clase padre

47
Apuntes de algoritmos

6.8.2. Clase abstracta


Una clase abstracta es aquella que construimos para derivar de ella otras clases, pero de la que no se
puede instanciar. Por ejemplo, la clase animal, no existe como tal en la naturaleza, no existe ningún ser que
sea tan solo animal (no hay ninguna instanciación directa de esa clase), existen humanos, gatos, conejos,
etc. Todos ellos son animales, pero no existe un ser vivo que sea solo animal.
• En la notación algorítmica se coloca el nombre la palabra abstracto delante del nombre de la clase.
Ejemplo: abstracto clase persona
Ejemplo: El siguiente diagrama de clases muestra la relación de Herencia entre la clase animal y sus hijas.
La clase animal es abstracta.

6.8.3. Relación de agregación (todo / parte, forma parte de)


Es una relación que representa a los objetos compuestos por otros objetos. Indica Objetos que a su vez
están formados por otros. El objeto en el nivel superior de la jerarquía es el todo y los que están en los
niveles inferiores son sus partes o componentes.
La relación forma parte de, no es más que una asociación, que se denota:
Multiplicidad
Nombre del objeto Nombre del objeto
de nivel superior que lo compone
4 .. *
carro ruedas

Si motor forma parte de carro, la flecha apunta a la clase motor, y el diamante va pegado a carro.
La multiplicidad es el rango de cardinalidad permitido que puede asumir la asociación, se denota LI..LS. Se
puede usar * en el limite superior para representar una cantidad ilimitada (ejemplo: 3..*).
Ejemplo: Objeto Casa descrito en términos de sus componentes

48
Apuntes de algoritmos

6.8.4. Relación de composición


Un componente es parte esencial de un elemento.
La relación es más fuerte que el caso de agregación, al punto que si el componente es eliminado o
desaparece, la clase mayor deja de existir.
La relación de composición, se denota de la siguiente forma:

clase mayor clase componente

persona corazón

6.8.5. Relación de asociación («uso», usa, cualquier otra relación)


Es una asociación que se establece cuando dos clases tienen una dependencia de utilización, es decir, una
clase utiliza atributos y/o métodos de otra para funcionar. Estas dos clases no necesariamente están en
jerarquía, es decir, no necesariamente una es clase padre de la otra, a diferencia de las otras relaciones de
clases.
El ejemplo mas común de esta relación es de objetos que son utilizados por los humanos para alguna
función, como Lápiz (se usa para escribir), tenedor (se usa para comer), silla (se usa para sentarse), etc.
Otro ejemplo son los objetos Cajero y Cuenta. El Cajero “usa a” la cuenta para hacer las transacciones de
consulta y retiro y verificar la información del usuario.
La relación de uso, se denota con una dependencia estereotipada:
usa a
clase 1 clase 2

Ejemplos:

49
Apuntes de algoritmos

7. Fundamentos del enfoque orientado a objeto


El Enfoque Orientado a Objeto se basa en cuatro principios que constituyen la base de todo desarrollo
orientado a objetos. Estos principios son: Abstracción, Encapsulamiento, Modularidad y Herencia.
Otros elementos a destacar (aunque no fundamentales) en la POO son: Polimorfismo, Enlace dinámico (o
binding), Concurrencia y Persistencia.

7.1. Abstracción
Es el principio de ignorar aquellos aspectos de un fenómeno observado que no son relevantes, con el
objetivo de concentrarse en aquellos que si lo son. Una abstracción denota las características esenciales de
un objeto (datos y operaciones), que lo distingue de otras clases de objetos. Decidir el conjunto correcto de
abstracciones de un determinado dominio, es el problema central del diseño orientado a objetos.
Los mecanismos de abstracción son usados en la POO para extraer y definir del medio a modelar, sus
características y su comportamiento. Dentro de la POO son muy usados mecanismos de abstracción:
Generalización, Agregación y clasificación.

7.1.1. Generalización
Es el mecanismo de abstracción mediante el cual un conjunto de clases de objetos son agrupadas en una
clase de nivel superior (Superclase), donde las semejanzas de las clases constituyentes (Subclases) son
enfatizadas, y las diferencias entre ellas son ignoradas. En consecuencia, a través de la generalización, la
superclase almacena datos generales de las subclases, y las subclases almacenan sólo datos particulares.
La especialización es lo contrario de la generalización. La clase Médico es una especialización de la clase
Persona, y a su vez, la clase Pediatra es una especialización de la superclase Médico.

7.1.2. Agregación
Es el mecanismo de abstracción por el cual una clase de objeto es definida a partir de sus partes (otras
clases de objetos). Mediante agregación se puede definir por ejemplo un computador, por descomponerse
en: la CPU, la ULA, la memoria y los dispositivos periféricos. El contrario de agregación es la
descomposición.

7.1.3. Clasificación
Consiste en la definición de una clase a partir de un conjunto de objetos que tienen un comportamiento
similar. La ejemplificación es lo contrario a la clasificación, y corresponde a la instanciación de una clase,
usando el ejemplo de un objeto en particular.

7.2. Encapsulamiento (ocultamiento de información)


Es la propiedad de la POO que permite ocultar al mundo exterior la representación interna del objeto. Esto
quiere decir que el objeto puede ser utilizado, pero los datos esenciales del mismo no son conocidos fuera de
él.
La idea central del encapsulamiento es esconder los detalles y mostrar lo relevante. Permite el ocultamiento de
la información separando el aspecto correspondiente a la especificación de la implementación; de esta forma,
distingue el "qué hacer" del "cómo hacer". La especificación es visible al usuario, mientras que la
implementación se le oculta.

50
Apuntes de algoritmos

El encapsulamiento en un sistema orientado a objeto se representa en cada clase u objeto, definiendo sus
atributos y métodos con los siguientes modos de acceso:
• Público (+). Atributos o Métodos que son accesibles fuera de la clase. Pueden ser llamados por cualquier
clase, aun si no está relacionada con ella.
• Privado (-). Atributos o Métodos que solo son accesibles dentro de la implementación de la clase.
• Protegido (#). Atributos o Métodos que son accesibles para la propia clase y sus clases hijas (subclases).
Los atributos y los métodos que son públicos constituyen la interfaz de la clase, es decir, lo que el mundo
exterior conoce de la misma.
Normalmente lo usual es que se oculten los atributos de la clase y solo sean visibles los métodos, incluyendo
entonces algunos de consulta para ver los valores de los atributos. El método constructor (Nuevo, New) siempre
es Público.

7.3. Modularidad
Es la propiedad que permite tener independencia entre las diferentes partes de un sistema. La modularidad
consiste en dividir un programa en módulos o partes, que pueden ser compilados separadamente, pero que
tienen conexiones con otros módulos. En un mismo módulo se suele colocar clases y objetos que guarden una
estrecha relación. El sentido de modularidad está muy relacionado con el ocultamiento de información.

7.4. Herencia
Es el proceso mediante el cual un objeto de una clase adquiere propiedades definidas en otra clase que lo
preceda en una jerarquía de clasificaciones. Permite la definición de un nuevo objeto a partir de otros,
agregando las diferencias entre ellos (Programación Diferencial), evitando repetición de código y permitiendo la
reusabilidad.
Las clases heredan los datos y métodos de la superclase. Un método heredado puede ser sustituido por uno
propio si ambos tienen el mismo nombre.
La herencia puede ser simple (cada clase tiene sólo una superclase) o múltiple (cada clase puede tener
asociada varias superclases). La clase Docente y la clase Estudiante heredan las propiedades de la clase
Persona (superclase, herencia simple). La clase Preparador (subclase) hereda propiedades de la clase Docente
y de la clase Estudiante (herencia múltiple).
Cuando se desea indicar invocar a un método que pertenece a la clase madre, lo indicamos con la siguiente
sintaxis:
super.nombre_método()
Para el ejemplo, la llamada en la clase hija ave del método comer de la clase madre animal sería:
super.comer()

7.5. Polimorfismo
Es una propiedad de la POO que permite que un método tenga múltiples implementaciones, que se seleccionan
en base al tipo objeto indicado al solicitar la ejecución del método.
El polimorfismo operacional o sobrecarga operacional permite aplicar operaciones con igual nombre a
diferentes clases o están relacionados en términos de inclusión. En este tipo de polimorfismo, los métodos son
interpretados en el contexto del objeto particular, ya que los métodos con nombres comunes son
implementados de diferente manera dependiendo de cada clase.

51
Apuntes de algoritmos

Por ejemplo, el área de un cuadrado, rectángulo y círculo, son calculados de manera distinta; sin embargo, en
sus clases respectivas puede existir la implementación del área bajo el nombre común Área. En la práctica y
dependiendo del objeto que llame al método, se usará el código correspondiente.
Ejemplo: superclase: clase animal subclases: clases perro, ave, pez
Se puede definir un método comer en cada subclase, cuya implementación cambia de acuerdo a la clase
invocada, sin embargo el nombre del método es el mismo.
perro.comer() ≠ ave.comer() ≠ pez.comer()
Otro ejemplo de polimorfismo es el operador +. Este operador tiene dos funciones diferentes de acuerdo al tipo
de dato de los operandos a los que se aplica. Si los dos elementos son numéricos, el operador + significa suma
algebraica de los mismos, en cambio si por lo menos uno de los operandos es un String o Carácter, el operador
es la concatenación de cadenas de caracteres.
Otro ejemplo de sobrecarga es cuando tenemos un método definido originalmente en la clase madre, que ha
sido adaptado o modificado en la clase hija. Por ejemplo, un método comer para la clase animal y otro comer
que ha sido adaptado para la clase ave, quien está heredando de la clase animal.
Para poder realizar la adaptación o modificación del método en la clase hija, debe estar declarado como método
abstracto en la clase madre.
Ejemplo: abstracto publico entero función mostrarCedula()

52
Apuntes de algoritmos

8. Ejemplos

8.1. Expresiones
Determinar el valor de la variable A.
a. A  (3 * 2 ^ 5 mod 1 + 8 * (3 - 5) < (2 + 8 - 1 mod 1)
A  (3 * 32 mod 1 + (-16)) < 10
A  -16 < 10
A  Verdadero
b. A  A o ( 3 + 5 * 8) < 3 y ((-6 / 3 div 4) * 2 < 2)
A  Verdadero o 43 < 3 y (0 * 2 < 2)
A  Verdadero o Falso y Verdadero
A  Verdadero o Falso
A  Verdadero

8.2. Diagramas de flujo


a. Establezca la codificación que amerite la su solución de los siguientes diagramas de flujo:

inicio

num = 1

suma = 0

“Ingresar número: ”

num

suma = suma + num

si no
num <> 0

“La suma es: ”, suma

fin

53
Apuntes de algoritmos

algoritmo ejemplo_8.2
var
entero : num, suma

inicio
num  1
suma  0
hacer
escribir(“Ingresar número: ”)
leer(num)
suma  suma + num
mientras (num <> 0)
escribir(“La suma es: ” + suma)
fin

8.3. Estructuras de selección


a. Escribir un procedimiento que aumenta Bs. 150 al sueldo de las personas que ganan Bs. 605 o menos.
algoritmo ejemplo_8.3.a
// Procedimiento para calcular el monto de un aumento de sueldo
var
real : sueldo

inicio
// se pide el valor del sueldo al usuario
escribir(“Suministre el monto del sueldo de la persona”)
// lee el sueldo actual del empleado
leer(sueldo)
// el condicional compara el sueldo del empleado
si (sueldo <= 605) entonces
// aumenta el sueldo del empleado
sueldo  sueldo + 150
// mensaje con el resultado
escribir(“El nuevo sueldo es: ” + sueldo)
fin_si
// Fin de la secuencia de instrucciones
fin

b. Crea una secuencia de instrucciones que calcule el monto de un aumento, a partir del sueldo del empleado
y su antigüedad (cantidad de años trabajados en la empresa). Para las personas que ganan hasta Bs. 500
se les aumenta 15% si tienen menos de 5 años de antigüedad en la empresa y 20% si tienen 5 ó más
años. Para los que ganan por encima de Bs. 500 hasta 2.500 se les aumenta 5% por cada 5 años de
antigüedad.
algoritmo ejemplo_8.3.b
{ Procedimiento para aumentar el sueldo según el monto del sueldo actual
y los años de servicio }
var
real : sueldo, aumento
entero : años, aux

inicio
escribir(“Suministre el sueldo y los años de antigüedad”)
// se solicitan y leen valores de entrada
leer(sueldo)
leer(años)
//contempla sueldo menores o iguales a 500

54
Apuntes de algoritmos

si (sueldo <= 500) entonces


{ este si anidado contempla la antigüedad para los que ganan hasta
Bs. 500 }
si (años < 5) entonces // trabajadores con menos de 5 años
// se calcula el monto del aumento, usando 15%
aumento  sueldo * 0,15
si_no
// se calcula el monto del aumento, usando 20%
aumento  sueldo * 0,2
fin_si
// contempla los que ganan más de 500
si_no
// ganan más de 500 y hasta 2.500
si (sueldo > 500 y sueldo <= 2.500) entonces
// calcula cuantas veces se le aplicará el aumento del 5%
aux  años div 5
// se calcula el monto del aumento
aumento  sueldo * (aux * 5) / 100
si_no
// no se aumenta el sueldo de los que ganan más de 2.500
aumento  0
fin_si
fin_si
si (aumento = 0) entonces
escribir(“Sueldo actual: ” + sueldo + “ gana más de 2.500”)
escribir(“no se contempló aumento”)
si_no
escribir(“Sueldo actual es ” + sueldo)
escribir(“Tiene una antigüedad de ” + años)
escribir(“Recibe aumento de ” + aumento)
escribir(“Su nuevo sueldo es ” + (sueldo + aumento))
fin_si
// Fin de la secuencia de instrucciones
fin

c. Dada una fecha en formato día/mes/año determinar el número de días y el nombre del mes de dicha fecha,
y sacar por pantalla la fecha convertida a formato de día “de” mes “de” año. Suponer que febrero siempre
tiene 28 días.
algoritmo ejemplo_8.3.c
var
entero : dia, mes, año, n_dias
cadena : n_mes

inicio
escribir(“Introduce la fecha en formato día mes año”)
leer(dia)
leer(mes)
leer(año)
según_sea (mes) hacer
1: n_mes  “enero”
n_dias  31
2: n_mes  “febrero”
n_dias  28
3: n_mes  “marzo”
n_dias  31
4: n_mes  “abril”
n_dias  30
5: n_mes  “mayo”

55
Apuntes de algoritmos

n_dias  31
6: n_mes  “junio”
n_dias  30
7: n_mes  “julio”
n_dias  31
8: n_mes  “agosto”
n_dias  31
9: n_mes  “septiembre”
n_dias  30
10: n_mes  “octubre”
n_dias  31
11: n_mes  “noviembre”
n_dias  30
12: n_mes  “diciembre”
n_dias  31
fin_según
escribir(“El mes de ” + n_mes + “ tiene ” + n_dias + “ dias”)
escribir(“La fecha es ” + n_dias + “ de ” + n_mes + “ de ” + año)
fin

8.4. Estructuras de repetición


a. Se desea sumar 35 números (pueden ser enteros o reales) suministrados por teclado y calcular su
promedio.
algoritmo ejemplo_8.4.a
// instrucciones para Sumar y Promediar
var
real : suma, promedio, num
entero : j

inicio
suma  0
desde j  1 hasta 35 hacer
escribir(“Suministre el nuevo número”)
leer(num)
suma  suma + num
fin_desde
promedio  suma / (j - 1)
escribir(“La suma de los números es ” + suma)
escribir(“El promedio de los números es ” + promedio)
fin

b. Dada la siguiente serie matemática:


a1 = 0
a2 = 0
an = an-1 + (2*an-2)
Determinar cual es el valor y el rango del primer término cuyo valor sea mayor o igual a 2000.
algoritmo ejemplo_8.4.b
var
entero : a1, a2, an, cont

inicio
cont  0
a1  1

56
Apuntes de algoritmos

a2  0
an  a1 + (2 * a2)
mientras (an < 2000) hacer
a2  a1
a1  an
an  a1 + (2 * a2)
cont  cont + 1
fin_mientras
escribir(“El rango es ” + cont + “ y el resultado es ” + an)
fin

c. Se desea conocer cuantas veces se repiten las vocales en un texto que el usuario suministra letra por letra
y que termina con ‘* ’
algoritmo ejemplo_8.4.c
var
entero : cantA, cantE, cantI, cantO, cantU
carácter : letra

inicio
cantA  0
cantE  0
cantI  0
cantO  0
cantU  0
escribir(“suministre la primera letra”)
leer(letra)
mientras (letra <> ‘*’) hacer
según_sea (letra) hacer
‘a’: cantA  cantA + 1
‘e’: cantE  cantE + 1
‘i’: cantI  cantI + 1
‘o’: cantO  cantO + 1
‘u’: cantU  cantU + 1
fin_según
escribir(“suministre próxima letra”)
leer(letra)
fin_mientras
escribir(“La cantidad de vocales A es ” + cantA)
escribir(“La cantidad de vocales E es ” + cantE)
escribir(“La cantidad de vocales U es ” + cantU)
fin

d. Calcule el promedio general de notas de un grupo de alumnos para una materia. Se sabe que la materia
tiene al menos un alumno. El usuario le indicará cuando terminó de suministrar todas las notas.
algoritmo ejemplo_8.4.d
var
real : nota, promedio
entero : numAlumnos
cadena : continuar

inicio
promedio  0
numAlumnos  1
continuar  “Si”
repetir
escribir(“Suministre la nota del alumno”)
leer(nota)

57
Apuntes de algoritmos

promedio  (promedio + nota) / numAlumnos


numAlumnos  numAlumnos + 1
// actualizo la variable de la condición de parada
escribir(“¿Desea suministrar otra nota? Indique Si ó No”)
leer(continuar)
hasta_que (continuar = “No”)
escribir(“El promedio general es ” + promedio)
fin

8.5. Funciones y procedimientos


a. Función sin pase de parámetros
entero función cantidadPalabrasLos()
{ solicita al usuario palabras, verifica si se suministra la palabra “los”
y en ese caso se cuenta. El algoritmo termina cuando se lea la palabra “fin” }
var
cadena : palabra
entero : cantLos
inicio
cantLos  0
escribir(“A continuación se le solicitarán palabras.)
escribir(“Suministre la palabra fin, para terminar el algoritmo”)
repetir
escribir(“Suministre una palabra”)
leer(palabra)
si (palabra = “los”) entonces
cantLos  cantLos + 1
fin_si
hasta_que (palabra = “fin”)
devolver(cantLos)
{ esta instrucción retorna o devuelve la cantidad de palabras al algoritmo
que llamo a esta función }
fin_función

b. Procedimientos y funciones con pase de parámetros


algoritmo ejemplo_8.5.b
{ Solicita una fecha de nacimiento y llama a acciones y funciones que hacen
varios cálculos con ella }
var
entero : diaNac, mesNac, añoNac, edad
cadena : nombre
lógico : esCorrecta, esBis, esMenorEdad
inicio
escribir(“suministra tu nombre”)
leer(nombre)

repetir
escribir(“suministra el día, mes y año de tu fecha de nacimiento”)
leer(diaNac)
leer(mesNac)
leer(añoNac)

// se llama a una función que verifica la fecha


esCorrecta  validarFecha(diaNac, mesNac, añoNac)

hasta_que (esCorrecta)

58
Apuntes de algoritmos

// se llama a una función que valida si el año de nacimiento fue bisiesto


esBis  validarBisieto(añoNac)

si no(esBis) entonces
escribir(“no naciste en un año Bisiesto”)
si_no
escribir(“Naciste en un año Bisiesto”)
fin_si

// calcula cuando cumple años


cumpleaños(nombre, diaNac, mesNac, añoNac)

edad  0
esMenorEdad  Falso

// calcula la edad y si es o no menor de edad


calcularEdad(añoNac, edad, esMenorEdad)

escribir(nombre + “ tu tienes ” + edad + “ años”)


fin

{ declaración formal de las funciones y procedimientos utilizados en el


algoritmo principal. En muchos lenguajes de programación estas declaraciones
formales deben estar ANTES del algoritmo que las llama. }

// verifica si el día (d), mes (m) y año (a) conforman una fecha válida
lógico función validarFecha(E entero : d, m, a)
var
lógico : correcta
inicio
correcta = verdadero;

// completa las instrucciones faltantes

devolver(correcta)
fin_función

// verifica si el año (a) es bisiesto


lógico función validarBisiesto(E entero : a)
devolver((a mod 4 = 0) y (a mod 100 <> 0) o (a mod 400 <> 0))
fin_función

{ verifica si ya la persona cumplió años. Este algoritmo supone que existen las
Funciones que devuelven el año, mes y día actual }
procedimiento cumpleaños(E cadena : nombre; E entero : dia, mes, año)
var
cadena : mensaje
entero : mesesFaltan
inicio
// 1er si, para la fecha de ejemplo añoActual() = 2007
si (año = añoActual()) entonces
mensaje  “todavía no has cumplido el primer añito”
// 2do si, ya cumplió años, para la fecha de ejemplo mesActual() = 6
si_no si (mes < mesActual()) entonces
mensaje  “ ya cumpliste años, felicitaciones atrasadas”
// 3er si, ya cumplió años, 3er si faltan = mes mod 12 + 1
si_no si (mes > mesActual()) entonces
mensaje  “ faltan aproximadamente ” + faltan +
“ para tu cumpleaños”

59
Apuntes de algoritmos

// 4to di, ya cumplió años, diaActual() = 4


si_no si (dia < diaActual()) entonces
mensaje  “ ya cumpliste años, felicitaciones atrasadas”
// 5to si, cumple años muy pronto, faltan = dia - 22
si_no si (dia > diaActual()) entonces
mensaje  “ alégrate sólo quedan ” + faltan
mensaje  mensaje + “ días para tu cumple”
si_no
mensaje  “ ¡¡¡Cumpleaños Feliz!!! muchos deseos de salud”
mensaje  mensaje + “ y prosperidad en tu día”
fin_si // cerrando si 5
fin_si // cerrando si 4
fin_si // cerrando si 3
fin_si // cerrando si 2
fin_si // cerrando si 1
escribir(nombre + mensaje)
fin_procedimiento

// Calcula la cantidad aproximada de años que tiene una persona


procedimiento calcularEdad(E entero : año; E/S entero : edad; E lógico : menor)
edad  añoActual() – año
menor  (edad < 18)
escribir(“¿La persona es menor de edad? ” + menor)
fin_procedimiento

c. Implementar un subprograma que me halle cual es la primera potencia en base 2 mayor que un número que
pasamos como parámetro, devolviendo el valor de dicha potencia y el exponente al que está elevado.
algoritmo ejemplo_8.5.c
var
entero : numero, resp1, resp2
inicio
escribir(“Introduce un número”)
leer(numero)
comprueba(numero, resp1, resp2)
escribir(“2^” + resp1 + “ = ” + resp2 + “ > ” + numero)
fin

procedimiento comprueba(E entero : num; E/S entero : n, pot)


var
entero : n
inicio
n 1
mientras (pot < n) hacer
pot  pot * 2
n  n+1
fin_mientras
fin_procedimiento

d. Calcular el primer término de la siguiente serie que sea mayor o igual a un valor V que se le pasa como
parámetro y me devuelva el lugar que ocupa en la serie y el valor.
Ai = 0
An = n + (An - 1)!
entero función factorial(E entero : num)
var
entero : i, acum
inicio
acum  1

60
Apuntes de algoritmos

desde i  1 hasta num hacer


acum  acum * i
fin_desde
devolver(acum)
fin_función

procedimiento serie(E entero : v; E/S entero : an, n)


var
entero : a1
inicio
a1  0
an  0
n  1
mientras (an <= v) hacer
n  n+1
an  n + factorial(a1)
a1  an
fin_mientras
fin_procedimiento

e. ¿Qué se escribe en pantalla tras la siguiente ejecución?


algoritmo ejemplo_8.5.e
var
entero : A, B, C
inicio
A  1
B  2
C  A+3
P1 (A, B - C, C)
C  C – F(A)
P2 (A, C)
P1 (C, B, A)
escribir(A + “, ” + B + “, ” + C)
fin

procedimiento P1(E/S entero : x; E entero : y; E/S entero : z)


inicio
x  y + z
y  x + 1
z  y * 2
fin_procedimiento

procedimiento P2(E/S entero : x; E entero : y)


inicio
x  x +1 –y
y  3
fin_procedimiento

entero función F(E entero : x)


inicio
x  x + 3
devolver(x – 1)
fin_función

La solución es A = 8; B = 2; C = 3

61
Apuntes de algoritmos

8.6. Arreglos
a. Hay unos multicines con 5 salas, y cada sala con 100 personas distribuidas en 20 asientos y 5 filas.
Si se pide la entrada para una sala, implementar un algoritmo que me diga si hay sitio en la sala.
algoritmo ejemplo_8.6.a
const
salas = 5
asientos = 20
filas = 5
var
entero : f, a, s
lógico : bandera
array [1..filas, 1..asientos, 1..salas] de entero : cine

inicio
pedirDatos(s)
mientras (s <> 0) hacer
bandera  falso
a  0
f  1
repetir
si (a > asientos) entonces
a  1
f  f + 1
fin_si
si (a = asientos) y (f >= filas) entonces
escribir(“Sala llena”)
bandera  verdadero
si_no
si (a[f, a, s] = 0) entonces
a[f, a, s]  1
escribir(“Asiento ” + a + “, fila ” + a)
bandera  verdadero
fin_si
fin_si
hasta_que (a[f, a, s] = 1) y (bandera = verdadero)
pedirDatos(s)
fin_mientras
fin

procedimiento pedirDatos(E/S entero : sala)


inicio
repetir
escribir(“¿En qué sala quieres entrar?”)
leer(sala)
hasta (sala >= 0) y (sala <= salas)
fin_procedimiento

b. Dada una matriz A de M*N elementos, actualizarla tal que la matriz resultante tenga divididos a los
elementos de la diagonal principal por la suma de los elementos que no forman parte de ella.
algoritmo ejemplo_8.6.b
var
array [1..M, 1..N] de real : a
real : suma

inicio
pedirDatos(a)

62
Apuntes de algoritmos

sumar(a, suma)
escribirArreglo(a)
fin

procedimiento pedirDatos(E/S array [1..M, 1..N] de real : matriz)


var
entero : i, j
inicio
desde i  1 hasta M hacer
desde j  1 hasta N hacer
escribir(“Introduce el elemento” + i + “, ” + j)
leer(matriz[i, j])
fin_desde
fin_desde
fin_procedimiento

procedimiento sumar(E array [1..M, 1..N] de real : matriz; E/S real : s)


var
entero : i, j
inicio
s  0
desde i  1 hasta M hacer
desde j  1 hasta N hacer
si (i <> j) entonces
s  s + matriz[i, j]
fin_si
fin_desde
fin_desde
fin_procedimiento

procedimiento escribirArreglo(E array [1..M, 1..N] de real : matriz; E real : s)


var
entero : i, j
inicio
desde i  1 hasta M hacer
desde j  1 hasta N hacer
si (i = j) entonces
escribir(matriz[i, j] / s)
si_no
escribir(matriz[i, j])
fin_si
fin_desde
fin_desde
fin_procedimiento

c. Se tiene guardado en una estructura los alumnos de una escuela, sabiendo que hay 3 cursos, M alumnos
por curso y N materias por estudiante, determinar mediante subprogramas:
• ¿Cual es la nota media de un determinado curso?
• ¿Cuantos aprobados y reprobados hay en una determinada materia?
• ¿Cual es el alumno de la escuela con mejor nota media?
algoritmo ejemplo_8.6.c
const
cursos = 3
alumnos = M
materias = N
tipo
array [1..cursos, 1.. alumnos, 1.. materias] de real : cubo

63
Apuntes de algoritmos

var
cubo : nota

inicio
pedirDatos(nota)
mediaCurso(nota)
cantidadAprobados(nota)
mediaAlumno(curso)
fin

procedimiento pedirDatos(E/S cubo : n)


var
entero : c, a, m
inicio
desde c  1 hasta cursos hacer
desde a  1 hasta alumnos hacer
desde m  1 hasta materias hacer
repetir
escribir(“Nota del alumno ” + a + “ materia ” + m + “curso ” + c)
leer(n[c, a, m])
hasta_que (n[c, a, m] >= 0) y (n[c, a, m] <= 20)
fin_desde
fin_desde
fin_desde
fin_procedimiento

procedimiento mediaCurso(E cubo : n)


var
entero : curso, a, m
real : media, suma

inicio
suma  0.0
repetir
escribir(“¿De qué curso quieres hacer la media?”)
leer(curso)
hasta_que (curso <= 1) y (curso <= cursos)
desde a  1 hasta alumnos hacer
desde m  1 hasta materias hacer
suma  suma + n[curso, a, m]
fin_desde
fin_desde
media  suma / (alumnos * materias)
escribir(“La nota media del curso ” + curso + “ es ” + media)
fin_procedimiento

procedimiento cantidadAprobados(E cubo : n)


var
entero : c, a, materia, reprobados, aprobados
inicio
reprobados 0
aprobados  0
repetir
escribir(“¿Qué materia quieres ver?”)
leer(materia)
hasta_que (materia >= 1) y (materias <= materias)
desde c  1 hasta cursos hacer
desde a  1 hasta alumnos hacer
si (n[c, a, materia] >= 10) entonces

64
Apuntes de algoritmos

aprobados  aprobados + 1
si_no
reprobados  reprobados + 1
fin_si
fin_desde
fin_desde
escribir(“En la materia ” + materia + “ hay ” + aprobados + “ aprobados”)
escribir(“En la materia ” + materia + “ hay ” + reprobados + “ reprobados”)
fin_procedimiento

procedimiento mediaAlumno(E cubo : n)


var
entero : c, e, a, alumno, curso
real : suma, media, mayor
inicio
mayor  0.0
desde c  1 hasta cursos hacer
desde a  1 hasta alumnos hacer
suma  0.0
desde m  1 hasta materias hacer
suma  suma + n[c, a, m]
fin_desde
media  suma / materias
si (media > mayor) entonces
mayor  media
curso  c
alumno  a
fin_si
fin_desde
fin_desde
escribir(“El alumno con mayor media es el ” + alumno + “ del curso ” + curso)
escribir(“y su nota es de ” + mayor)
fin_procedimiento

d. Una empresa consta de 5 departamentos con 20 empleados cada departamento, si se tiene todas las
ventas en una estructura, determinar:
• Ventas de un determinado departamento en un determinado mes.
• Ventas de un determinado empleado en un determinado departamento.
• ¿Cual es el departamento con más ventas?
algoritmo ejemplo_8.6.d
const
departamentos = 5
empleados = 20
meses = 12
tipo
array [1.. departamentos, 1.. empleados, 1.. meses] de real : matriz
var
matriz : ventas
real : cantidad

inicio
pedirDatos(ventas)
ventasDepartamentoMes(ventas)
ventasEmpleadoDepartamento(ventas)
mejorDepartamento(ventas)
fin

65
Apuntes de algoritmos

procedimiento pedirDatos(E/S matriz : a)


var
entero : d, e, m
inicio
desde d  1 hasta departamentos hacer
desde e  1 hasta empleados hacer
desde m  1 hasta meses hacer
escribir(“Ventas del departamento ” + d)
escribir(“empleado ” + e)
escribir(“mes ” + m)
leer(a[d, e, m])
fin_desde
fin_desde
fin_desde
fin_procedimiento

procedimiento ventasDepartamentoMes(E matriz : a)


var
entero : departamento, e, mes
real : venta
inicio
venta  0.0
repetir
escribir(“Departamento”)
leer(departamento)
hasta_que (departamento >= 1) y (departamento <= departamentos)
repetir
escribir(“Mes”)
leer(mes)
hasta_que (mes >= 1) y (mes <= 12)
desde e  1 hasta empleados hacer
venta  venta + a[departamento, e, mes]
fin_desde
escribir(“Las ventas del departamento” + departamento)
escribir(“en el mes” + mes + “son” + venta)
fin_procedimiento

procedimiento ventasEmpleadoDepartamento(E matriz : a)


var
entero : departamento, empleado, m
real : venta
inicio
venta  0.0
repetir
escribir(“Empleado”)
leer(empleado)
hasta_que (empleado >= 1) y (empleado <= empleados)
repetir
escribir(“Departamento”)
leer(“departamento”)
hasta_que (departamento >= 1) y (departamento <= departamentos)
desde m  1 hasta meses hacer
venta  venta + a[departamento, empleado, m]
fin_desde
escribir(“Las ventas del empleado ” + empleado)
escribir(“del departamento ” + departamento + “ son ” + venta)
fin_procedimiento

66
Apuntes de algoritmos

procedimiento mejorDepartamento(E matriz : a)


var
entero : d, e, m, departamento
real : mayor, venta
inicio
mayor  0.0
desde d  1 hasta departamentos hacer
venta  0
desde e  1 hasta empleados hacer
desde k  1 hasta meses hacer
venta  venta + a[d, e, m]
fin_desde
fin_desde
si (venta > mayor) entonces
mayor  venta
departamento  d
fin_si
fin_desde
escribir(“El mejor departamento es el ” + departamento + “ con ” + mayor)
fin_procedimiento

8.7. Registros
a. Tenemos un array con la información de nuestros productos, por cada producto almacenamos su código,
descripción, stock actual y stock mínimo.
Se trata de obtener otro array que contenga los productos de los que halla que hacer pedidos porque su
stock sea inferior al mínimo, tal que al proveedor le tenemos que dar como datos la identificación del
producto y la cantidad que pedimos, que coincidirá con el stock mínimo.
Normalmente trabajamos con 100 productos.
algoritmo ejemplo_8.7.a
tipo
registro : producto
entero : codigo
cadena : descripción
entero : stock
entero : stock_min
fin_registro
registro : pedido
entero : codigo
entero : cantidad
fin_registro
array [1..100] de producto : listaProducto
array [1..100] de pedido : listaPedido
var
listaProducto : prod
listaPedido : ped
entero : i, j

inicio
j  1
desde i  1 hasta 100 hacer
si (prod[i].stock < prod[i].stock_min) entonces
ped[j].codigo  prod[i].codigo
ped[j].cantidad  prod[i].stock_min
j  j + 1

67
Apuntes de algoritmos

fin_si
fin_desde
fin

b. Dado un array que contiene la información de los alumnos de una clase de 100 alumnos, y teniendo en
cuenta que de cada uno de ellos almacenamos su número de expediente, nombre y nota media. Hallar la
media de todos los alumnos de esa clase y dar otra opción que pida el nombre de un alumno y me de su
nota si este alumno existe.
algoritmo ejemplo_8.7.b
tipo
registro : alumno
entero : expediente
cadena : nombre
real : media
fin_registro
array[1..100] de alumno : lista
var
lista : estudiante
entero : op, i
lógico : marca
cadena : nombre

inicio
presentar(op)
mientras (op <> 0) hacer
según_sea op hacer
1: escribir(“La media de la clase es ” + notaMedia(estudiante))
2: escribir(“Introduce un nombre”)
leer(nombre)
marca  falso
i  1
repetir
si (comparar(estudiante[i].nombre, nombre) = verdadero) entonces
marca = verdadero
si_no
i  i + 1
fin_si
hasta_que (i > 100) o (marca = verdadero)
si (marca = verdadero) entonces
escribir(“La nota de ” + nombre + “ es ” + estudiante[i].media)
si_no
escribir(“El alumno no existe”)
fin_si
fin_según
presentar(op)
fin_mientras
fin

procedimiento presentar(E/S entero : opcion)


inicio
repetir
escribir(“0. Salir”)
escribir(“1. Hallar nota media”)
escribir(“2. Hallar la nota de un alumno”)
escribir(“Introduce una opción”)
leer(opcion)
hasta_que (opcion >= 0) y (opcion <= 2)
fin_procedimiento

68
Apuntes de algoritmos

real función notaMedia(E lista : a)


var
entero : i
real : acum
inicio
acum  0
desde i  1 hasta 100 hacer
acum  acum + a[i].nota
fin_desde
devolver(acum / 100)
fin_función

lógico función comparar(E cadena : c1, c2)


var
entero : i
inicio
i  1
mientras (c1[i] = c2[i]) y (c1[i] <> ’$’) y (c2[i] <> ’$’) hacer
i  i + 1
fin_mientras
si (c1[i] = c2[i]) entonces
devolver(verdadero)
si_no
devolver(falso)
fin_si
fin_función

c. Tenemos un array con la indicación de cada producto, stock, descripción y fecha. Hallar una opción que nos
sirva iterativamente para hacer pedidos de productos y que termina cuando pidamos el producto 0.
Por cada pedido se da el identificador de producto que se pide, y la cantidad de producto, y lo que nos dice
es si hay cantidad suficiente, respondiendo “Pedido suministrado” y actualizando el stock, y si el producto
solicitado no existe o no hay suficiente cantidad, mostrará un mensaje de error explicando la causa.
algoritmo ejemplo_8.7.c
tipo
registro : t_fecha
entero: dia
entero : mes
entero : año
fin_registro
registro : producto
entero : codigo
cadena : descripicion
entero : stock
t_fecha : fecha
fin_registro
array[1..10] de producto : lista
var
lista : prod
entero : codigo, cantidad, i
lógico : marca

inicio
escribir(“Introduce el código”)
leer(codigo)
escribir(“Introduce la cantidad”)
leer(cantidad)
mientras (codigo <> 0) hacer
i  1

69
Apuntes de algoritmos

marca  falso
repetir
si (codigo = prod[i].codigo) entonces
marca  verdadero
si_no
i  i + 1
fin_si
hasta_que (marca = verdadero) o (i > 100)
si (marca = falso) entonces
escribir(“No existe el producto”)
sino
si (prod[i].stock < cantidad) entonces
escribir(“No hay cantidad suficiente”)
si_no
prod[i].stock  prod[i].stock – cantidad
escribir(“pedido suministrado”)
fin_si
fin_si
fin_mientras
fin

8.8. Cadenas
a. Borrar de una cadena una subcadena que forma parte de ella. Dar la posición de inicio y final de la
subcadena que quiero borrar.
procedimiento borrar(E/S cadena : c; E entero : ini, fin)
var
entero : i, j
inicio
i  ini
f  fin + 1
mientras (c[f] <> ’$’) hacer
c[i]  c[f]
i  i + 1
fin_mientras
c[i]  ‘$’
fin_procedimiento

b. Insertar una cadena dentro de otra a partir de una determinada posición.


procedimiento insertar(E/S cadena : c; E cadena : s; E entero : pos)
var
entero : p, j, i
inicio
p  pos
j  1
mientras (s[j] <> ’$’) hacer
desde i  longitud(c) +1 hasta p hacer
c[i + 1]  c[i]
fin_desde
c[p]  s[j]
j  j + 1
p  p + 1
fin_mientras
fin_procedimiento

70
Apuntes de algoritmos

c. Crear una función a la que se le pasa una cadena como parámetro y como resultado devuelve la longitud
de la misma.
entero función longitud(E cadena : c)
var
entero : l
inicio
l  0
mientras (c[L + 1] <> ‘$’) hacer
l  l + 1
fin_mientras
devolver(l)
fin_procedimiento

d. Intercambiar la aparición de una subcadena dentro de una cadena, por otra subcadena. Para eso la primera
subcadena tiene que aparecer en la otra.
procedimiento intercambio(E/S cadena : c; E cadena : c2, c3)
var
entero : i, pos
inicio
i  1
mientras (c1[i] <>’$’) hacer
si (c1[i] = c2[i]) entonces
pos  buscar(c1, c2)
si (pos <> 0) entonces
borrar(c1, pos, pos + longitud(c2) - 1)
insertar(c1, c3, pos)
i  pos + longitud(c3)
si_no
i  i +1
fin_si
si_no
i  I+1
fin_si
fin_mientras
fin_procedimiento

e. Comparar 2 cadena si son iguales o no. Realizar la comparación utilizando los valores ASCII asociados a
cada carácter. En el caso de que se comparen 2 cadenas de diferente longitud tal que la cadena de menor
longitud tiene N caracteres y estos N caracteres coinciden con los N primeros caracteres de la cadena más
larga, se considera mayor la cadena más larga.
entero función comparacion(E cadena c1, c2)
var
entero : i
inicio
i  1
mientras (c1[i] = c2[i]) y (c1[i] <> ‘$’) y (c2[i] <> ‘$’) hacer
i  i + 1
fin_mientras
si (c1[i] = c2[i]) entonces
devolver(0)
si_no
devolver(ascii(c1[i]) - ascii(c2[i]))
fin_si
fin_función

71
Apuntes de algoritmos

f. Crear una función que dado 2 cadenas, busque si existe la cadena 1 dentro de la cadena 2.
entero función busqueda(E cadena : c, s1)
var
entero : i, pos, k
lógico : encontrado
inicio
e  1
encontrado  falso
mientras (c[i] <> ’$’) y (encontrado = falso) hacer
si (c[i] = s[i]) entonces
pos  i
k  1
mientras (c[i] = s[k]) y (c[i] <> ’$’) y (s[k] <> ’$’) hacer
i  i + 1
k  k + 1
fin_mientras
si (s[k] = ’$’) entonces
encontrado  verdadero
si_no
i  pos + 1
pos  0
fin_si
si_no
i  i + 1
fin_si
fin_mientras
devolver(pos)
fin_función

g. Crear una función que extraiga parte de una cadena, sabiendo el inicio y el fin, e insertarlo de una segunda
cadena.
procedimiento subcadena(E cadena : c1; E entero : inicio, long; E/S cadena : c2)
var
entero : i, k
inicio
si (inicio <= 0) o (inicio > longitud(c1)) entonces
c2[1]  ‘$’
si_no
i  inicio
k  1
mientras (i <= inicio + long) y (c1[i] < > ‘$’) hacer
c2[k]  c1[i]
k  k + 1
i  i + 1
fin_mientras
c2[k]  ‘$’
fin_si
fin_procedimiento

72
Apuntes de algoritmos

8.9. Definición de una clase

clase rectángulo
// Atributos
var
privado real : largo, ancho
// Métodos
// Método constructor
constructor rectángulo(E real : lar, anc)
inicio
largo  lar
ancho  anc
fin_constructor
// Método que modifica el valor del atributo largo
público procedimiento modificarLargo(E real : lar)
inicio
largo  lar
fin_procedimiento
// Método que retorna el valor del atributo largo
público real función mostrarLargo()
inicio
devolver(largo)
fin_función
// Método que modifica el valor del atributo ancho
público procedimiento modificarAncho(E real : anc)
inicio
ancho  anc
fin_procedimiento
// Método que retorna el valor del atributo ancho
público real función mostrarAncho()
inicio
devolver(ancho)
fin_función
// Método que retorna el área o superficie ocupada por el rectángulo
público real función calcularÁrea()
inicio
devolver(largo * ancho)
fin_función

73
Apuntes de algoritmos

// Retorna el perímetro del rectángulo


público real función calcularPerímetro()
inicio
devolver(2 * (largo + ancho))
fin_función
fin_clase

// Uso de la clase rectángulo


clase algoritmoPrincipal
// Atributos
var
// Se declara una variable de tipo objeto rectángulo a la cual llamaremos
rect
privado rectángulo : rect
// Se declaran las variables reales l y a para largo y ancho del
rectángulo
privado real : l, a
público método principal()
inicio
escribir(“Suministre a continuación los valores para el largo y el ancho”)
leer(l)
leer(a)
rect = nuevo rectángulo(l, a)
escribir(“Resultados de los cálculos”)
escribir(“Área: ”+ rect.calcularÁrea())
escribir(“Perímetro ” + rect.calcularPerímetro())
fin_metodo
fin_clase

8.10. Asociación (ver algoritmo del Ejemplo 8.9.)

74
Apuntes de algoritmos

8.11. Herencia, clase abstracta y asociación

abstracto clase persona


// Atributos
var
privado entero : cedula
privado cadena : nombre
privado entero : edad
// Métodos
// Método constructor
constructor persona(E entero : c; E cadena : n; E entero : e)
inicio
cedula  c
nombre  n
edad  e
fin_constructor
// Método que modifica el valor del atributo cedula
público procedimiento modificarCédula(E entero: c)
inicio
cedula  c
fin_procedimiento
// Método que retorna el valor del atributo cedula
público real función mostrarCédula()
inicio
devolver(cedula)
fin_función
// Método que modifica el valor del atributo nombre
público procedimiento modificarNombre(E cadena : n)
inicio
nombre  n
fin_procedimiento

75
Apuntes de algoritmos

// Método que retorna el valor del atributo nombre


público real función mostrarNombre()
inicio
devolver(nombre)
fin_función
// Método que modifica el valor del atributo edad
público procedimiento modificarEdad(E cadena : e)
inicio
edad  e
fin_procedimiento
// Método que retorna el valor del atributo edad
público real función mostrarEdad()
inicio
devolver(edad)
fin_función
fin_clase
clase alumno hereda_de persona
// Atributos
var
privado entero : identificacion
// Métodos
// Método constructor
constructor alumno(E entero : c; E cadena : n; E entero : e, i)
inicio
super(c, n, e)
identificacion  i
fin_constructor
// Método que modifica el valor del atributo identificación
público procedimiento modificarIdentificación(E entero: i)
inicio
identificacion  i
fin_procedimiento
// Método que retorna el valor del atributo identificación
público real función mostrarIdentificación()
inicio
devolver(identificacion)
fin_función
fin_clase
clase algoritmoPrincipal
// Atributos
var
privado alumno : estudiante
privado entero : c, e, i
privado cadena : n
público método principal()
inicio
escribir(“Suministre los datos del alumno”)
leer(c)
leer(n)
leer(e)
leer(i)
estudiante = nuevo alumno(c, n, e, i)
escribir(“Los datos del alumno son: ”)

76
Apuntes de algoritmos

escribir(“Cédula de identidad: ”+ estudiante.mostrarCedula())


escribir(“Nombre: ” + estudiante.mostrarNombre())
escribir(“Edad: ” + estudiante.mostrarEdad())
escribir(“N° de carnet: ” + estudiante.mostrarIdentificacion())
fin_metodo
fin_clase

8.12. Polimorfismo, herencia, clase abstracta y asociación

abstracto clase cudrilátero


var
privado entero : color
// Métodos
// Método constructor
constructor cuadrilátero(E entero : c)
inicio
color  c
fin_constructor

77
Apuntes de algoritmos

// Método que modifica el valor del atributo color


público procedimiento modificarColor(E entero: c)
inicio
color  c
fin_procedimiento
// Método que retorna el valor del atributo color
público real función mostrarColor()
inicio
devolver(color)
fin_función
// Método que calcula el área del cudrilátero
abstracto público real función calcularÁrea()
inicio
fin_función
fin_clase
clase cuadrado hereda_de cuadrilátero
// Atributos
var
privado real : lado
// Métodos
// Método constructor
constructor cuadrado(E entero : c, E real : l)
inicio
super(c)
lado  l
fin_constructor
// Método que modifica el valor del atributo lado
público procedimiento modificarLado(E entero: l)
inicio
lado  l
fin_procedimiento
// Método que retorna el valor del atributo lado
público real función mostrarLado()
inicio
devolver(lado)
fin_función
// Método que calcula el área del cuadrado
público real función calcularÁrea()
inicio
devolver(lado ** 2)
fin_función
// Método que calcula el perímetro del cuadrado
público real función calcularPerímetro()
inicio
devolver(4 * lado)
fin_función
fin_clase
clase rectángulo hereda_de cuadrilátero
// Atributos
var
privado real : ladoA, ladoB

78
Apuntes de algoritmos

// Métodos
// Método constructor
constructor rectángulo(E entero : c, E real : lA, lB)
inicio
super(c)
ladoA  lA
ladoB  lB
fin_constructor
// Método que modifica el valor del atributo lado
público procedimiento modificarLadoA(E entero: lA)
inicio
ladoA  lA
fin_procedimiento
// Método que retorna el valor del atributo ladoA
público real función mostrarLadoA()
inicio
devolver(ladoA)
fin_función
// Método que modifica el valor del atributo ladoB
público procedimiento modificarLadoB(E entero: lB)
inicio
ladoB  lB
fin_procedimiento
// Método que retorna el valor del atributo ladoB
público real función mostrarLadoB()
inicio
devolver(ladoB)
fin_función
// Método que calcula el área del rectángulo
público real función calcularÁrea()
inicio
devolver(ladoA * ladoB)
fin_función
// Método que calcula el perímetro del rectángulo
público real función calcularPerímetro()
inicio
devolver(2 * (ladoA + ladoB))
fin_función
fin_clase
clase cubo hereda_de cuadrado
// Atributos
var
privado real : altura
// Métodos
// Método constructor
constructor cubo(E entero : c, E real : l, a)
inicio
super(c, l)
altura  a
fin_constructor

79
Apuntes de algoritmos

// Método que modifica el valor del atributo altura


público procedimiento modificarAltura(E entero: a)
inicio
altura  a
fin_procedimiento
// Método que retorna el valor del atributo altura
público real función mostrarAltura()
inicio
devolver(altura)
fin_función
// Método que calcula el volumen del cubo
público real función calcularVolumen()
inicio
devolver(altura * super.calcularÁrea())
fin_función
fin_clase
clase algoritmoPrincipal
// Atributos
var
privado cubo : c
privado rectángulo : r
privado entero : colorCubo, colorRectangulo
privado real : lado, altura, ladoA, ladoB
público método principal()
inicio
escribir(“Suministre los datos de las figuras”)
leer(colorCubo)
leer(lado)
leer(altura)
leer(ladoA)
leer(ladoB)
leer(colorRectangulo)
c = nuevo cubo(colorCubo, lado, altura)
r = nuevo rectángulo(colorRectangulo, ladoA, ladoB)
escribir(“El volumen del cubo es: ” + c. calcularVolumen())
escribir(“El área del rectángulo es: ”+ r.calcularÁrea())
escribir(“El perímetro del rectángulo es:” + r.calcularPerímetro())
fin_metodo
fin_clase

80
Apuntes de algoritmos

Bibliografía
• Joyanes, L. (2007). Fundamentos de Programación - Algoritmos, Estructuras de Datos y Objetos.
Tercera Edición. Madrid, España: Mc Graw Hill.
• Joyanes, L. (2003). Libro de Problemas, Fundamentos de Programación - Algoritmos, Estructuras de
Datos y Objetos. Segunda Edición. Madrid, España: Mc Graw Hill.
• Joyanes, L. (2006). Programación en Pascal. Cuarta Edición. Madrid, España: Mc Graw Hill.
• Kimmel, P. (2007). Manual de UML. Primera Edición. Mc Graw Hill.
• Leestma, S. y Nyhoff, L. (2000). Programación en Pascal. Cuarta Edición. Madrid, España: Pretence Hall.

81

Potrebbero piacerti anche