You are on page 1of 577

,

.' \
<
<
,
.
,

,
. "
,
,
ESTRUCTURA DE DATOS
Algoritmos, abstraccin y objetos
<

<
r

,
CONSULTORES EDITORIALES
REA DE INFORMTICA y COMPUTACIN
Antonio Vaquero Snchez
Catedrtico de Lenguajes y Si stemas Informticos
Escuela Superior de Informtica
Universidad Complutense de Madrid
ESPAA
Gerardo Quiroz Vieyra
Ingeniero en Comunicaciones y Electrnica
por la ESIME del Instituto Politcnico Nacional
Profesor de la Universidad Autnoma Metropolitana
Unidad Xochimi1co

MEXICO

orl

. ,

OS,8 r8CCIOn O e OS
Luis Joyanes Aguilar
Ignacio Zahonero Martnez
Departamento de Lenguajes y Sistemas Informticos
y de Ingeniera de Software
Escuela Universitaria de Informtica
Universidad Pontificia de Salamanca en Madrid
MADRID. BUENOS AIRES. CARACAS. GUATEMALA. LISBOA. MXICO
NUEVA YORK. PANAM. SAN JUAN. SANTAF DE BOGOT. SANTIAGO. sAo PAULO
AUCKLAND HAMBURGO LONDRES. MILN. MONTREAL NUEVA DELHI PARs
SAN FRANCISCO. SIDNEY SINGAPUR STo LOUIS TOKIO. TORONTO

j
,
,
,
,
ESTRUCTURA DE DATOS. Algoritmos, abstraccin y objetos
No est permitida la reproduccin total o parcial de este libro, ni su tratamiento in-
formtico, ni la transmisin de ninguna forma o por cualquier medio, ya sea electr-
nico, mecnico, por fotocopia, por registro u otros mtodos, sin el permiso previo
y por escrito de los titulares del Copyright.
DERECHOS RESERVADOS 1998, respecto a la primera edicin en espaol, por
McGRAW-HILL/INTERAMERICANA DE ESPAA, S. A. U.
Edificio Valrealty, 1." planta
Basauri, 17
28023 Aravaca (Madrid)
ISBN: 84-481-2042-6
Depsito legal: M. 16.148-1999
Editora: Concepcin Fernndez Madrid
Diseo de cubierta: Design Master Dima
Compuesto en: Puntographic, S. L.
Impreso en: Cobra, S. L.
IMPRESO EN ESPAA - PRINTED IN SPAIN

.... . .
.. .

.. .
A los benjamines de nuestras familias, Luis y Paloma
,

..
..
,

..
..
..
..
...
,-' ,
..
..
1
1
,

..

Prlogo .................................................................................................................... .
PARTE I. ABSTRACCIN Y PROGRAMACiN. INTRODUCCIN
A LA INGENIERA DE SOFTWARE
Captulo 1. Ingeniera de software: introduccin a la metodologa de cons-
truccin de grandes programas .................................................. ..
1.1. IAbstraccin; ...................................................................................... .
1.2. Resolucin de problemas y programacin ..................................... .
l.3. Herramientas para la resolucin de problemas .............................. .
1.3.1. Diseo descendente ........................................................... .
1.3.2. Abstraccin procedimental ............................................... .
1.3.3. i Abstraccin de datos ......................................................... .
l.3.4. Ocultacin de la informacin .......................................... ..
l.3.5. I Programacin orientada a objetos ................................... ..
1.4. Factores en la calidad del software ............................................... ..
l.5. El ciclo de vida del software ......................................................... ..
1.5.1. Anlisis .............................................................................. .
1.5.2. Diseo ................................................................................ .
1.5.3. Implementacin (codificacin) ........................................ ..
154 P b
't "
. .. me as e In egraclon ........................................................ .
1.5.5. Verificacin ....................................................................... .
1.5.6. Mantenimiento .................................................................. .
l.5.7. La obsolescencia: programas obsoletos .......................... .
l.5.8. Iteracin y evolucin del software ................................... .
1.6. Mtodos formales de verificacin de programas ........................... .
1.6.1. Aserciones (asertos) ......................................................... .
1.6.2. Precondiciones y postcondiciones ................................... .
l.6.3. Reglas para prueba de programas .................................... .
l.6.4. Invariantes de bucles ......................................................... .
l.6.5. Etapas a establecer la exactitud (correccin) de un pro-
grama ................................................................................. .
l. 7. Principios de diseo de sistemas de software ................................ .
1.7.1. Modularidad mediante diseo descendente ..................... .
1.7.2. Abstraccin y encapsulamiento ...................................... ..
1.7.3. Modificabilidad ......................................... .............. ......... ..


XXI
3
4
4
5
6
7
7
7
8
9
lo:"""'"
11
12
13
13
14
15
15
16
16
17
17
19
22
23
23
24
25
"
VII
,
,
,
,
,
.
,
, __ ~ __ .z ___ .. -, __ __________________ , _____ . _=_. _. ______________________________________ __
viii Estructura de datos
1.8.
1.9.
1.7.4. Comprensibilidad y fiabilidad ......................................... .
1.7.5. Interfaces de usuario ........................................................ .
1. 7 .6. Programacin segura contra fallos .................................. .
1.7.7. Facilidad de uso ............................................................... .
1.7.8. Eficiencia .......................................................................... .
1.7.9. Estilo de programacin, documentacin y depuracin ...
Estilo de programacin ............................... o.,
1.8.1.
1.8.2.
1.8.3.
1.8.4.
1.8.5.
1.8.6.
1.8.7.
1.8.8.
1.8.9.
Modularizar un programa en subprogramas ................. ..
Evitar variables globales en subprogramas .................... .
Usar nombres significativos para identificadores .......... .
Definir constantes con nombres ...................................... .
Evitar el uso de got o ..................................................... .
Uso adecuado de parmetros valor/variable .................. ..
U so adecuado de funciones ............................................ ..
Tratamiento de errores ..................................................... .
Legibilidad ~ ...................................................................... .
La documentacin ................................................................. .......... .
1.9.1. Manual del usuario ........................................................... .
1.9.2. Manual de mantenimiento (documentacin para progra-
madores) ........................................................................... .
1.9.3. Documentacin interna .................................................... .
1.9.4. Documentacin externa .................................................. ..
1.9.5. Documentacin del programa ........................................ ..
l. 10. Depuracin .................................... oo
1.1 0.1.
l.l 0.2.
Localizacin y reparacin de errores .............................. .
Los equipos de programacin ........................................ ..
1.11. . Diseo de algoritmos ....................................................................... .
1.12. Pruebas (testing) .............................................................................. .
1.12.1.
l.l2.2.
1.12.3.
1.12.4.
Errores de sintaxis (de compilacin) .............................. .
Errores en tiempo de ejecucin ...................................... ..
Errores lgicos ................................................................. .
El depurador ..................................................................... .
1.13. Eficiencia ......................................................................................... .
l.l3.1. Eficiencia versus legibilidad (claridad) .......................... .
1.14. Transportabilidad ............................................................................. .
Resumen ........................................................................................................ .
E
..
]erCIClos ...................................................................................................... .
Problemas ...................................................................................................... .
Captulo 2. Construccin de grandes programas: mdulos versus uni-
26
26
26
27
27
28
28
29
29
30
31
31
31
32
32
33
35
35
36
37
37
37
38
39
41
42
42
44
45
45
46
46
49
49
49
50
51
dades .................. ......... .................. ........................ ..... ....................... 53
2. l. Concepto de unidad.... ............. ................... ...................................... 54
2.2. Estructura de una unidad.................................................................. 54
Contenido ix
2.3.
2.4.
2.2.1.
2.2.2.
2.2.3.
2.2.4.
2.2.5.
.
Cabecera de la unidad ....................................................... .
Seccin de interfaz ............................................................ .
Seccin de implementacin .............................................. .
Seccin de iniciacin (inicializacin) ............................. .
Ventajas de las unidades ................................................... .
Creacin de unidades ...................................................................... .
2.3.1. Construccin de grandes programas ................................ .
2.3.2. Uso de unidades ................................................................ .
2.3.3. Declaraciones/infonnacin pblica y privada ................. .
2.3.4. Clusula uses en la seccin de implementacin .......... .
Utilizacin de unidad estndar ....................................................... .
2.4.1. Unidad System ............................................................... .
2.4.2. Unidad Crt ....................................................................... .
2.4.3. Unidad DOS ....................................................................... .
2.4.4. Unidad Printer ............................................................. .
2.4.5. Unidad Graph .................................................................. .
2.5. Situacin de las unidades en sus discos: dnde busca Turbo Bor-
55
55
56
57
57
57
61
61
62
63
65
66
66
67
68
68
land Pascal las unidades? ................................................................. 69
2.6. Identificadores idnticos en diferentes unidades ............................ 71
2.7. Sntesis de unidades ......................................................................... 71
2.7.1. Estructura de una unidad ............................ ............ ........... 72
2.7.2. Excepciones en la escritura de unidades .......................... 73
2.7.3. Compilacin de unidades .................................................. 74
2.8. Otros mtodos de estructurar programas: inclusin, solapamientos
y encadenamiento ............................................................................ .
2.8.1.
2.8.2.
2.8.3.
2.8.4.

Los archivos de inclusin o incluidos (include) ............. .
Los solapamientos (overlays) ................................ : .......... .
La unidad OverIay (generacin de solapamientos) ......... .
Encadenamiento de archivos compilados ........................ .
Resumen ............................................................. , ......................................... .

E
..
1 erClClOS .................................................................................................... .
Referencias bibliogrficas ......................................................................... .
r
74
74
75
76
79
79
79
82
Captul I 3. Abstraccin de datos: tipos abstractos de datos y objetos ....... 83
,
3.1. El papel (el rol) de la abstraccin .................................................. .
3.1.1. La abstraccin como un proceso mental naturaL ........... .
3.1.2. Historia de la abstraccin del software ............................ .
3. 1.3. Procedimientos .................................................................. .
3.1.4. Mdulos ............................................................................. .
3.1.5. Tipos abstractos de datos .................................................. .
3.1.6. Objetos ............................................................................... .
3.2. Un nuevo paradigma de programacin .......................................... .
,
.
!
,
i

X Estructura de datos
3.3.
,. . .
'NI . odularldad ..................................................................................... .
3.3.1. La estructura de un mdulo ............................................. .
3.3.2. Reglas de modularizacin ............................................... .
3.4. Diseo de mdulos .......................................................................... .
3.4.1. Acoplamiento de mdulos .............................................. ..
3.4.2. Cohesin de mdulos ..................................................... ..
3.5. Tipos de datos ........................................ o
3.6. Abstraccin en lenguajes de programacin ................................... .
3.6.1. Abstracciones de control ................................................. .
3.6.2. Abstracciones de datos ................................................... ..
3.7. Tipos abstractos de datos (TAD) .................................................... .
3.7.1. Ventajas de los tipos abstractos de datos ........................ .
3.7.2. Implementacin de los TAD .......................................... ..
3.8. Tipos abstractos de datos en Turbo Borland Pascal ...................... .
3.8.1. Aplicacin del tipo abstracto de dato pila ..................... .
3 9 O
. , b'
.. rlentaclon a o ~ t o s ...................................................................... .
3.9.1. Abstraccin ............................................................. ......... .
. 3.9.2. Encapsulacin .................................................................. .
3.9.3. Modularidad ..................................................................... .
3.9.4. Jerarqua .................................................. ......................... .
3.9.5. Polimorfismo .................................................................... .
3.9.6. Otras propiedades ............................................................ .
3.10. Reutilizacin de software ............................................................... ..
3.11. Lenguajes de programacin orientados a objetos .......................... .
3.11.1. Clasificacin de los lenguajes orientados a objetos ...... .
3.12. Desarrollo tradicional frente a desarrollo orientado a objetos .... ..
3.13. Beneficios de las tecnologas de objetos ....................................... ..
Resumen ........................................................................................................ .
E
..
jerCIClOS ...................................................................................................... .
PARTE 11. FUNDAMENTOS BSICOS DE ESTRUCTURAS DE DATOS
Y TIPOS ABSTRACTOS DE DATOS
89
90
91
94
94
95
96
97
97
98
99
101
101
102
104
105
107
107
107
108
108
109
110
111
112
116
118
120
120
Captulo 4. Estructuras de datos dinmicas: punteros ................................. 125
4.1. ' Estructuras de datos dinmicas ............ .............. .................... .......... 125
4.2. f Punteros (apuntadores) .................................................................... 127
4.2.1. Declaracin de punteros .................................................... 127
4.3. Operaciones con variables puntero: procedimientos New y Dis-
pose ....................................... A
4.3.1.
4.3.2.
4.3.3.
Procedimiento New ........................................................... .
Variables de puntero con registros ................................... .
Iniciacin y asignacin de punteros ................................. .
130
130
134
135

1
t
Contenido xi
4.3.4. Procedimiento Di s po s e .............
4.3.5. Constante ni 1 ........................... .
4.3.6. Naturaleza dinmica de los punteros ............................... .
4.3.7. Comparacin de punteros ................................................. .
4.3.8. Paso de punteros como parmetros .................................. .
4.4. El tipo genrico puntero (Pointer) .................................................. .
4.5. La asignacin de memoria en Turbo Borland Pascal .................... .
4.5.1. El montculo (heap) y los punteros .................................. .

4.5.2. Mtodos de asignacin y liberacin de memoria ............ .


4.5.3. New y Dispose .............................................................. .
4.5.4. Mark y Release ........................................................... .
4.5.5. GetMem y FreeMem ...................................................... .
4.5.6. MemAvail y MaxAvail ............................................... .
Resumen .................................................................................................. ' ... .
E
..
JerCICIOS ................................................................................
Problemas ................................................................................................... .

l37
l38
138
l39
141
142
142
143
145
145
146
146
147
148
149
152
Captulo 5. IListas -enlazadas: el TAD lista enlazada ...................................... 153
5.1. Especificacin formal del tipo abstracto de datos lista ................. .
5.2. Implementacin del TAD lista con estructuras estticas .............. .
5.3. Implementacin del TAD lista mediante variables dinmicas ...... .
5.4. Iniciar una lista enlazada ................................................................ .
5.5. Bsqueda en listas enlazadas .......................................................... .
5.6. Operaciones de direccin: siguiente, anterior, ltimo ................... .
5.7. Insercin de un elemento en una lista ............................................ .
5.8. Supresin de un elemento de una lista ........................................... .
5.9. Recorrido de una lista ..................................................................... .
5.10. Lista ordenada ................................................................................. .
5.10.1. Implementacin de una lista ordenada ............................ .
5.10.2. Bsqueda en lista ordenada .............................................. .
Resumen ........................................................................................................ .
E
..
Jerclclos ...................................................................................................... .
Problemas ...................................................................................................... .
153
156
159
162
162
163
164
166
168
168
168
170
175
176
177
Captulo 6. \ Listas doblemente enlazadas ......................................................... 179

6.1. Especificacin de lista doblemente enlazada .................................. 179


6.2. Implementacin de una lista doblemente enlazada mediante va-
. bl d' .
rla es lnamlcas ............................................................................. .
6.2.1. Creacin de nodos en la lista ........................................... .
6.2.2. Eliminacin de nodo ......................................................... .
6.3. Una aplicacin resuelta con listas doblemente enlaZadas ............. .
6.4. Implementacin de una lista circular mediante variables dinmicas ... .
180
181
184
186
195
,
j
!
i
j.

I


xii Estructura de datos
6.5. Implementacin de una lista circular mediante variables dinmicas ... .
6.6. Implementacin de listas circulares con doble enlace .................. .
Resumen .............................................................. o
E
..
Jerclclos .................................................................................................... .
Problemas ................................................................................................... .
Captulo 7.
7.1.
7.2.
7.3.
7.4.
7.5.
IPilas: el TAD pi 1 a ........................................................................ .
Especificacin formal del tipo abstracto de datos pila ................. .
Implementacin del TAD pila con arrays .................................. .
Implementacin del TAD pi 1 a mediante variables dinmicas ... .
Evaluacin de expresiones aritmticas mediante pilas ................. .
7.4.1. Notaciones Prefija (Polaca) y Postfija (Polaca inversa) ..
7.4.2. Algoritmo para evaluaciones de una expresin aritmtica ....
Aplicacin prctica de la evaluacin de una expresin aritmtica
7.5.1. Unidad Pilaop ................................................................ .
7.5.2. Unidad ExpPost (transformacin a postfija) ............... .
7.5.3. Evaluacin de la expresin en postfi j a ............................ .
Resumen ...................... a
E
..
Jerclclos .................................................................................................... .
Problemas ................................................................................................... .
196
200
203
204
204
207
207
208
211
215
215
216
218
218
220
222
224
225
225
Captulo 8. fColas y colas de prioridades: el TAD cola .................................. 227
8.1. Especificacin formal del tipo abstracto de datos cola ................. .
8.2. Implementacin del TAD cola con arrays lineales ........................ .
8.3. Implementacin del TAD cola con arrays circulares .................... .
8.4. Implementacin del TAD cola con listas enlazadas ...................... .
8.5. Implementacin del TAD cola con listas circulares ...................... .
8.6. Bicolas .............................................................................................. .
8.7. Colas de prioridades ........................................................................ .
8.8. Implementacin de colas de prioridades ....................................... ..
8.8.1. Implementacin mediante una nica lista ....................... .
8.8.2. Implementacin mediante una lista de n colas ................ .
8.9. Implementacin de un problema con colas de prioridades ........... .
Resumen ..................................................................................................... .
E
..
Jerclclos .................................................................................................... .
Pro b 1 emas ................................................................................................... .
PARTE UI. ESTRUCTURAS DE DATOS AVANZADAS
Captul 9
9.1.
9.2.
Recursividad: algoritmos recursivos .......................................... .
Recursividad .................................................................................... .
Cundo no utilizar la recursividad ................................................. .
9.2.1. Eliminacin de la recursividad ......................................... .
228
229
231
235
237
239
244
245
245
246
247
256
257
258
263
263
264
266

..

,
..
..
,

!
1
,
!
~
..
j
..




. J
1
,
1
,
..




,


j



Contenido

XIII
9.3. Algoritmos divide y vencers ...................................................... 267
9.3.1. Torres de Hanoi .................................................................. 267
9.3.2. Traza de un segmento ........................................................ 269
9.4. Implementacin de procedimientos recursivos mediante pilas...... 270
9.4.1. El problema de las Torres de Hanoi resuelto sin recur-
sividad................................................................................. 271
9.5. Algoritmos de vuelta atrs (backtracking) ...................................... 277
9.5.1. Solucin del problema Salto del caballo con esquema

IteratIVO ................................... o.,
9.5.2. Problema de las ocho reinas ............................................ ..
9.5.3. Solucin no recursiva al problema de las ocho reinas .... .
9.5.4. Problema de la mochila .................................................... .
9.5.5. Problema del laberinto ..................................................... ..
9.5.6. Generacin de permutaciones de n elementos ................ .
9.6. Problema de la seleccin ptima .................................................... .
9.6.1. El viajante de comercio ................................................... ..
9.7. Problema de los matrimonios estables .......................................... ..
Resumen ...................................................................................................... .
E
..
~ e r l l o s .................................................................................................... .
Problemas .................................................................................................... .
Captulo 10.
10.1.
10.2.
10.3.
10.4.
10.5.
10.6.
,
I Arboles binarios ....... ................................................................... .
Concepto de rbol ......................................................................... .
,
Arboles binarios ............................................................................ .
10.2.1.
10.2.2.
10.2.3.
10.2.4.
,
Terminologa .................... ............................................. .
Nivel de un nodo y altura de un rbol .......................... .
,
Arboles binario, lleno y completo ................................ .
Recorrido de un rbol binario ....................................... .
Arboles de expresin .................................................................... .
Construccin de un rbol binario ................................................ ..
Recorrido de un rbol ................................................................... .
10.5.1. Recorrido en orden ..................................................... .
10.5.2. Recorrido preorden ................................................. ..
10.5.3. Recorrido postorden ............................................. ... .
10.5.4. Implementacin de los algoritmos de recorrido .......... .
Aplicacin de rboles binarios: evaluacin de expresiones ....... .
10.6.1. Notacin postfija: notacin polaca .............................. ..
,
10.6.2. Arbol de expresin ........................................................ .
10.6.3. Transformacin de expresin infija a postfija ............. .
10.6.4. Creacin de un rbol a partir de la expresin en post-
10.6.5.
10.6.6.
fija ................................................................................... .
Evaluacin de la expresin en postfija ......................... .
Codificacin del programa de evaluacin .................... .
281
286
288
290
293
296
297
298
298
306
306
308
311
312
314
315
316
318
320
320
322
324
325
326
326
328
329
329
330
331
331
332
334
" -,



,
xiv Estructura de datos
,
10.7. Arbol binario de bsqueda .......................................................... ..
10.7.1 Creacin de un rbol binario ........................................ .
10.8. Operaciones en rboles binarios de bsqueda ............................. .
10.8.1. Bsqueda ........................................................................ .
10.8.2. Insercin ......................................................................... .
1 O 8 3 El
. ,
. " lffilnaClon .................................................................... .
10.8.4. Recorrido de un rbol ................................................... .
10.8.5. Determinacin de la altura de un rbol ...... .................. .
Resumen ..................................................................................................... .
E
..
~ e r l l o s .................................................................................................... .
Problemas .................................................................................................... .
Referencias bibliogrficas ......................................................................... .
,
334
336
340
341
341
342
344
345
346
347
349
350
Captulo 11. Arboles equilibrados ........................................ ..................... ....... 353
11.1. Eficiencia de la bsqueda en un rbol binario ............................ .
11.2. rbol binario equilibrado (AVL) ................................................. .
11.3. Creacin de un rbol equilibrado de N claves ............................. .
11.4. Insercin en rboles equilibrados: rotaciones ............................. .
11.4.1. Insercin de un nuevo nodo ............... .......................... ..
11.4.2. Proceso a seguir: rotaciones ......................................... .
11.4.3. Formacin de un rbol equilibrado ............................. ..
11. 4.4. Procedimiento de insercin con balanceo .................... .
11.5. Eliminacin de un nodo en un rbol equilibrado ........................ .
11.6. Manipulacin de un rbol equilibrado ........................................ ..
Resumen ..................................................................................................... .
E
..
Jerclclos .................................................................................................... .
Problemas ................................................................................................... .
,
353
354
355
356
357
357
360
363
366
372
376
377
377
Captulo 12. Arboles B ....................................................................................... 379
12.1.
12.2.
12.3.
12.4.
12.5.
12.6.
12.7.
12.8.
12.9.
Definicn de un rbol B .............................................................. .
.
Representacin de un rbol B de orden m ................................... .
Proceso de creacin en un rbol B ............................................... .

Bsqueda de una clave en un rbol B .......................................... .


Algoritmo de insercin en un rbol B de orden m ................... ... .
Recorrido en un rbol B de orden m ... ................ ........................ ..
Eliminacin de una clave en un rbol B de orden m .................. .
TAO rbol B de orden m .......... .................................................... .
Realizacin de un rbol B en memoria externa .......................... .
Resumen ........................... , ......................................................................... .

EJerCICIos .................................................................................................... .
Problemas ................................................................................................... .
379
380
381
384
385
389
390
397
400
414
415
415
Contenido
Captulo 13. Grafos. Representacin y operaciones ..................................... .
13.1. Grafos y aplicaciones .................................................................... .
13.2. Conceptos y definiciones .............................................................. .
13.2.1. Grado de entrada, grado de salida ................................ .
13.2.2. Camino ........................................................................... .
13.3. Representacin de los grafos ........................................................ .
13.3.1. Matriz de adyacencia .................................................... .
13.3.2. Listas de adyacencia ...................................................... .
13.4. TAO grafo ...................................................................................... .
13.4.1.
13.4.2.
Realizacin con matriz de adyacencia ........................ ..
Realizacin con listas de adyacencia .......................... ..
13.5. Recorrido de un grafo ................................................................... .
13.5.1. Recorrido en anchura .................................................... .
13.5.2. Realizacin del recorrido en anchura .......................... ..
13.5.3. Recorrido en profundidad ............................................ ..
13.5.4. Recorrido en profundidad de un grafo ........................ ..
13.5.5. Realizacin del recorrido en profundidad .................... .
13.6. Componentes conexas de un grafo .............................................. .
13.7. Componentes fuertemente conexas de un grafo dirigido .......... ..
13.8. Matriz de caminos. Cierre transitivo ............................................ .
13.9. Puntos de articulacin de un grafo .............................................. .
Resumen ..................................................................................................... .
E
..
jerCIClos .................................................................................................... .
Problemas ........................... .......................... ............................................. .
Captulo 4)
..
......
14.1.
14.2.
14.3.
14.4.
14.5.
Algoritmos fundamentales con grafos ...................................... .
Ordenacin topolgica .................................................................. .
Matriz de caminos: algoritmo de Warshall .................................. .
Problema de los caminos ms cortos con un solo origen: algorit-
mo de Dijkstra ............................................................................... .
14.3.1. Algoritmo de la longitud del camino ms corto .......... .
Problema de los caminos ms cortos entre todos los pares de vr-
tices: algoritmo de Floyd .............................................................. .
14.4.1. Recuperacin de caminos ............................................ ..
Concepto del flujo ......................................................................... .
14.5.1.
14.5.2.
14.5.3.
14.5.4.
14.5.5.
14.5.6.
14.5.7.
Planteamiento del problema ........................................ ..
F l
, ,.
ormu aClon matematlca ............................................... .
Algoritmo del aumento del flujo: algoritmo de Ford y
Fulkerson ....................................................................... .
Ejemplo de mejora de flujo .......................................... .
Esquema del algoritmo de aumento de flujo .............. ..
Tipos de datos y pseudocdigo .................................... .
Codificacin del algoritmo de flujo mximo: Ford-Fu1kerson .

xv
417
417
418
419
420
421
421
424
426
426
428
431
431
433
434
435
435
437
439
442
446
450
451
453
455
456
459
461
462
467
469
470
471
472
472
474
476
478
479





XVI Estructura de datos
14.6.
14.7.
14.8.
Problema del rbol de expansin de coste mnimo ..................... .
14.6.1. Definiciones ................................................................... .
,
14.6.2. Arboles de expansin de coste mnimo ...................... ..
Algoritmo de Prim y Kruskal ...................................................... ..
,
Codificacin. Arbol de expansin de coste mnimo .................. ..
Resumen ..................................................................................................... .
E
..
jerCIClos .................................................................................................... .
Problemas ...... o
PARTE IV. ARCHIVOS Y ORDENACiN

483
483
483
484
488
493
493
496
Captulo 15. Ordenacin, bsqueda y mezcla ................................................ 501

15.1.
15.2.
15.3.
15.4.
15.5.
15.6.
15.7.
15.8.
15.9.
15.10.
15.11.
15.12.
15.13.
15.14.
Introduccin .......................................... ........................................ .
Ordenacin .................................................................................... .
Ordenacin por burbuja ................................................................ .
15.3.1.
15.3.2.
15.3.3.
15.3.4.
15.3.5.
A
'l' .
na lSIS ....................................................................

Procedimientos de ordenacin .................................. ..


Algoritmo de burbuja mejorado (refinamiento) ........ .
Programacin completa de ordenacin por burbuja ..
Anlisis de la ordenacin por burbuja ...................... ..
O d
, 1"
r enaClon por se eCC10n ............................................................. .
O d
, . .,
r enaClon por InserClon ............................................................. .
15.5.1.
15.5.2.
Algoritmo de insercin binaria .................................. .
Comparacin de ordenaciones cuadrticas ................ .
Ordenacin Shell ........................................................................... .
Ordenacin rpida (quicksort) ...................................................... .
15.7.1. Anlisis de la ordenacin rpida ................................ .
Ordenacin por mezcla (mergesort) ............................................ .
Mtodo de ordenacin por montculos (heapsort) ...................... .
15.9.1. Montculo ....................................................................... .
15.9.2. Procedimiento empuja .................................................. ..
15.9.3. Montculo inicial .0
Mtodo de ordenacin binsort .................................................... ..
Mtodo de ordenacin radix-sort.. ............ .................................. ..
Bsqueda lineal ............................................................................. .
15.12.1. Anlisis ........................................................................ .
15.12.2. Eficiencia de la bsqueda lineal ................................ ..
Bsqueda binaria ........................................................................... .
15.13.1. Eficiencia de la bsqueda binaria .............................. .
B
' d b" .
usque a lnarla recursIva ........................................................... .
15.14.1. Funcin bsqueda ...................................................... ..
15.14.2. Procedimiento BusquedaBin ................................ ..


502
502
503
503
507
507
508
509
510

512
514
514
514
517
522
522
525
525
528
529
529
533 .
536
536
539
540
542
544
544
545

'


,
,

~

. . .. " ... "
Contenido
15.15. Mezcla ............................................................................................ .
Resumen ........................................................................................................ .
E
..
Jerclclos ...................................................................................................... .
Pro b 1 emas ................................................................ " .................................... .
. '"

xvii
546
548
548
549
Captulo 16. Anlisis de algoritmos ................................................................. 553
16.1. Medida de la eficiencia de algoritmos ........................................ ..
16.1.1. Anlisis del orden de magnitud .................................... .
16.1.2. Consideraciones de eficiencia ...................................... .
16.1.3. Anlisis de rendimiento ................................................ .
16 1 4 T
d' . ,
. .. lempo e eJeCUClon ..................................................... .
16.2. Notacin O-grande ....................................................................... .
16.2.1. Descripcin de tiempos de ejecucin ............................ .
16.2.2. Definicin conceptual ................................................... ..
16.2.3. Funciones tipo monomio .............................................. ..
,
16.2.4. Ordenes de funciones polinmicas ............................... .
,
16.2.5. Ordenes exponenciales y logartmicas .......................... .
16.2.6. Bases de logaritmos distintas ....................................... ..
16.2.7. Inconvenientes de la notacin O-grande .. .................... .
16.3; La eficiencia de los algoritmos de bsqueda .............................. ..
16.3.1. Bsqueda secuencial .................................................... ..
16.3.2. Bsqueda binaria ........................................................... .
16.4. Anlisis de algoritmos de ordenacin ......................................... ..
16.4.1. Anlisis de la ordenacin por seleccin ....................... .
16.4.2. Anlisis de la ordenacin por burbuja ........................ ..
16.4.3. Anlisis de la ordenacin por insercin ....................... .
16.4.4. Ordenacin por mezcla ................................................. .
16.4.5. Ordenacin rpida ......................................................... .
16.4.6. Anlisis del mtodo Radix Sort ................................... ..
16.5. Tablas comparativas de tiempos .................................................. ..
Resumen ..................................................................................................... .
E
..
JerCICIOS .................................................................................................... .
Problemas ................................................................................................... .
Referencias bibliogrficas ......................................................................... .
Captulo 17. Archivos (ficheros). Fundamentos tericos ............................. .
17.1. Nocin de archivo. Estructura jerrquica .................................... .
17.1.1. Campos .......................................................................... .
17.] .2. Registros ........................................................................ .
17.2. Conceptos, definiciones y terminologa ...................................... .
17.3. Organizacin de archivos ............................................................ ..
17.3.1. Organizacin secuencial ............................................... .
17.3.2. Organizacin directa .................................................... ..
553
554
555
555
555
556
557
557
558
559
559
560
562
563
563
564
565
565
566
567
568
569
570
571
572
573
577
579
581
581
582
583
584
587
588
589
1

,


XVIII Estructura de datos
17.4. Operaciones sobre archivos ......................................................... ..
17.4.1. Creacin de un archivo ................................................. .
17.4.2. Consulta de un archivo .................................................. .
17.4.3. Actualizacin de un archivo ......................................... .
17.4.4. Clasificacin de un archivo ........................................... .
17.4.5. Reorganizacin de un archivo ..................................... ..
17.4.6. Destruccin de un archivo ............................................ .
17 4 7 R
. , ti ., d h
. .. eumon, USlOn e un arc IVO ..................................... ..
17.4.8. Rotura/estallido de un archivo ...................................... .
17.5. Gestin de archivos ....................................................................... .
17.6. Mantenimiento de archivos .......................................................... .
17.6.1. Altas ............................................................................... .
17.6.2. Bajas ....................... .............................. ......................... .
17.6.3. Modificaciones .............................................................. .
17.6.4. Consulta ......................................................................... .
17.6.5. Operaciones sobre registros .......................................... .
17.7. Procesamiento de archivos. Problemas resueltos ........................ .
Resumen ..................................................................................................... .
E
..
J erClClOS .................................................................................................... .
Problemas ................................................................................................... .
Captulo 18.
18.1.
18.2.
18.3.
Tratamiento de archivos de datos ............................................ ..
Archivos de texto .......................................................................... .
Cmo aumentar la velocidad de acceso a archivos ..................... .
18.2.1. Archivos con funcin de direccionamiento hash ........ .
18.2.2. Funciones hash .............................................................. .
18.2.3. Resolucin de colisiones ............................................... .
18.2.4. Realizacin con encadenamiento ................................. .
Archivos indexados ....................................................................... .
18.3.1. Archivo indexado de una fonoteca ............................... .
18.3.2. Programa de manipulacin de archivos indexados ..... .
Resumen ..................................................................................................... .
E
..
Jerclclos .................................................................................................... .
Pro b lemas ................................................................................................... .
Captulo 19.
19.1.
19.2.
19.3.
Ordenacin externa .................................................................... .
Ordenacin externa. Mtodos de ordenacin .............................. .
Mtodo de mezcla directa (mezcla simple) ................................. .
19.2.1. Codificacin ................................................................... .
Mtodo de mezcla equilibrada mltiple ...................................... .
19.3.1. Tipos de datos .......................................... ...................... .
19.3.2. Cambio de finalidad de archivo .................................... .
19.3.3. Control del nmero de tramos ...................................... .
19.3.4. Codificacin ................................................................... .
589
590
590
591
592
592
592
592
593
593
594
595
595
596
596
596
596
613
614
615
617
617
622
622
623
625
636
645
645
650
652
653
653
655
655
656
657
661
661
662
662
663
__ o
., ,._------- - ----- ----- -----_ ..... . ,,'
Contenido
19.4. Mtodo polifsico de ordenacin externa.. .................................. .
19.4.1. Ejemplo con tres archivos ............................................ ..
19.4.2. Ejemplo con cuatro archivos ........................................ .
19.4.3. Distribucin inicial de tramos ...................................... .
19.4.4. Mezcla polifsica versus mezcla mltiple ................... .
19.4.5. Algoritmo de mezcla ..................................................... .
19.4.6. Codificacin ................................................................... .
Resumen ........................................................................................... 0
E
..
Jerclclos .................................................................................................... .
Problemas ................................................................................................... .
Referencias bibliogrficas ......................................................................... .

PARTE V. PROGRAMACIN ORIENTADA A OBJETOS
Captulo 20. Objetos: Conceptos fundamentales y programacin orien-
tada a objetos ............................................................................... .
20.1. La estructura de los objetos: sintaxis ........................................... .
20.1.1. Encapsulamiento ............................................................ .
20.2. Secciones pblica y privada ........................................................ ..
20.2.1. Declaracin de una base ............................................... .
20.2.2. Declaracin de un objeto .............................................. .
20.2.3. Implementacin de los mtodos .................................. ..
20.3. Definicin de objetos mediante unidades .................................... .
20.3.l. Uso de un tipo objeto .................................................... .
20.4. La herencia .................................................................................... .
20.4.l. La herencia con inher i t ed ..................................... .
20.5. Los mtodos ........................... o
20.6. Objetos dinmicos ......................................................................... .
20.6.l.
20.6.2.
20.6.3.
Asignacin de objetos dinmicos ................................. .
Liberacin de memoria y destructores ......................... .
La clusula S e 1 f .......................................................... .
20.7. Polimorfismo ................................................................................. .
20.8.
20.9.
20.10.
20.7.l.
20.7.2.
Constructores y destructores en objetos dinmicos .... .
Anulacin de mtodos heredados ................................. .
Constructores y destructores ........................................................ .
Los procedimientos New y Dispose en POO .............................. .
Mejoras en programacin orientada a objetos ............................ .
20.10.1. La ocultacin mediante public y private ................... .
Resumen ........ ................................................................................................ .
E
,. d "
rrores tlplCOS e programaclon .................................................................. .
E
, "
JerCICIOS ....................................................................................................... .
Problemas ...................................................................................................... .
Referencias bibliogrficas ............................................................................ .
xix
667
667
669
670
671
671
672
, 678
678
679
679
683
684
691
691
692
693
693
694
695
696
702
705
705
705
707
709
714
717
718
721
724
725
726
727
729
730
730
730
.,.



,
XX Estructura de datos
Apndices

Apndice A. Vademcum de Matemticas para la resolucin de algoritmos
, .
numerlCOS . o', oo
Apendice B. Unidades estndar de Turbo Borland Pascal 7 ............................ .
Apndice C.
Apndice D.
Apndice E.
Apndice F.
Apndice G.
Apndice H.
,
B.I. Las unidades estndar ........................................................ .
B.2. La unidad Systern ............................................................ .
B.3. La unidad Printer ........................................................ ..
8.4. La unidad DOS ................................................................... .
B.5. Procedimientos y funciones de la unidad DOS ................ .
B.6. La unidad Crt ................................................................... .
B.7. La unidad Str i ngs: funciones ...................................... ..
Resumen oo oo
El editor de Turbo Pascal 7.0 ...................................................... ..
El entorno integrado de desarrollo de Turbo Pascal 7.0 ............ ..
Depuracin de sus programas en Turbo Pascal .......................... ..
Mensajes y cdigos de error ........................................................ ..
Gua de referencia Turbo Borland Pascal .................................... .
Gua del usuario ISO/ANSI Pascal Estndar .............................. .
Indice ..................................................................................................................... o oo.
733
739
740
740
741
742
744
753
760
764
765
769
783
797
805
829
849

Estructura de datos como disciplina informtica


y de computacin
Una de las disciplinas clsicas en todas las carreras relacionadas con la Informtica o las
Ciencias de la Computacin es Estructura de datos. El estudio de las estructuras de
datos es casi tan antiguo como el nacimiento de la programacin, y se ha convertido en
materia de estudio obligatoria en todos los curriculum desde finales de los aos sesenta
y sobre todo en la dcada de los setenta cuando apareci el lenguaje Pascal de la mano
del profesor Niklaus Wirtz, y posteriormente en la dcada de los ochenta con la apari-
cin de su obra ya clsica Algorihtms and Data Structures en 1986.
Ha sido en la dcada de los ochenta cuando surgieron los conceptos clsicos de es-
tructuras de datos, y aparecieron otros nuevos que se han ido consolidando en la segun-
da mitad de esa dcada, para llegar a implantar la caracterstica distintiva de la dcada de
los noventa, la orientacin a objetos. Una razn para que esta caracterstica se haya
convertido en ncleo fundamental de la programacin que se realiza en los noventa, y
que se seguir realizando en el tercer milenio, ha sido que un objeto encapsula el diseo
o implementacin de un tipo abstracto de datos (TAD). Adems de encapsulacin de
datos, los objetos tambin encapsulan herencia; por ejemplo, una cola es un tipo de lista
con restricciones especficas, de modo que el diseo del tipo de dato Cola puede heredar
algunos de los diseos de mtodos ( operaciones) del tipo de dato Lis t a.
As pues, Estructura de datos. Algoritmos, abstraccin y objetos trata sobre el estu-
dio de las estructuras de datos dentro del marco de trabajo de los tipos abstractos de
datos (TAD) y bajo la ptica del anlisis y diseo de los algoritmos que manipulan esos
tipos abstractos de datos u objetos.
Objetivos y caractersticas
La filosofia con la que se ha construido el libro reside en el desarrollo modular de pro-
gramas que, hoy da, conduce de modo inequvoco a los principios de ingeniera de soft-
ware que facilitan la construccin de grandes programas: abstraccin, legibilidad, com-
prensibilidad y reutilizacin o reusabilidad del software. Estos principios se consiguen
mediante especificacin del software, que supone, a su vez, la separacin entre la espe-

XXI
-
.. ,
,
xxii Estructura de datos
cificacin y la implementacin (unidades en Pascal, paquetes en Ada 95, clases en C++,
etctera) y conduce a la construccin de bibliotecas de componentes (clases y objetos)
que facilitan la construccin de software mediante la reutilizacin de software ya exis-
tente en bibliotecas de funciones y/o componentes,
El lenguaje utilizado en el libro es Pascal y, en particular, la versin Turbo Borland
que soporta el concepto de unidad (mdulo de compilacin separada) y de clases y obje-
tos, y en consecuencia facilita la construccin de tipos abstractos de datos y la progra-
macin orientada a objetos.
Para conseguir esos principios que rigen la construccin de programas siguiendo las
modernas teoras de la ingeniera de software, es preciso fijarse una serie de objetivos
parciales, cuya consecucin lleva al objetivo final: Enseanza. aprendizaje y dominio
de los conceptos de estructuras de datos y sus algoritmos de manipulacin.
En consecuencia, los diferentes objetivos generales que busca el libro son:
Introducir y describir en profundidad las estructuras de datos clsicas (pilas. co-
las. listas. rboles. grafos y archivos) que se encuentran en casi todos los progra-
mas de computadora.
Ensear a los estudiantes y lectores autodidactas, el uso de tcnicas de anlisis y
diseo con las que se pueden evaluar y validar algoritmos.
Proporcionar ejemplos de principios de ingeniera de software y tcnicas de pro-
gramacin que incluyen abstraccin de datos y programacin orientada a objetos.
Introduccin al uso adecuado de las caractersticas especficas de Turbo Borland
Pascal, especialmente aquellas que permiten la compilacin separada: unidades,
tanto predefinidas incorporadas en el compilador como definidas por el usuario.
El lenguaje elegido para implementar los diferentes algoritmos incluidos en el libro
ha sido, como ya se ha comentado, Pascal. La razn esencial ha sido pragmtica: Pascal
sigue siendo, y estamos seguros que as seguir, el lenguaje idneo para ensear a los
estudiantes de Computacin, Informtica y restantes Ingenieras, las tcnicas de progra-
macin estructurada. Cientos de miles, han sido los estudiantes que han aprendido Pas-
cal y ese ha sido su primer lenguaje de programacin, aunque hoy en el campo profesio-
nal haya sido desplazado por otros lenguajes tales como C, C++, Java o Visual Basic.
En cualquier forma, siempre hemos tenido la idea de que los lenguajes de computa-
dora no son slo un mecanismo de descripcin de algoritmos o de programas de compu-
tadoras, sino tambin un vehculo de concepcin, reflexin y anlisis, en la resolucin
de problemas con computadora. Por ello, pensamos que Pascal, como cualquier otro
lenguaje estructurado o incluso un pseudolenguaje, como puede ser un pseudocdigo,
servir para conseguir el rigor y el formalismo que el profesor quiera conseguir con sus
alumnos, o el propio estudiante se marque siguiendo las directrices de sus maestros o
profesores.
Desde un punto de vista cientfico, el libro se ha escrito apoyndose en las obras de
las autoridades ms reconocidas en el campo de algoritmos y estructuras de datos, fun-
damentalmente D. E. Knuth y N. Wirth, y las inestimables obras de A. V. Aho, J. Hop-
croft, 1. D. Ullman, E. Horowitz, D. Sahni, B. Liskov, entre otros, y que el lector encon-


Prlogo

trar en las referencias bibliogrficas que acompaan a algunos captulos o en la biblio-
grafia final del libro.

El libro como texto de referencia universitaria y profesional
Estructura de datos es una disciplina acadmica que se incorpora a todos los planes de
estudios de carreras universitarias de Ingeniera Informtica, Ingeniera en Sistemas
Computacionales y Licenciatura en Informtica, as como suele ser tambin frecuente la
incorporacin en planes de estudios de informtica en Formacin Profesional o Institu-
tos Politcnicos. Suele considerarse tambin Estructuras de datos como una extensin
de las asignaturas de Programacin, en cualquiera de sus niveles. Por estas circunstan-
cias han nacido numerosas iniciativas de incorporacin de esta disciplina a los diferen-
tes planes de estudios. .
Este es el caso de Espaa. Los planes de estudios de Ingeniera en Illfonntica, Inge-
niera Tcnica en Informtica de Sistemas e Ingeniera Tcnica en Informtica de Ges-
tin incluyen, todos ellos, una materia troncal llamada Estructura de datos, que luego se
convierte en asignaturas anuales o semestrales. El Consejo de Universidades no slo
obliga a las universidades a incluir esta asignatura como materia troncal, y en conse-
cuencia asignatura obligatoria, sino que adems recomienda descriptores para la mis-
ma. As estos descriptores son: tipos abstractos de datos, estructuras de datos y algoritmos
de manipulacin, ficheros (archivos)>>. En esta edicin se ha dejado fuera del contenido
del libro el descriptor bases de datos, por entender que suele constituir parte de una
asignatura especfica que an formando parte de Estructura de datos suele tener entidad
propia o complementaria. De igual fOl ma la organizacin internacional ACM recomien-
da un curriculum para la carrera de Computer Science, equivalente a las carreras univer-
sitarias espaolas ya citadas. Asimismo, todos los pases de Iberoamrica han incluido
tambin la asignatura Estructura de datos en sus currculos. As nos consta por nuestras
numerosas visitas profesionales a universidades e institutos tecnolgicos de Mxico, Cuba,
Venezuela, Guatemala, etc., donde hemos podido examinar sus planes de estudios e inter-
cambiar experiencias, tanto con profesores (maestros) como con estudiantes.
Estructuras de datos: Algoritmos, abstraccin y objetos. Siguen las recomendacio-
nes dadas por el Consejo de Universidades de Espaa para las carreras de Ingeniera
Informtica, tanto la superior como la tcnica, y se ha adaptado en la medida de lo posi-
ble al curriculum recomendado por la ACM, en particular el curso C2 (Curriculum '78,
CACM 3/79 y CACM 8/85). Asimismo se adapta a cursos tpicos sobre conocimiento de
algoritmos y estructura de datos, as como de los lenguajes de programacin, segn se
describe en el informe Computing Curricula 1991 del ACM/IEEE-CS (CommunACM 34,
6 junio 1991) Joint Curriculum Task Force. El libro trata de ajustarse a las directrices
dadas para Estructura de datos y Anlisis de algoritmos propuestos en ese informe y se
puede usar como materia fundamental y/o complementaria de un curso normal de cien-
cias de la computacin para graduados y no graduados.
El texto se ha diseado para un curso de dos cuatrimestres (semestres), de algoritmos
y estructuras de datos. Su divisin seleccin del captulo y adscripcin a uno u otro
.
I
xxiv Estructura de datos
cuatrimestre, creemos deben ser decididos por el profesor (maestro) en funcin de su
experiencia y de los objetivos marcados. Podra servir para un cuatrimestre siempre que
hubiese una seleccin adecuada del profesor y se tuviera en cuenta la formacin previa
del estudiante.

Requisitos
El nico requisito previo para los estudiantes que emplean este texto es un curso de uno
o dos semestres, de programacin con diseo de algoritmos mediante pseudocdigos, o
lenguajes estructurados, tales como FORTRAN, Pascal, C, C++ o Java. Los estudiantes
que han estudiado sus cursos de programacin sin utilizar el lenguaje Pascal, pueden
seguir este libro junto con alguno de los libros de texto que se listan en la bibliografia
final del libro o en las referencias bibliogrficas de los captulos 1 y 2. No obstante, se
han incluido varios apndices sobre Pascal y Turbo Pascal que pensamos ser suficiente,
al menos, a nivel de sintaxis para refrescar o adquirir aquellos conocimientos bsicos
necesarios para seguir la calificacin de los diferentes algoritmos del libro.
Depuracin
Todos los programas y algoritmos del texto se han probado y depurado. Adems de nuestra
tarea de puesta a punto de programas, diferentes profesores nos han ayudado en esta
tarea. Este es el caso de Matilde Femndez, Lucas Snchez, Jess Prez, Isabel Torralvo
y M.
a
del Mar Garca, todos ellos profesores de la Facultad de Informtica y Escuela
Universitaria de Informtica de la Universidad Pontificia de Salamanca en el campus de
Madrid. Su entusiasmo y el cario puesto en esta actividad ha sido desbordante y siem-
pre aportaron sugerencias valiosas. Por supuesto, que cualquier error que todava pudie-
ra existir, es absoluta responsabilidad de los autores.
Los ejercicios y problemas de los diferentes captulos varan en tipo y dificultad.
Algunos son reiterativos para confirmar la comprensin de los textos. Otros implican
modificaciones a programas o algoritmos presentados. Se han incluido gran cantidad de
problemas de programacin con diferentes niveles de complejidad que confiamos sean
complementos eficientes a la formacin conseguida por el lector.
Contenido
Este libro se ha dividido en cinco partes y ocho apndices.
Parte 1: Abstraccin y Programacin: Introduccin a la ingeniera de software. Esta
parte contiene los captulos 1, 2 y 3 y describe una introduccin a la metodologa de
construccin de grandes programas, una comparacin entre los conceptos de mdulos y
unidades, as como el importante concepto de abstraccin de datos.
Prlogo XXV
Parte 11: Fundamentos bsicos de estructuras de datos y tipos abstractos de datos.
Esta parte contiene la descripcin del importante tipo de dato llamado puntero, junto
con la descripcin de las estructuras de datos ms tpicas: listas enlazadas, listas doble-
mente enlazadas, pilas y colas.
Parte 111: Estructuras de datos avanzadas. Las estructuras rboles binarios, equili-
brado y B, grafos, junto con el estudio de algoritmos recursivos y de manipulacin de
las citadas estructuras de datos, son el tema central de esta parte.
Parte IV: Archivos y ordenacin. En esta parte se tratan los importantes algoritmos de
manipulacin de ordenacin, bsqueda y mezcla, junto con el concepto de archivo y su
tratamiento; otro concepto importante que se estudia en esta parte, es el Anlisis de Al-
goritmos, como tcnica indispensable para conseguir algoritmos eficientes.
Parte V: En esta parte se introduce al lector en programacin orientada a objetos,
apoyada en el concepto de objeto como extensin de un tipo abstracto de datos.
Una descripcin detallada de los diferentes captulos se proporciona a continuacin.
El captulo 1 es una introduccin a la metodologa de construccin de software, as como
las tcnicas de ingeniera de software. Se describen las herramientas usuales para la
resolucin de problemas junto con las diferentes etapas del ciclo de vida del software.
Asimismo se enumeran los principios de diseo de sistemas de software, junto con nor-
mas para un estilo de programacin, documentacin, depuracin y pruebas.
En el captulo 2 se describe el concepto de mdulo y cmo se puede implementar en
Turbo Pascal, mediante unidades. Se describe el concepto de unidad, el modo de crea-
cin y de utilizacin de las mismas. El importante concepto de abstraccin de datos y su
implementacin mediante tipos abstractos de datos.
En el captulo 3 se comienza el estudio de la orientacin a objetos as como los dife-
rentes lenguajes de programacin orientados a objetos, junto al importante concepto de
reutilizacin de software.
El captulo 4 proporciona una introduccin a las estructuras de datos dinmicas. El
captulo describe el tipo de dato puntero en Pascal y muestra cmo utilizar la asignacin
dinmica de memoria.
El tipo abstracto de dato Lista, se estudia en el captulo 5. La implementacin ms
usual son las listas enlazadas y por esta razn se analizan sus algoritmos de manipula-
cin. Uno de los casos ms frecuentes en el diseo y construccin de estructura de datos
es la ordenacin de elementos. El captulo describe el caso particular de las listas enla-
zadas.
Otros tipos de listas muy utilizadas en la manipulacin de estructuras de datos son
las listas doblemente enlazadas y las listas circulares. Sus algoritmos de implementa-
cin se estudian en el captulo 6.
Las pilas y las colas son otros tipos de datos muy usuales en cualquier programa de
software. Por esta razn se estudian en detalle junto con los procedimientos y funciones
necesarios para poder utilizarlas. Estas estructuras de datos son listas, por lo que su
,

XXVI Estructura de datos
implementacin se realizar, no slo con arrays, sino fundamentalmente mediante listas
enlazadas o circulares. Los tipos abstractos de datos pila y cola se describen en los cap-
tulos 7 y 8.
El captulo 9 se dedica a la descripcin de la recursividad as como al uso de proce-
dimientos y funciones recursivas. La recursividad es una propiedad esencial en el diseo
de tcnicas algortmicas, por esta circunstancia se hace un estudio exhaustivo y detalla-
do de los algoritmos recursivos clsicos y aquellos otros ms complejos. As se analizan
los tpicos algoritmos de divide y vencers, como es el popular algoritmo de las Torres
de Hanoi, hasta los algoritmos de vuelta atrs (backtraking) ms famosos y eficientes
tales como: el problema de las ocho reinas, el problema de la mochila o el proble-
ma de los matrimonios estables.

El captulo 10 introduce al tipo de dato Arbol binario. Los rboles binarios son es-
tructuras de datos recursivas y la mayora de sus propiedades se pueden definir recursi-
vamente. Los rboles binarios tienen numerosas aplicaciones; entre ellas una de las ms
usuales es la evaluacin de expresiones. En el captulo se describen tambin los descen-
dientes de los rboles binarios, como es el caso de los rboles binarios de bsqueda. Las
operaciones en los rboles binarios de bsqueda son motivo de anlisis a lo largo del
captulo.
Otro tipo de extensiones rboles son los complejos y eficientes rboles B y r-
boles AVL o equilibrados. Sus algoritmos de manipulacin se describen en los cap-
tulos 11 y 12.
Los grafos son uno de los tipos de datos ms clsicos y de mayor utilidad en el
diseo de problemas complejos. La implementacin y los algoritmos de manipulacin
de grafos se estudian en el captulo 13. Sin embargo, un estudio completo de grafos y de
la teora de grafos requiere mucho ms que un captulo; por esta circunstancia, se exami-
nan aspectos avanzados en el captulo 14. As, se describen algoritmos complejos tales
como los algoritmos de Dijkstra, Warshall, Floyd o Kruskal.
Los mtodos clsicos de ordenacin, bsqueda y mezcla, tanto los ms sencillos has-
ta otros complejos, se describen en el captulo 15. As se analizan los mtodos de orde-
nacin por burbuja, seleccin, insercin, Shell, quicksort (rpido), mergesort (mezcla) o
heapsort (montculo), junto con la ordenacin binaria (binsort) o radix (Radix-sort).
Las tcnicas de anlisis de algoritmos y la medida de la eficiencia de los mismos se
analizarn en el captulo 16. La notacin O grande utilizada en el anlisis de algoritmos
se describe en dicho captulo 16.
La estructura de datos clsica en cuanto a organizacin de los datos son los archivos
(ficheros). La organizacin de archivos junto con las operaciones sobre los mismos se
describen en el captulo 17. En el captulo 18 se describen los archivos de texto y los
archivos indexados, junto con las tcnicas de direccionamiento aleatorio (hash).
La ordenacin externa de estructuras de datos junto con los mtodos de implementa-
. cin correspondiente se estudian en el captulo 19.
El captulo 20 realiza una descripcin del tipo de dato objeto junto con la implemen-
tacin de las propiedades clsicas que soportan tales como herencia y polimorfismo.
Los apndices complementan el contenido terico del libro. El Apndice A es un
vademcum de frmulas matemticas que se requieren normalmente en la construccin
Prlogo xxvii
de algoritmos no slo numricos sino de gestin. El concepto de mdulo o unidad en
Turbo Pascal es motivo de estudio en el apndice B, donde se describen las unidades
estndar del compilador. El apndice C describe el editor de texto del compilador as
como la descripcin de su funcionalidad. El apndice E describe los mtodos de depura-
cin de programas en Turbo Borland Pascal y los mensajes y cdigos de error se inclu-
yen en el apndice F. El apndice G es una amplia gua de referencia de sintaxis del
compilador de Turbo Borland Pascal. El apndice H es una gua de usuario de ISO/
ANSI Pascal pensado en aqueIlos lectores que utilicen un compilador de Pascal estndar
distinto del compilador Turbo Borland Pascal.
AGRADECIMIENTOS
Este libro no es slo fruto del trabajo de los autores, tal y como sucede con la creacin
de la mayora de los libros tcnicos. Muchas personas han colaborado de una u otra
manera para que este libro vea la luz.
Entre estas personas queremos destacar aqueIlas que ms han influido en la versin
ltima. Los profesores de Estructuras de datos, Lucas Snchez, Matilde Fernndez y
Jess Prez, del Departamento de Lenguajes y Sistemas Informticos e Ingeniera de
Software de la Facultad de Informtica y de la Escuela Universitaria de Informtica de
la Universidad Pontificia de Salamanca (UPSA), con sus aportaciones y sugerencias fru-
to de su larga experiencia como profesores de la asignatura Estructura de datos en el
campus de Madrid, han ledo y revisado las primeras pruebas de imprenta de este libro,
y nos han dado ideas y sugerencias que han mejorado notablemente el libro. Las profe-
soras M.
a
Mar Garca e Isabel Torralvo y el profesor Joaqun Abeger, todos del mismo
departamento que los profesores anteriores, tambin han ledo las galeradas del texto y
han detectado erratas y depurado muchos programas del libro.
Adems de los profesores anteriores, otros profesores de la Facultad y Escuela Uni-
versitaria de Informtica de UPSA han ayudado y apoyado a que esta obra sea una rea-
,
lidad: Paloma Centenera, Luis Villar y Angel Hermoso.
A todos deseamos agradecer nuestro reconocimiento por su arduo trabajo. No slo
nos han demostrado que son colegas, sino y sobre todo son amigos. Nuestras gracias
ms sinceras a todos eIlos, sin su apoyo y trabajo esta obra no sera la misma.
Naturalmente, no seramos justos si no reconociramos la inmensa ayuda que ha
supuesto y seguir suponiendo las sugerencias, consejos y crticas que nuestros numero-
sos alumnos de todos estos aos pasados nos han hecho tanto en Espaa como en Lati-
noamrica. Son el mejor aliciente que cualquier profesor puede tener. En nuestro caso
ha sido una realidad vivida da a da. Nuestro agradecimiento eterno.
Una ltima reflexin
Estructura de datos es una disciplina clave en los curriculum universitarios de inform-
tica y computacin. En nuestra obra hemos volcado nuestra experiencia de ms de diez

,
,
I

XXVIII Estructura de datos
aos en la enseanza universitaria; nuestra esperanza es que hayamos conseguido trans-
mitir dicha experiencia, y que nuestros lectores puedan no slo iniciarse en el aprendiza-
je de las estructuras de los datos, sino llegar a dominar su concepto, organizacin, dise-
o y manipulacin de los algoritmos correspondientes. El mayor deseo de los autores
sera poder conseguir los objetivos del libro, que su aprendizaje sea gradual y que lle-
guen a dominar este vital e importante campo informtico de las estructuras de datos.

Madrid, julio de 1998
Los autores


,
''''f>,-.: ',',>.' ,,' ',,:
,

-,
1
,
,
,
I
,,',,;'.
PARTE
,
,
,
I
,
,
,
,
,
,
,
CAPITULO
n
a
. ,
enlerla eso
. . ,
are: Intro ucclon
a meto
,
o o la
. ,
e construcclon
e es I ro
.- - _ ., _. -.
.. r, '" _ . :-:-, -: -/ ';"':. ','.
CONTE
1 .1 . Abstraccin.'
1.2. Resolucin de problemas de programacin.
1.3. Herramientas para la resolucin de problemas.
1.4. Factores en la calidad del software.
1.5. El ciclo de vida del software.
1.6. Mtodos formales de verificacin de programas.
1.7. Principios de diseos de sistemas de software.
1.8. Estilo de programacin.
1.9. La documentacin.
1.10. Depuracin.
1.11. Diseo de algoritmos.
1.12. Pruebas (testing).
1.13. Eficiencia.
1.14. Transportabilidad (portabilidad).
RESUMEN.
EJERCICIOS.
PROBLEMAS.

La produccin de un programa se puede dividir en diferentes fases:
anlisis, diseo, codificacin y depuracin, prueba y mantenimiento.
Estas fases se conocen como ciclo de vida del software, y son los prin-
cipios bsicos en los que se apoya la ingeniera del software. Deben
considerarse siempre todas las fases en el proceso de creacin de pro-
gramas, sobre todo cuando stos son grandes proyectos. La ingeniera
de o del software trata de la creacin y produccin de programas a
gran escala.
3
4 Estructura de datos
,
1.1. ABSTRACCION
Los seres humanos se han convertido en la especie ms influyente de este planeta, debido
a su capacidad para abstraer el pensamiento. Los sistemas complejos, sean naturales o
artificiales, slo pueden ser comprendidos y gestionados cuando se omiten detalles que son
irrelevantes a nuestras necesidades inmediatas. El proceso de excluir detalles no deseados
o no significativos, al problema que se trata de resolver, se denomina abstraccin, y es
algo que se hace en cualquier momento.
Cualquier sistema de complejidad suficiente se puede visualizar en diversos niveles
de abstraccin dependiendo del propsito del problema. Si nuestra intencin es conseguir
una visin general del proceso, las caractersticas del proceso presente en nuestra abstrac-
cin constar principalmente de generalizaciones. Sin embargo, si se trata de modificar
partes de un sistema, se necesitar examinar esas partes con gran nivel de detalle. Consi-
deremos el problema de representar un sistema relativamente complejo tal como un coche.
El nivel de abstraccin ser diferente segn sea la persona o entidad que se relaciona con
el coche: conductor, propietario, fabricante o mecnica.
As, desde el punto de vista del conductor sus caractersticas se expresan en trminos
de sus funciones (acelerar, frenar, conducir, etc.); desde el punto de vista del propietario
sus caractersticas se expresan en funcin de nombre, direccin, edad; la mecnica del
coche es una coleccin de partes que cooperan entre s para proveer las funciones citadas,
mientras que desde el punto de vista del fabricante interesa precio, produccin anual de
la empresa, duracin de construccin, etc. La existencia de diferentes niveles de abstrac-
cin conduce a la idea de una jerarqua de abstracciones.
Las soluciones a problemas no triviales tiene una jerarqua de abstracciones de modo
que slo los objetivos generales son evidentes al nivel ms alto. A medida que se des-
ciende en nivel los aspectos diferentes de la solucin se hacen evidentes.
En un intento de controlar la complejidad, los diseadores del sistema explotan las
caractersticas bidimensionales de la jerarqua de abstracciones. La primera etapa al tratar
con un problema grande es seleccionar un nivel apropiado a las herramientas (hardware
y software) que se utilizan para resolverlo. El problema se descompone entonces en subpro-
blemas que se pueden resolver independientemente de modo razonable.
, ,
1.2. RESOLUCION DE PROBLEMAS DE PROGRAMACION
El trmino resolucin del problema se refiere al proceso completo de tomar la descrip-
cin del problema y desarrollar un programa de computadora que resuelva ese proble-
ma. Este proceso requiere pasar a travs de muchas fases: desde una buena comprensin
del problema a resolver, hasta el diseo de una solucin conceptual, para implementar la
solucin con un programa de computadora.
Realmente qu es una solucin? Normalmente, una solucin consta de dos compo-
nentes: algoritmos y medios para almacenar datos. Un algoritmo es una especificacin
concisa de un mtodo para resolver un problema. Una accin que un algoritmo realiza con
frecuencia es operar sobre una coleccin de datos. Por ejemplo, un algoritmo puede

i

,
,
I

,


I


"
!
Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 5
tener que poner menos datos en una coleccin, quitar datos de una coleccin o realizar
preguntas sobre una coleccin de datos. Cuando se construye una solucin, se deben
organizar sus colecciones de datos de modo que se pueda operar sobre los datos fcil-
mente en la manera que requiera el algoritmo. .
Sin embargo, no slo se necesita almacenar los datos en estructuras de datos sino
tambin operar sobre esos datos. De este modo una entidad fundamental ser el tipo
abstracto de datos (TAO) (Abstract Data Type, ADT), que es una coleccin de datos y
un conjunto de operaciones que actan sobre esos datos. Por ejemplo, supongamos que
se necesita almacenar una coleccin de nombres de futbolistas de modo que permita una
bsqueda rpida de un nombre dado. El algoritmo de bsqueda binaria que se estudiar
en el captulo 15 pellnitir buscar en una lista (un array) eficientemente, si el array o
lista est ordenado. Por consiguiente, una solucin a este problema es almacenar los
nombres ordenados en un array y utilizar un algoritmo de bsqueda binaria para buscar
en el array un nombre especificado. Un TAD que visualice el array ordenado junto con
el algoritmo de bsqueda binaria resolver el problema.
1.3. HER ENTAS PARA LA RESOLUCiN DE PROBLEMAS
Diferentes herramientas ayudan al programador y al ingeniero de software a disear una
solucin para un problema dado. Algunas de estas herramientas son diseo descendente,
abstraccin procedimental, abstraccin de datos, ocultacin de la informacin, recursin
o recursividad y programacin orientada a objetos.
1.3.1. Diseo descendente
Cuando se escriben programas de tamao y complejidad moderada, nos enfrentamos a la
dificultad de escribir dichos programas. La solucin para resolver estos problemas
y, naturalmente, aquellos de mayor tamao y complejidad, es recurrir a la modularidad
mediante el diseo descendente. Qu significa diseo descendente y modularidad? La
filosofia del diseo descendente reside en que se descompone una tarea en sucesivos
niveles de detalle. Para ello se divide el programa en mdulos independientes proce-
dimientos, funciones y otros bloques de cdigo ,como se observa en la Figura 1.1.
Programa
principal
..'
Funcin F, Funcin F
2
Procedimiento P,
Figura 1.1. Un prOgrama dividido en mdulos independientes.
,
,

-------------_._ .. - ..
6 Estructura de datos
El concepto de solucin modular se aprecia en la aplicacin de la Figura 1.2, que
busca encontrar la nota media de un conjunto de notas de una clase de informtica.
Existe un mdulo del ms alto nivel que se va refinando en sentido descendente para
encontrar mdulos adicionales ms pequeos. El resultado es una jerarqua de mdulos;
cada mdulo se refina por los de bajo nivel que resuelve problemas ms pequeos
y contiene ms detalles sobre los mismos. El proceso de refinamiento contina hasta que
los mdulos de nivel inferior de la jerarqua sean tan simples como para traducirlos direc-
tamente a procedimientos, funciones y bloques de cdigo en Pascal o C, que resuelven
problemas independientes muy pequeos. De hecho, cada mdulo de nivel ms bajo
debe ejecutar una tarea bien definida. Estos mdulos se denominan altamente cohesivos.
Cada mdulo se puede dividir en subtareas. Por ejemplo, se puede refinar la tarea de
leer las notas de una lista, dividindolo en dos subtareas. Por ejemplo, se puede refinar
la tarea de leer las notas de la lista en otras dos subtareas: pedir al usuario una nota
y situar la nota en la lista.
1.3.2. Abstraccin procedimental
Cada algoritmo que resuelve el diseo de un mdulo equivale a una caja negra que ejecuta
una tarea determinada. Cada caja negra especifica lo que hace pero no cmo lo hace, y
de igual modo cada caja negra conoce cuantas cajas negras existen y lo que hacen.
Normalmente, estas cajas negras se implementan como subprogramas. Una abstrac-
cin procedimental separa el propsito de un subprograma de su implementacin. Una
vez que un subprograma se haya escrito o codificado, se puede usar sin necesidad de
conocer su cuerpo y basta con su nombre y una descripcin de sus parmetros.
La modularidad y abstraccin procedimental son complementarios. La modularidad
implica romper una solucin en mdulos; la abstraccin procedimental implica la espe-
cificacin de cada mdulo antes de su implementacin en Pascal. El mdulo implica que
se puede cambiar su algoritmo concreto sin afectar el resto de la solucin.
Encontrar
la media
Leer las notas Ordenar
Obtener el
elemento central
de la lista la lista
de la lista
Pedir al usuario Situar la nota
una lista en la lista
Figura 1.2. Diagrama de bloques que muestra la jerarqua de mdulos.
--- .- ._-------------------------------------... - - --- - - -----------------
Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 7
La abstraccin procedimental es esencial en proyectos complejos, de modo que se pue-
dan utilizar subprogramas escritos por otras personas, sin necesidad de tener que conocer
sus algoritmos.
1.3.3. Abstraccin de datos
La abstraccin procedimental significa centrarse en lo que hace un mdulo en vez de
en los detalles de cmo se implementan los detalles de sus algoritmos. De modo similar,
la abstraccin de datos se centra en las operaciones que se ejecutan sobre los datos en
vez de cmo se implementarn las operaciones.
Como ya se ha comentado antes, un tipo abstracto de datos (TAD) es una colec-
cin de datos y un conjunto de operaciones sobre esos datos. Tales operaciones pueden
aadir nuevos datos, o quitar datos de la coleccin, o buscar algn dato. Los otros mdu-
los de la solucin conocern qu operaciones puede realizar un TAD. Sin embargo, no
conoce cmo se almacenan los datos ni cmo se realizan esas operaciones.
Cada TAD se puede implementar utilizando estructuras de datos. Una estructura de
datos es una construccin que se puede definir dentro de un lenguaje de programacin
para almacenar colecciones de datos. En la resolucin de un problema, los tipos abstractos
de datos soportan algoritmos y los algoritmos son parte de los que constituye un TAD.
Para disear una solucin, se deben desarrollar los algoritmos y los TAD al unsono.
1.3.4. Ocultacin de la informacin
La abstraccin identifica los aspectos esenciales de mdulos y estructura de datos que
se pueden tratar como cajas negras. La abstraccin es responsable de sus vistas externas
o pblicas, pero tambin ayuda a identificar los detalles que debe ocultar de la vista
pblica (vista privada). El principio de ocultacin de la informacin no slo oculta los
detalles dentro de la caja negra, sino que asegura que ninguna otra caja negra pueda
acceder a estos detalles ocultos. Por consiguiente, se deben ocultar ciertos detalles dentro
de sus mdulos y TAD y los hacen inaccesibles a otros mdulos y TAD.
Un usuario de un mdulo no se preocupa sobre los detalles de su implementacin y,
al contrario, un desarrollador de un mdulo o TAD no se preocupa sobre sus usos.
1.3.5. Programacin orientada a objetos
Los conceptos de modularidad, abstraccin procedimental, abstraccin de datos y ocul-
tacin de la informacin conducen a la programacin orientada a objetos, basada en el
mdulo o tipo de dato objeto.
Las prioridades fundamentales de un tipo son: encapsulamientos, herencia y polimor-
fismo. El encapsulamiento es la combinacin de datos y operaciones que se pueden
ejecutar sobre esos datos en un objeto. En Turbo Borland Pascal el encapsulamiento en
un objeto se codifica mediante una unidad.
Herencia es la propiedad que permite a un objeto transmitir sus propiedades a otros
objetos denominados descendientes; la herencia permite la reutilizacin de objetos que

8 Estructura de datos
se hayan definido con anterioridad. El polimorfismo es la propiedad que permite deci-
dir en tiempo de ejecucin la funcin a ejecutar, al contrario que sucede cuando no exis-
te polimorfismo en el que la funcin a ejecutar se decide previamente y sin capacidad de
modificacin, en tiempo de ejecucin.
1.4. FACTORES EN LA CALIDAD DEL SOFTWARE
La construccin de software requiere el cumplimiento de numerosas caractersticas. Entre
ellas se destacan las siguientes:
Eficiencia
La eficiencia de un software es su capacidad para hacer un buen uso de los recursos que
manipula.
Transportabilidad (portabilidad)
La transportabilidad o portabilidad es la facilidad con la que un software puede ser
transportado sobre diferentes sistemas fisicos o lgicos.
Verificabilidad (facilidad de verificacin)
La verificabilidad o facilidad de verificacin de un software es su capacidad para sopor-
tar los procedimientos de validacin y de aceptar juegos de test o ensayo de programas.
Integridad
La integridad es la capacidad de un software a proteger sus propios componentes contra
los procesos que no tenga el derecho de acceder.
Facilidad de utilizacin
Un software es fcil de utilizar si se puede comunicar consigo de manera cmoda.
Correccin (exactitud)
Capacidad de los productos software de realizar exactamente las tareas definidas por su
especificacin.
Robustez
Capacidad de los productos software de funcionar incluso en situaciones anormales .


i

I
1

Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 9


Extensibilidad
Facilidad que tienen los productos de adaptarse a cambios en su especificacin. Existen
dos principios fundamentales para conseguir esto:
diseo simple;
descentralizacin.
Reutilizacin
Capacidad de los productos de ser reutilizados, en su totalidad o en parte, en nuevas
aplicaciones.
Compatibilidad
Facilidad de los productos para ser combinados con otros.
1.5. EL CICLO DE VIDA DEL SOFTWARE
Existen dos niveles en la construccin de programas: aquellos relativos a pequeos pro-
gramas (los que normalmente realizan programadores individuales) y aquellos que se
refieren a sistemas de desarrollo de programas grandes (proyectos de software) y que,
generalmente, requieren un equipo de programadores en lugar de personas individuales.
El primer nivel se denomina programacin a pequea escala; el segundo nivel se deno-
mina programacin a gran escala.
La programacin en pequea escala se preocupa de los conceptos que ayudan a crear pe-
queos programas aquellos que varan en longitud desde unas pocas lneas a unas pocas
pginas . En estos programas se suele requerir claridad y precisin mental y tcnica. En
realidad, el inters mayor desde el punto de vista del futuro programador profesional est
en los programas de gran escala que requiere de unos principios slidos y firmes de lo que
se conoce como ingeniera de software y que constituye un conjunto de tcnicas para facilitar
el desarrollo de programas de computadora. Estos programas o mejor proyectos de software
estn realizados por equipos de personas dirigidos por un director de proyectos (analista o
ingeniero de software) y los programas pueden tener ms de 100.000 lneas de cdigo.
El desarrollo de un buen sistema de software se realiza durante el ciclo de vida que
es el periodo de tiempo que se extiende desde la concepcin inicial del sistema hasta su
eventual retirada de la comercializacin o uso del mismo. Las actividades humanas rela-
cionadas con el ciclo de vida implican procesos tales como anlisis de requisitos, diseo,
implementacin, codificacin, pruebas, verificacin, documentacin, mantenimiento y
evolucin del sistema y obsolescencia. En esencia el ciclo de vida del software comienza
con una idea inicial, incluye la escritura y depuracin de programas, y contina durante
aos con correcciones y mejoras al software original l.
I Carrasco, Hellman y Verof: Data structures and problem solving with Turbo Pascal, The Benjamingl
Cummings Publishing, 1993, pg. 210 .

I
,

10 Estructura de datos
El ciclo de vida del software es un proceso iterativo, de modo que se modificarn las
sucesivas etapas en funcin de la modificacin de las especificaciones de los requisitos
producidos en la fase de diseo o implementacin, o bien una vez que el sistema se ha
implementado, y probado, pueden aparecer errores que ser necesario corregir y depu-
rar, y que requieren la repeticin de etapas anteriores.
La Figura 1.3 muestra el ciclo de vida de software y la disposicin tpica de sus
diferentes etapas en el sistema conocido como ciclo de vida en cascada, que supone que
la salida de cada etapa es la entrada de la etapa siguiente.
1.5.1. Anlisis
La primera etapa en la produccin de un sistema de software es decidir exactamente qu
se supone ha de hacer el sistema; esta etapa se conoce tambin como anlisis de requisitos
o especificaciones y por esta circunstancia muchos tratadistas suelen subdividir la etapa
en otras dos:
Anlisis y definicin del problema.
Especificacin de requisitos.
La parte ms dificil en la tarea de crear un sistema de software es definir cul es el
problema y a continuacin especificar lo que se necesita para resolverlo. Normalmente
la definicin del problema comienza analizando los requisitos del usuario, pero estos
requisitos, con frecuencia, suelen ser imprecisos y dificiles de describir. Se deben especi-

ficar todos los aspectos del problema, pero con frecuencia las personas que describen el
problema no son programadores yeso hace imprecisa la definicin. La fase de especifica-
cin requiere normalmente la comunicacin entre los programadores y los futuros usua-
rios del sistema e iterar la especificacin, hasta que tanto el especificador como los usuarios
estn satisfechos de las especificaciones y hayan resuelto el problema normalmente.
Anlisis
..
Diseo
Implementacin
Depuracin
Mantenimiento
Figura 1.3. Ciclo de vida del software.
,


.
.,

1
Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 11
En la etapa de especificaciones puede ser muy til para mejorar la comunicacin
entre las diferentes partes implicadas construir un prototipo o modelo sencillo del sistema
final; es decir, escribir un programa prototipo que simule el comportamiento de las partes
del producto software deseado. Por ejemplo, un programa sencillo incluso ineficien-
te puede mostrar al usuario la interfaz propuesta por el analista. Es mejor descubrir
cualquier dificultad o cambiar su idea original antes que la programacin se encuentre
en estado avanzado o, incluso, terminada. El modelado de datos es una herramienta muy
importante en la etapa de definicin del problema. Esta herramienta es muy utilizada en
el diseo y construccin de bases de datos.
Tenga presente que el usuario final, normalmente, no conoce exactamente lo que desea
haga el sistema. Por consiguiente, el analista de software o programador, en su caso, debe
interactuar con el usuario para encontrar lo que el usuario desear haga el sistema. En
esta etapa se debe responder a preguntas tales como:
Cules son los datos de entrada?
Qu datos son vlidos y qu datos no son vlidos?
Quin utilizar el sistema: especialistas cualificados o usuarios cualesquiera (sin
formacin)?
Qu interfaces de usuario se utilizarn?
Cules son los mensajes de error y de deteccin de errores deseables? Cmo
debe actuar el sistema cuando el usuario cometa un error en la entrada?
Qu hiptesis son posibles?
Existen casos especiales?
Cul es el formato de la salida?
Qu documentacin es necesaria?
Qu mejoras se introducirn probablemente al programa en el futuro?
Cmo debe ser de rpido el sistema?
Cada cuanto tiempo ha de cambiarse el sistema despus que se haya entregado?
El resultado final de la fase de anlisis es una especificacin de los requisitos del
software.
Descripcin problema

Prototipos de
1.5.2. Diseo
La especificacin de un sistema indica lo que el sistema debe hacer. La etapa de diseo
del sistema indica cmo ha de hacerse. Para un sistema pequeo, la etapa de diseo puede
ser tan sencilla como escribir un algoritmo en pseudocdigo. Para un sistema grande, esta
etapa incluye tambin la fase de diseo de algoritmos, pero incluye el diseo e interaccin
de un nmero de algoritmos diferentes, con frecuencia slo bosquejados, as como una
estrategia para cumplir todos los detalles y producir el cdigo correspondiente.
,

.

,
12 Estructura de datos
Es preciso determinar si se pueden utilizar programas o subprogramas que ya exis-
ten o es preciso construirlos totalmente. El proyecto se ha de dividir en mdulos utili-
zando los principios de diseo descendente. A continuacin se debe indicar la interaccin
entre mdulos; un diagrama de estructuras proporciona un esquema claro de estas rela-
ciones 2.
En este punto, es importante especificar claramente no slo el propsito de cada
mdulo, sino tambin el flujo de datos entre mdulos. Por ejemplo, se debe responder a
las siguientes preguntas: Qu datos estn disponibles al mdulo antes de su ejecucin?
Qu supone el mdulo? Qu hacen los datos despus de que se ejecuta el mdulo? Por
consiguiente, se deben especificar en detalle las hiptesis, entrada y salida para cada
mdulo. Un medio para realizar estas especificaciones es escribir una precondicin, que
es una descripcin de las condiciones que deben cumplirse al principio del mdulo, y una
postcondicin, que es una descripcin de las condiciones al final de un mdulo. Por
ejemplo, se puede describir un procedimiento que ordena una lista (un array) de la forma
siguiente:
procedure o rdenar (A, n)
(Ordena una li sta en orden ascende nte
precondi cin : A e s u n array de N enter os, 1 <= n <= Max.
postcondicin: A(l) <= A[2 ) < ... <= A[ n ) , n es ina l terable }
Por ltimo, se puede utilizar pseudocdigo 3 para especificar los detalles del algorit-
mo. Es importante que se emplee bastante tiempo en la fase de diseo de sus programas.
El resultado final de diseo descendente es una solucin que sea fcil de traducir en
estructuras de control y estructuras de datos de un lenguaje de programacin especfico,
en nuestro caso, Turbo Borland Pascal.
El gasto de tiempo' en la. 'fa.S ahorro de tiempo cuando se escriba y
depura su programa.
'. ""r, 'i' .
, ' -, . . ,
. .. '
'i '
, ,
1.5.3. Implementacin (codificacin)
La etapa de implementacin (codificacin) traduce los algoritmos del diseo en un progra-
ma escrito en un lenguaje de programacin. Los algoritmos y las estructuras de datos reali-
zadas en pseudocdigo han de traducirse a un lenguaje que entienda la computadora.
2 Para ampliar sobre este tema de diagramas de estructuras, puede consultar estas obras nuestras: Fun-
damentos de programacin, 2." edicin, McGraw-Hill, 1992; Problemas de metodologa de la programa-
cin, McGraw-Hill, 1992, o bien la obra Pascal y Turbo Pascal. Un enfoque prctico, de Joyanes, Zahonero
y Hermoso, en McGraw-Hill, 1995.
J Para consultar el tema del pseudocdigo, vanse las obras: Fundamentos de programacin. A 19orit-
mas y estructuras de datos, 2." edicin, McGraw-Hill , 1996, de Luis Joyanes, y Fundamentos de programa-
cin. Libro de problemas, McGraw-Hill, 1996, de Luis Joyanes, Luis Rodrguez y Matilde Fernndez.

Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 13
La codificacin ha de realizarse en un lenguaje de programacin. Los lenguajes clsicos
ms populares son PASCAL, FORTRAN, COBOL Y C; los lenguajes orientados a obje-
tos ms usuales son C++, Java, Visual BASIC, Smaltalk, etc.
La codificacin cuando un problema se divide en subproblemas, los algoritmos que
resuelven cada subproblema (tarea o mdulo) deben ser codificados, depurados y proba-
dos independientemente.
Es relativamente fcil encontrar un error en un procedimiento pequeo. Es casi imposible
encontrar todos los errores de un programa grande, que se codific y comprob como una
sola unidad en lugar de como una coleccin de mdulos (procedimientos) bien definidos.
Las reglas del sangrado (indentacin) y buenos comentarios facilitan la escritura del
cdigo. El pseudocdigo es una herramienta excelente que facilita notablemente la codi-
ficacin.
1.5.4. Pruebas e integracin
Cuando los diferentes componentes de un programa se han implementado y comproba-
do individualmente, el sistema completo se ensambla y se integra.
La etapa de pruebas sirve para mostrar que un programa es correcto. Las pruebas nunca
son fciles. Edgar Dijkstra ha escrito que mientras que las pruebas realmente muestran
la presencia de errores, nunca puede mostrar su ausencia. Una prueba con xito en la
ejecucin significa slo que no se han descubierto errores en esas circunstancias espec-
ficas, pero no se dice nada de otras circunstancias. En teora el nico modo que una
prueba puede mostrar que un programa es correcto, es verificar si todos los casos posi-
bles se han intentado y comprobado (es lo que se conoce como prueba exhaustiva); es
una situacin tcnicamente imposible incluso para los programas ms sencillos. Supon-
gamos, por ejemplo, que se ha escrito un programa que calcule la nota media de un
examen. Una prueba exhaustiva requerir todas las combinaciones posibles de marcas y
tamaos de clases; puede llevar muchos aos completar la prueba.
La fase de pruebas es una parte esencial de un proyecto de programacin. Durante la
fase de pruebas se necesita eliminar tantos errores lgicos como pueda. En primer lugar,
se debe probar el programa con datos de entrada vlidos que conducen a una solucin
conocida. Si ciertos datos deben estar dentro de un rango, se deben incluir los valores
en los extremos finales del rango. Por ejemplo, si el valor de entrada de n cae en el
rango de 1 a 10, se ha de asegurar incluir casos de prueba en los que n est entre 1 y 10.
Tambin se deben incluir datos no vlidos para comprobar la capacidad de deteccin de
errores del programa. Se han de probar tambin algunos datos aleatorios y por ltimo
intentar algunos datos reales .
1.5.5. Verificacin
La etapa de pruebas ha de comenzar tan pronto como sea posible en la fase de diseo y
continuar a lo largo de la implementacin del sistema. Incluso aunque las pruebas son
herramientas extremadamente vlidas para proporcionar la evidencia de que un programa
es correcto y cumple sus especificaciones, es dificil conocer si las pruebas realizadas

,
l
r
,

,
I
14 Estructura de datos
son suficientes. Por ejemplo, cmo se puede conocer que son suficientes los diferentes
conjuntos de datos de prueba o que se han ejecutado todos los caminos posibles a travs
del programa?
Por esas razones se ha desarrollado un segundo mtodo para demostrar la correccin
o exactitud de un programa. Este mtodo, denominado verificacin formal, implica la
construccin de pruebas matemticas que ayudan a determinar si los programas hacen
lo que se supone han de hacer. La verificacin fOlmal implica la aplicacin de reglas
formales para mostrar que un programa cumple su especificacin: la verificacin. La
verificacin formal funciona bi<;!n en programas pequeos, pero es compleja cuando se
utiliza en programas grandes. La teora de la verificacin requiere conocimientos
matemticos avanzados y por otra parte se sale fuera de los objetivos de este libro; por
esta razn slo hemos constatado la importancia de esta etapa.
La prueba de que un algoritmo es correcto es como probar un teorema matemtico. Por
ejemplo, probar que un mdulo es exacto (correcto) comienza con las precondiciones
(axiomas e hiptesis en matemticas) y muestra que las etapas del algoritmo conducen a
las postcondiciones. La verificacin trata de probar con medios matemticos que los
algoritmos son correctos.
Si se descubre un error durante el proceso de verificacin, se debe corregir su algo-
ritmo y posiblemente se han de modificar las especificaciones del problema. Un mtodo
es utilizar invariantes (una condicin que siempre es verdadera en un punto especfico
de un algoritmo), lo que probablemente har que su algoritmo contenga pocos errores
antes de que comience la codificacin. Como resultado se gastar menos tiempo en la
depuracin de su programa.
1.5.6. Mantenimiento
Cuando el producto software (el programa) se ha terminado, se distribuye entre los posi-
bles usuarios, se instala en las computadoras y se utiliza (produccin). Sin embargo, y
aunque a priori el programa funcione correctamente, el software debe ser mantenido
y actualizado. De hecho, el coste tpico del mantenimiento excede, con creces, el coste
de produccin del sistema original.
Un sistema de software producir errores que sern detectados, casi con seguridad,

por los usuarios del sistema y que no se descubrieron durante la fase de prueba. La correc-
cin de estos errores es parte del mantenimiento del software. Otro aspecto de la fase de
mantenimiento es la mejora del software aadiendo ms caractersticas o modificando
partes existentes que se adapten mejor a los usuarios.
Otras causas que obligarn a revisar el sistema de software en la etapa de mantenimien-
to son las siguientes: 1) Cuando un nuevo hardware se introduce, el sistema puede ser
modificado para ejecutarlo en un nuevo entorno; 2) Si cambian las necesidades del usuario,
suele ser menos caro y ms rpido, modificar el sistema existente que producir un siste-
ma totalmente nuevo. La mayor parte del tiempo de los programadores de un sistema se
gasta en el mantenimiento de los sistemas existentes y no en el diseo de sistemas total-
mente nuevos. Por esta causa, entre otras, se ha de tratar siempre de disear programas
de modo que sean fciles de comprender y entender (legibles) y fciles de cambiar,

,
;
I
i
,
!
,

Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 15


1.5.7. La obsolescencia: programas obsoletos
La ltima etapa en el ciclo de vida del software es la evolucin del mismo, pasando por
su vida til hasta su obsolescencia o fase en la que el software se queda anticuado y es
preciso actualizarlo o escribir un nuevo programa sustitutorio del antiguo.
La decisin de dar de baja un software por obsoleto no es una decisin fcil. Un sistema
grande representa una inversin enorme de capital que parece, a primera vista, ms barato
modificar el sistema existente, en vez de construir un sistema totalmente nuevo. Este
criterio suele ser, normalmente, correcto y por esta causa los sistemas grandes se disean
para ser modificados. Un sistema puede ser productivamente revisado muchas veces.
Sin embargo, incluso los programas grandes se quedan obsoletos por caducidad de tiempo
al pasar una fecha lmite determinada. A menos que un programa grande est bien escri-
to y adecuado a la tarea a realizar, como en el caso de programas pequeos, suele ser
ms eficiente escribir un nuevo programa que corregir el programa antiguo.
1.5.8. Iteracin y evolucin del s
Las etapas de vida del software suelen formar parte de un ciclo o bucle, como su nombre
sugiere, y no son simplemente una lista lineal. Es probable, por ejemplo, que durante la
fase de mantenimiento tenga que volver a las especificaciones del problema para verifi-
carlas o modificarlas.
Obsrvese en la Figura 1.4 que las diferentes etapas rodean al ncleo documenta-
cin. La documentacin no es una etapa independiente como se puede esperar sino que
est integrada en todas las etapas del ciclo de vida del software.
Mantenimiento Especificaciones
Evolucin Diseo
Produccin Verificacin
Pruebas Codificacin
Figura 1.4. Etapas del ciclo de vida del software cuyo ncleo aglutinador
es la documentacin.
,

,. ...

2i
16 Estructura de datos
1.6. MTODOS FORMALES DE VERIFICACiN
DE PROGRAMAS
Aunque la verificacin formal de programas se sale fuera del mbito de este libro, por su
importancia vamos a considerar dos conceptos clave, asertos (afirmaciones) y precondi-
ciones/postcondiciones invariantes que ayuden a documentar, corregir y clarificar el di-
seo de mdulos y de programas.
1.6.1. Aserciones (asertos) 4
Una parte importante de una verificacin formal es la documentacin de un programa a
travs de asertos o aserciones, sentencias lgicas acerca del programa que se declaran
verdaderas. Un aserto se escribe como un comentario y describe lo que se supone sea
verdadero sobre las variables del programa en ese punto.
Una asercin (aserto) es una frase sobre una condicin especfica en un cierto
punto de un algoritmo o programa.
EJEMPLO 1.1
El siguiente fragmento de programa contiene una secuencia de sentencias de asigna-
cin, seguidas por un aserto:
A
-
-
x
-

-
y -
-
10 ;
A' ,
x + A;
( as e r t o : A e s lO )
{as er t o : X es lO }
{aser t o : Y e s 2 0}
La verdad de la primera afirmacin, {A e s lO} , sigue a la ejecucin de la pri-
mera sentencia con el conocimiento de que lOes una constante. La verdad de la segun-
da afirmacin, {X e s lO }, sigue de la ejecucin de x : = A con el conocimiento de
que A e s 10. La verdad de la tercera afirmacin, {Y e s 2 O } , sigue de la ej ecucin
y : = X + A con el conocimiento de que X es 1 0 Y A es 10. En este segmento
del programa se utilizan afirmaciones como comentarios para documentar el cambio en
una variable de programa despus que se ejecuta cada sentencia de afirmacin.
La tarea de utilizar verificacin formal es probar que un segmento de programa cumple
su especificacin. La afirmacin final se llama postcondicin (en este caso, { Y e s 2 O } )
y sigue a la presuncin inicial oprecondicin (en este caso, {l O es una con s tante} )
despus que se ejecuta el segmento de programa.
4 Este trmino se suele traducir tambin por afirmaciones o declaraciones. El trmino aserto est ms
extendido en la jerga informtica, y al igual que aserto, estn los dos trminos admitidos por el DRAE.
.

!
,
I
I
i
I
,
,
I
I
I
I
!
,
,

I
,
I
,
,
,

,
Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 17
1.6.2. Precondiciones y postcondiciones
Las precondiciones y postcondiciones ya citadas anteriormente son afirmaciones
sencillas sobre condiciones al principio y al final de los mdulos. Una precondicin de
un procedimiento es una afirmacin lgica sobre sus parmetros de entrada; se supone
que es verdadera cuando se llama al procedimiento. Una pos/condicin de un procedi-
miento puede ser una afirmacin lgica que describe el cambio en el estado del progra-
ma producido por la ejecucin del procedimiento; la postcondicin describe el efecto de
llamar al procedimiento. En otras palabras, la postcondicin indica que ser verdadera
despus que se ejecute el procedimiento.
EJEMPLO 1.2
{Precondiciones y postcondiciones del procedimiento LeerEnteros}
procedure LeerEnteros (Min, Max:lnteger; var N: Integer);
{
}
Lectura de un entero entre Min y Max en N
Pre : Min y Max son valores asignados
Post: devuelve en N el primer valor del dato entre Min y Max
si Min <= Max es verdadero; en caso contrario
N no est definido.
La precondicin indica que los parmetros de entrada Min y Max se definen antes
de que comience la ejecucin del procedimiento. La postcondicin indica que la ejecu-
cin del procedimiento asigna el primer dato entre Min y Max al parmetro de salida
siempre que Min < = Max sea verdadero.
Las precondiciones y postcondiciones son ms que un mtodo para resumir acciones de
un procedimiento. La declaracin de estas condiciones debe ser la primera etapa en el
diseo y escritura de un procedimiento. Es conveniente en la escritura de algoritmos de
procedimientos, se escriba la cabecera del procedimiento que muestra los parmetros
afectados por el procedimiento as como unos comentarios de cabecera que contienen
las precondiciones y postcondiciones.
Precondicin: Predicado lgico que debe cumplirse al comenzar la ejecucin
de una operacin.
Postcondicin: Predicado lgico .quedebecumplirs.e alacabarJa ejecucin de
una operacin; siempre que se haya cumplido previamente laprecondicin co- ." .
rrespondiente ..
1.6.3. Reglas para prueba de programas
Un medio til para probar que un programa P hace lo que realmente ha de hacer es
proporcionar aserciones (asertos) que expresen las condiciones antes y despus de que
P sea ejecutada. En realidad las aserciones son como sentencias o declaraciones
que pueden ser o bien verdaderas o bien falsas .
,

I

,
18 Estructura de datos
La primera asercin, la precondicin, describe las condiciones que han de ser verda-
deras antes de ejecutar P.
La segunda asercin, la postcondicin, describe las condiciones que han de ser ver-
daderas despus de que P se ha ejecutado (suponiendo que la precondicin fue verdade-
ra antes). El modelo general es:
(precondicin)
(postcondicin)
EJE LO 1.3
{ = condiciones l gicas que son
verdaderas antes de que P se ejecut e }
{= condiciones lg ica s que son ve rdaderas
despus de que P se e j ecute}
ElprocedimientoOrdenarSeleccion (A, m, n) ordena a los elementosdelarray.
A [m . . n] en orden descendente. El modelo correspondiente puede escribirse as:
{m n} {precondicin: A ha de t e n e r al menos 1 eleme n to}
Ordena rSe l ecci on (A , m, nl {programa de ordenacin a e j ecutar}
( A[m] > A[m+l ] ... A[n] {postcondic i n : elementos d e A en orden
descendent e }
PROBLEMA 1.1
Encontrar la posicin del elemento mayor de una lista con indicacin de precondicio-
nes y postcondiciones.
function EncontrarMax (var A:Lista; m, n: Integerl : Integer;
{precondicin : m < n}
{pos tcondicin : devuelve posic in elemento mayor en A[m .. n]}
var i, j : Int eger ;
begin

l : = m;
j : = n ; {aser c i n}
repeat
i :=i+l0 ;
i f A [ i] > A [ j] then j : = i ;
until i = n;
En contrarMax

: = J ; {devuelve j como elemento mayor}
end;

PROBLEMA 1.2
Ordenar por el mtodo seleccin con precondiciones y postcondiciones:
procedure Orde nar Se l eccion ( var A:Lis t a; m, n : I n t ege rl;
{preco ndicin : m n }
(postcondi c i n : A[m,n] est o r d enado ta l que
A[m] A[m+l] ... A[ n])
Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 19
var PosicionMax, Aux : Integer;
begin
if m < n then
begin
posicionMax := EncontrarMax(A,m,n);
{Intercambiar A[m] A[PosicionMax]}
Aux := A[m];
A[m] := A[PosicionMax];
A[PosicionMax] := Aux;
OrdenarSeleccion (A,m+l,n);
{produce: A[m+l] A[m+2) ... A[n)}
end {if}
{Asercin final: A[m) A[m+l) ... A[n)}
end {OrdenarSeleccion}
1.6.4. Invariantes de bucles
Una invariante de bucle es una condicin que es verdadera antes y despus de la ejecu-
cin de un bucle. Las invariantes de bucles se utilizan para demostrar la correccin (exac-
titud) de algoritmos iterativos. Utilizando invariantes, se pueden detectar errores antes
de comenzar la codificacin y por esa razn reducir tiempo de depuracin y prueba.
1.4
Un bucle que calcula la suma de los n primeros elementos del array (lista) A:
{calcular la suma de A[l), A[2], ... A[n)}
{asercin n >= 14}
Suma := O;
J
' . - l'
. - ,
while j <= n do
begin
Suma := Suma + A[j);
j := succ(j)
end
Antes de que este bucle comience la ejecucin Suma es O y j es l. Despus que el
bucle se ha ejecutado una vez, Suma es A [1] Y j es 2.
Invariante del bucle Suma es la suma de los elementos A [1] a A [ j + 1] .
EJEMPLO 1.5
Invariante de un bucle que sume n enteros (n entero positivo); i, Suma, n son de tipo
entero.
20 Estructura de datos
{aserc i n n>= 1 } {pr e cond icin }
suma : = O;
1
, . - l'
- ,
whi1e i <= n do
begin
Suma
,
:= Suma + l;
,
1
.-
. - i + 1
end
{asercin : Suma es 1+2 +3 + ... +n-1 +n} {po stcondi c i n}
Una invariante del bucle puede ser:
{invariante: i <= n y Suma es 1+2+ . . i- 1 }
lo que significa: i debe ser menor que o igual que n y despus de cada pasada o vuelta,
Suma es igual a la suma de todos los enteros positivos menores que i.
En la verificacin de programas la invariante del bucle se utiliza para probar que el
bucle cumple su especificacin. Para nuestro propsito, se puede utilizar el invariante
del bucle para documentar el comportamiento del mismo y se situar justo antes del
cuerpo del bucle.
{Suma de enteros 1 a n}
{preco ndicin : n >= 1}
Suma := O;
1
, . - 1
- ,
while i <= n do
{invariante : i <= n +1 y Suma es 1+2+ ... i - 1}
begin
Suma
,
1
.-
. -
end;
: Suma
i+1
,
+ l;
{po stcondicin : Suma es 1+2+3+ .. n-1+n}
Invariantes de bucle como herramientas de diseo
Otra aplicacin de los invariantes de bucle es la especificacin del bucle:
condicin de repeticin y cuerpo del bucle.
EJEMPLO 1.6
Si la variante de un bucle es:
. .. . ,
InIClaClOn,
{invariante: i <= n y Suma es la suma de todos los nmeros ledos del
t eclado}
Se puede deducir que:
Suma := 0.0:
l
. - O'
- ,

1 < n
Read (Item);
Suma : = Suma + I tem;
i :=i+l
{ ini ciaci n}
{condi cin / prueba del bucle}
{cuerpo del bucle}
,
Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 21
Con toda esta informacin es una tarea fcil escribir el bucle de suma:
Suma : = 0 . 0 ;
i : = O;
while i < n do
Read ( Item);
{y , toma l os va lores 0,1, 2 , 3 , .. n - 1}
Suma : = Suma + Item;
i : = i + 1
end;
EJEMPLO 1.7
En los bucles for es posible declarar tambin invariantes, pero teniendo presente
la particularidad de esta sentencia: la variable de control del bucle es indefinida des-
pus que se sale del bucle, por lo que para definir su invariante se ha de considerar que
dicha variable de control se incrementa antes de salir del bucle y mantiene su valor
.fi nal.
{precond icin n > = l }
Suma : = o;
for i : = 1 to n do
{i nva ri ante : i < = n +l y Suma es 1+2+ ... i -l }
Suma : = Suma + i ;
{postcondi cin : Suma es 1+ 2 +3 + .. n - l +n }
PROBLEMA 1.3
Escribir un bucle controlado por centinela que calcule el producto de un conjunto de
datos.
{Ca l cula r el producto de una serie de dat os }
{precondicin : cen tine l a es con stante }
Pr oducto := 1 ;
Wr ite ln ( ' Par a t ermina r, i n t roduzca ', Cent i nel a : 1);
Writeln ( ' I ntr odu zca n mero :' ) ;
ReadLn (Numero);
while Nume ro <> Centinel a do
{invariant e : Produc to es el produ c to d e todos los valore s l edos en
Nmero y n ing u no era el Ce ntine l a }
begin
Pr oduc t o := Pr oducto * Numer o ;
Wri t eLn ( ' I n troduzca nme ro si gu i ente :' ) ;
Rea dLn (Numero)
end;
{postcondicin : Pr oducto es e l produc to de todos los n meros l edos e n
Nume ro ant e s de l cen t i ne la } ''''_'0 .0' . "
22 Estructura de datos
1.6.5. Etapas a establecer la exactitud (correccin)
de un programa
Se pueden utilizar invariantes para establecer la correccin (exactitud) de un algoritmo
iterativo. Supongamos el algoritmo ya estudiado anteriormente.
{calcular la suma d e A[lJ, A[2J, ... A[n] }
Suma
. -
O ; . -

1 ;
J
-
-
while

N do
J < =
begin
Suma - Suma + A [ j ] ;
-

suc c (j)
J
-
-
end
{ invar i ante: Suma es l a suma de l o s element os A[l] a A[j- l ] }
L
Los siguientes cuatro puntos han de ser verdaderos 5:
l. El invariante debe ser inicialmente verdadero, antes de que comience la ejecu-
cin por primera vez del bucle. En el ejemplo anterior, Suma es O y j es 1
inicialmente. En este caso, el invariante significa que Suma contiene la suma de
los elementos A [1] a A [ O ] , que es verdad ya que no hay elementos en este
rango.
2. Una ejecucin del bucle debe mantener el invariante. Esto es si el invariante
es verdadero antes de cualquier iteracin del bucle, entonces se debe demostrar
que es verdadero despus de la iteracin. En el ejemplo, el bucle aade A [ j] a
Suma ya continuacin incrementa j en l. Por consiguiente, despus de una eje-
cucin del bucle, el elemento aadido ms recientemente a Suma es A [ j -1] ;
esto es, el invariante que es verdadero despus de la iteracin.
3. El invariante debe capturar la exactitud del algoritmo. Esto es, debe demos-
trar que si el invariante es verdadero cuando termina el bucle, el algoritmo es
correcto. Cuando el bucle del ejemplo termina, j contiene N + 1 Y el invariante
es verdadero: Suma contiene la suma de los elementos A [1] a A [J -1] , que es
la suma que se trata de calcular.
4. El bucle debe terminar. Esto es, se debe demostrar que el bucle termina des-
pus de un nmero finito de iteraciones. En el ejemplo, j comienza en 1 y a
continuacin se incrementa en 1 en cada ejecucin del bucle. Por consiguiente,
j eventualmente exceder a N con independencia del valor de N. Este hecho y la
caracterstica fundamental de while garantizan que el bucle terminar.
La identificacin de invariantes de bucles ayuda a escribir. bucles correct()s. Se
representa el invariante como un comentario que precede a cada bucle. En el ejem-
plo anterior:
{Invariante: 1 <= j <= N+l y Suma = A[l] + ... +A [j-l]}
while j <= N do
5 Carrasco, Helman y Verof, op. cit., pg. 15.
... _-

Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 23
-
1.7. PRINCIPIOS DE DISENO DE SIST S DE SOFTWARE
El diseo de sistemas de software de calidad requiere el cumplimiento de una serie de
caractersticas y objetivos. En un sentido general los objetivos a conseguir que se consi-
deran tiles en el diseo de sistemas incluyen al menos los siguientes principios:
l. Modularidad mediante diseo descendente.
2. Abstraccin y ocultamiento de la informacin.
3. Modificabilidad.
4. Comprensibilidad y fiabilidad.
5. Interfaces de usuario.
6. Programacin segura contra fallos.
7. Facilidad de uso.
8. Eficiencia.
9. Estilo de programacin.
10. Depuracin.
1 1 . Documentacin.
1.7.1. Modularidad mediante diseo descendente
Un principio importante que ayuda a tratar la complejidad de un sistema es la modula-
ridad. La descomposicin del problema se realiza a travs de un diseo descendente que
a travs de niveles sucesivos de refinamiento se obtendrn diferentes mdulos. Normal-
mente los mdulos de alto nivel especifican qu acciones han de realizarse mientras que
los mdulos de bajo nivel definen cmo se realizan las acciones.
La programacin modular tiene muchas ventajas. A medida que el tamao de un
programa crece, muchas tareas de programacin se hacen ms difciles. La diferencia
principal entre un programa modular pequeo y un programa modular grande es, sim-
plemente, el nmero de mdulos que cada uno contiene, ya que el trabajo con programas
modulares es similar y slo se ha de tener presente el modo en que unos mdulos inter-
,
actuan con otros.
La modularidad tiene un impacto positivo en los siguientes aspectos de la progra-
. ,
maClOn:
Construccin del programa. La descomposicin de un programa en mdulos
permite que los diversos programadores trabajen de modo independiente en cada
uno de sus mdulos. El trabajo de mdulos independientes convierte la tarea de es-
cribir un programa grande en la tarea de escribir muchos programas pequeos.
Depuracin del programa. La depuracin de programas grandes puede ser una
tarea enorme, de modo que se facilitar esa tarea, al centrarse en la depuracin de
pequeos programas ms fciles de verificar.
Legibilidad. Los programas grandes son muy difciles de leer, mientras que los
programas modulares son ms fciles de leer.

i
24 Estructura de datos
Eliminacin de cdigo redundante. Otra ventaja del diseo modular es que se
pueden identificar operaciones que suceden en muchas partes diferentes del pro-
grama y se implementan como subprogramas. Esto significa que el cdigo de una
operacin aparecer slo una vez, produciendo como resultado un aumento en la
legibilidad y modificabilidad.
1.7.2. Abstraccin y encapsulamiento
La complejidad de un sistema puede ser gestionado utilizando abstraccin. La abstrac-
cin es un principio comn que se aplica en muchas situaciones. La idea principal es
definir una parte de un sistema de modo que puede ser comprendido por s mismo (esto
es, como una unidad) sin conocimiento de sus detalles especficos y sin conocimiento de
cmo se utiliza esta unidad a un nivel ms alto.
Existen dos tipos de abstracciones: abstraccin procedimental y abstraccin de da-
tos. La mayora de los lenguajes de programacin soportan este tipo de abstraccin. Es '
aquella en que se separa el propsito de un subprograma de su implementacin. Una vez
que se ha escrito un subprograma, se puede utilizar sin necesidad de conocer las peculia-
ridades de sus algoritmos. Suponiendo que el subprograma est documentado adecuada-
mente, se podr utilizar con slo conocer la cabecera del mismo y sus comentarios des-
criptivos; no necesitar conocer su cdigo.
La modularidad tratada anteriormente y la abstraccin procedimental se com-
plementan entre s. La modularidad implica la rotura de una solucin en mdulos; la
abstraccin procedimental implica la especificacin de cada mdulo claramente antes
de que se implemente en Pascal. De hecho, lo importante es poder utilizar los subprogramas
predefinidos, tales como Wri teln, Sqrt, etc., o bien los definidos por el usuario sin
necesidad de conocer sus algoritmos.
El otro tipo de abstraccin es la abstraccin de datos, soportada hoy da por diversos
lenguajes Turbo Borland Pascal, C++, Ada-83, Ada-95. Modula-2, etc. El propsito de
la abstraccin de datos es aislar cada estructura de datos y sus acciones asociadas. Es de-
cir, se centra la abstraccin de datos en las operaciones que se realizan sobre los datos en
lugar de cmo se implementan las operaciones. Supongamos, por ejemplo, que se tiene
una estructura de datos Clientes, que se utiliza para contener informacin sobre los
clientes de una empresa, y que las operaciones o acciones a realizar sobre esta estructura
de datos incluyen Insertar, Buscar y Borrar. El mdulo, objeto o tipo abstracto de datos,
Ti poC 1 i en t e es una coleccin de datos y un conjunto de operaciones sobre esos datos.
Tales operaciones pueden aadir nuevos datos, buscar o eliminar datos. Estas operaciones
constituyen su interfaz, mediante la cual se comunica con otros mdulos u objetos.
Un tipo abstracto de datos (TAD) se implementar mediante unidades en Turbo
BorIand Pascal. Por su importancia se dedicar un captulo completo a tratar ms deteni-
damente el concepto de un TAD, su diseo e implementacin prctica (captulo 3).
Otro principio de diseo es la ocultacin de la informacin. El propsito de la ocul-
tacin de la informacin es hacer inaccesible ciertos detalles que no afecten a los otros
mdulos del sistema. Por consiguiente, el objeto y sus acciones constituyen un sistema
cerrado, cuyos detalles se ocultan a los otros mdulos.
Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 25
La abstraccin identifica los aspectos esenciales de mdulos y estructura de datos,
que se pueden tratar como cajas negras. La abstraccin indica especificaciones funcio-
nales de cada caja negra; es responsable de su vista externa o pblica. Sin embargo, la
abstraccin ayuda tambin a identificar detalles de lo que se debe ocultar de la vista
pblica detalles que no estn en las especificaciones pero deben ser privados . El
principio de ocultacin de la informacin no slo oculta detalles dentro de la caja negra
. sino que tambin asegura que ninguna otra caja negra pueda acceder a estos detalles
ocultos. Por consiguiente, se deben ocultar ciertos detalles dentro de sus mdulos y TAD,
Y hacerlos inaccesibles a los restantes mdulos y TAD.

La abstraccin de datos y su expresin ms clara el tipo abstracto de datos, se imple-
menta en Turbo Borland Pascal con unidades.
1.7.3. Modificabilidad
La modificabilidad (facilidad de modificacin) se refiere a los cambios controlados de
un sistema dado. Un sistema se dice que es modificable si los cambios en los requisitos
pueden adecuarse bien a los cambios en el cdigo. Es decir, un pequeo cambio en los
requisitos en un programa modular normalmente requiere un cambio pequeo slo en
algunos de sus mdulos; es decir, cuando los mdulos son independientes (esto es, d-
bilmente acoplados) y cada mdulo realiza una tarea bien definida (esto es, altamente
cohesivos). La modularidad asla las modificaciones.
Las tcnicas ms frecuentes para hacer que un programa sea fcil de modificar son:
uso de subprogramas y uso de constantes definidas por el usuario.
El uso de procedimientos tiene la ventaja evidente, no slo de eliminar cdigo
redundante sino tambin hace el programa resultante ms modificable. Normalmente
ser un signo de mal diseo de un programa que pequeas modificaciones a un pro-
grama requieran su reescritura completa. Un programa bien estructurado en mdulos
ser modificable ms fcilmente; es decir, si cada mdulo resuelve slo una pequea
parte del problema global, un cambio pequeo en las especificaciones del problema nor-
malmente slo afectar a unos pocos mdulos y en consecuencia eso facilitar su modi-
ficacin.
Las constantes definidas por el usuario o con nombre son otro medio para mejorar la
modificabilidad de un programa.
EJEMPLO 1.8
Los lmites del rango de un array suelen ser definidos mejor mediante constantes con
nombre que mediante constantes numricas. As, la declaracin tpica de un array y su
proceso posterior mediante un bucle es:
type Ti poPunt os = array [1 .. 100 } of integer;
for i := 1 to 1 00 do
proceso d e l os e lementos

,

,
i
,
,
26 Estructura de datos
El diseo ms eficiente podra ser:
const NumeroDel t ems = 100 ;
type TipoPunto = array [l .. NumeroDeltemsl of i nteger ;
for i := 1 to Nume roDe l tems do
proces o de los element os
ya que cuando se desee cambiar el nmero de elementos del array slo sera necesario
cambiar el valor de la constante NumeroDeItems, mientras que en el caso anterior
supondr cambiar la declaracin del tipo y el ndice de bucle, mientras que en el segun-
do caso slo el valor de la constante.
1.7.4. Comprensibilidad y fiabilidad
Un sistema se dice que es comprensible si refleja directamente una visin natural del
mundo 6. Una caracterstica de un sistema eficaz es la simplicidad. En general, un siste-
ma sencillo puede ser comprendido ms fcilmente que uno complejo.
Un objetivo importante en la produccin de sistemas es el de la fiabilidad. El objeti-
vo de crear programas fiables ha de ser crtico en la mayora de las situaciones.
1.7.5. Interfaces de usuario
Otro criterio importante a tener presente es el diseo de la interfaz del usuario. Algunas
directrices a tener en cuenta pueden ser:
En un entorno interactivo, se ha de tener en cuenta las preguntas posibles al usua-
rio y sobre todo aquellas que solicitan entradas de usuario.
Es conveniente que se realicen eco de las entradas de un programa. Siempre que
un programa lee datos, bien de usuario a travs de un terminal o de un archivo, el
programa debe incluir los valores ledos en su salida.
Etiquetar (rotular) la salida con cabeceras y mensajes adecuados.
1.7.6. Programacin segura contra fallos
Un programa es seguro contra fallos cuando se ejecuta razonablemente por cualquiera
que 10 utilice. Para conseguir este objetivo se han de comprobar los errores en datos de
entrada y en la lgica del programa.
Supongamos un programa que espera leer datos enteros positivos pero lee ,25. Un
mensaje tpico a visualizar ante este error suele ser:
Erro r de rango
6 Tremblay, Donrek y Bunt: Infroducfion fo Computer Science. An Algorithmic approach, McGraw-
Hill, 1989, pg. 440.
----- - - -- - ----------------------------------------------_.


Ingenierfa de software: introduccin a la metodologa de construccin de grandes programas 27
Sin embargo, es ms til un mensaje tal como ste:
-25 no es un nmero vlido de aos
Por favor vuelva a introducir el nmero
Otras reglas prcticas a considerar son:
No utilizar tipos subrango para detectar datos de entrada no vlidos. Por ejemplo,
si se desea comprobar que detelminados tipos nunca sean negativos, se pueden
cambiar las definiciones de tipo global a:
type TipoNoNeg - O .. maxint; {tipo nuevo}
TipoMillar = Bajo .. Alto; {permanece el mismo}
TipoTabla = array[TipoMillar] of TipoNoNeg;
{un array de este tipo contiene s610 enteros no negativos}
Comprobar datos de entrada no vlidos
ReadLn (Grupo, Nmero)

if Nmero >= O
then agregar Nmero a total
elee manejar el error.
Cada subprograma debe comprobar los valores de sus parmetros. As, en el caso
de la funcin S urna 1 n te rv a 1 o que suma todos los enteros comprendidos
entre m y n .
function Sumalntervalo (m,n:lnteger) : Integer;
{
}
precondici6n : m y n son enteros tales que m < = n
postcondici6n: Devuelve Sumalntervalo = m+(m+l)+ ... +n
m y n son inalterables
var Suma, Indice : Integer;
begin
Suma := O;
for Indice := m to n do
Suma := Suma + Indice;
Sumalntervalo := Suma
end;
1.7.7. Facilidad de uso
La utilidad de un sistema se refiere a su facilidad de uso. Esta propiedad ha de tenerse
presente en todas las etapas del ciclo de vida, pero es vital en la fase de diseo e implemen-
. , . ,
taclOn o construcclOn.
1.7.8. Eficiencia
El objetivo de la eficiencia es hacer un uso ptimo de los recursos del programa. Tradicio-
nalmente, la eficiencia ha implicado recursos de tiempo y espacio. Un sistema eficiente
11-------------- -
- _ .. _ ...
I
.
l
28 Estructura de datos
es aquel cuya velocidad es mayor con el menor espacio de memoria ocupada. En tiempos
pasados los recursos de memoria principal y de CPU eran factores clave a considerar para
aumentar la velocidad de ejecucin. En el ao 1997 las CPU (UCP, Unidad Central de
Proceso) tpicas de los PC eran Pentium de 166 y 200 MHz. En el ao 1988 son usuales
los Pentium de 233 Mhz y Pentium 11 de 266 Mhz y son ya muy frecuentes; las memo-
rias centrales usuales son 16 Mbytes o 32 Mbytes, aunque bsicamente los tamaos de
memorias tradicionales para trabajos profesionales ya son de un mnimo de 64 Mbytes;
el factor eficiencia ya no se mide con los mismos parmetros de memoria y tiempo. Hoy
da debe existir un compromiso entre legibilidad, modificabilidad y eficiencia, aunque,
con excepciones, prevalecer la legibilidad y modificabilidad.
1.7.9. Estilo de programacin, documentacin y depuracin
Estas caractersticas hoy da son claves en el diseo y construccin de programas, por esta
causa dedicaremos por su especial importancia tres secciones independientes para tratar
estos criterios de diseo.
,
1.8. ESTILO DE PROGRAMACION
Una de las caractersticas ms importantes en la construccin de programas, sobre todo
los de gran tamao, es el estilo de programacin. La buena calidad en la produccin de
programas tiene relacin directa con la escritura de los mismos, su legibilidad y com-
prensibilidad. Un buen estilo de programacin suele venir con la prctica, pero el re-
querimiento de unas reglas de escritura del programa, al igual que sucede con la sinta-
xis y reglas de escritura de un lenguaje natural humano, debe buscar esencialmente que
no slo sean legibles y modificables por las personas que lo han construido sino tambin
-y esencialmente puedan ser ledos y modificados por otras personas distintas. No
existe una frmula mgica que garantice programas legibles, pero existen diferentes re-
glas que facilitarn la tarea y con las que prcticamente suelen estar de acuerdo casi
todos, desde programadores novatos a ingenieros de software experimentados.
Naturalmente las reglas de estilo para construir programas claros, legibles y fcil-
mente modificables, depender del tipo de programacin y lenguaje elegido. En nuestro
caso y dado que el tipo de programacin es estructurado y el lenguaje es Pascal/Turbo
Borland Pascal, nos centraremos en este enfoque, pero estas reglas sern fcilmente ex-
trapolables a otros lenguajes estructurados tales como C, C++, Ada, Modula-2, etc.
Reglas de estilo de programacin
l. Modularizar un programa en partes coherentes (uso amplio de subprogramas) .
2. Evitar variables globales en subprogramas.
3. Usar nombres significativos para identificadores.
4. Definir constantes con nombres al principio del programa.
5. Evitar el uso del goto y no escribir nunca cdigo spaghetti.
- ---------------------------------------------------------------------------------
,

-

Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 29

6. Escribir subrutinas cortas que hagan una sola cosa y bien.
7. U so adecuado de parmetros variable.
8. Usar declaraciones de tipos.
9. Presentacin ( comentarios adecuados).
10. Manejo de errores.
11. Legibilidad.
12. Documentacin.
1.8.1. Modularizar un programa en subprogramas
Un programa grande que resuelva un problema complejo siempre ha de dividirse en
mdulos para ser ms manejable. Aunque la divisin no garantiza un sistema bien organi-
zado ser preciso encontrar reglas que permitan conseguir esa buena organizacin.
Uno de los criterios clave en la divisin es la independencia; esto es, el acoplamiento
de mdulos; otro criterio es que cada mdulo debe ejecutar una sola tarea, una funcin
relacionada con el problema. Estos criterios fundamentalmente son acoplamiento y cohe-
sin de mdulos, aunque existen otros criterios que no se tratarn en esta seccin.
El acoplamiento se refiere al grado de interdependencia entre mdulos. El grado de
acoplamiento se puede utilizar para evaluar la calidad de un diseo de sistema. Es preciso
minimizar el acoplamiento entre mdulos, es decir, minimizar su interdependencia. El
criterio de acoplamiento es una medida para evaluar cmo un sistema ha sido modulari-
zado. Este criterio sugiere que un sistema bien modularizado es aquel en que las interfa-
ces sean claras y sencillas.
Otro criterio para juzgar un diseo es examinar cada mdulo de un sistema y deter-
minar la fortaleza de la ligadura (enlace) dentro de ese mdulo. La fortaleza interna
de un mdulo, esto es, lo fuertemente (estrictamente) relacionadas que estn entre s las
partes de un mdulo, se conoce como propiedad de cohesin. Un modelo cuyas par-
tes estn fuertemente relacionadas con cada uno de los otros se dice que es fuertemente
cohesivo. Un modelo cuyas partes no estn relacionadas con otras se dice que es cohesi-
vo dbilmente.
Los mdulos de un programa deben estar dbilmente acoplados y fuertemente co-
hesionados.
Como regla general es conveniente utilizar subprogramas ampliamente. Si un con-
junto de sentencias realiza una tarea recurrente, repetitiva, identificable, debe ser un
subprograma. Sin embargo, una tarea no necesita ser recurrente para justificar el uso de
un subprograma.
1.8.2. Evitar variables globales en subprogramas
Una de las principales ventajas de los subprogramas es que pueden implementar el con-
cepto de mdulo aislado. El aislamiento se sacrifica cuando un subprograma accede a

,
I

..
30 Estructura de datos
variables globales, dado que los efectos de sus acciones producen los efectos laterales
indeseados, normalmente.
En general, el uso de variables globales con subprogramas no es correcto. Sin em-
bargo, el uso de la variable global, en s, no tiene porqu ser perjudicial. As, si un dato
es inherentemente importante en un programa al que casi todo subprograma debe acce-
der al mismo, entonces ese dato ha de ser global por naturaleza.
1.8.3. Usar nombres significativos para identificadores
Los identificadores que representan los nombres de mdulos, subprogramas, funciones, ti-
pos, variables y otros elementos, deben ser elegidos apropiadamente para conseguir pro-
gramas legibles. El objetivo es usar interfaces significativas que ayuden al lector a recordar
el propsito de un identificador sin tener que hacer referencia continua a declaraciones o
listas externas de variables. Hay que evitar abreviaturas crpticas.
Identificadores largos se deben utilizar para la mayora de los objetos significativos
de un programa, as como los objetos utilizados en muchas posiciones, tales como, por
ejemplo, el nombre de un programa usado frecuentemente. Identificadores ms cortos se
utilizarn estrictamente para objetos locales: as, i, j, k, son tiles para ndices de arrays
en un bucle, variables contadores de bucle, etc., y son ms expresivos que 1 n die e,

Los identificadores deben utilizar letras maysculas y minsculas. Cuando un identifi-
cador consta de dos o ms palabras, cada palabra debe comenzar con una letra mayscula.
Una excepcin son los tipos de datos definidos por el usuario que suelen comenzar con
una letra minscula. As identificadores idneos son:
Sa l ar ioMes NombreMensajeUsuario Mens a jesDatosMal
Algunas reglas que se pueden seguir son:
Usar nombres para nombrar objetos de datos tales como variables, constantes y
tipos. Utilizar Salario mejor que APagar o Pagar.
Utilizar verbos para nombrar procedimientos. LeerCaracter, LeerSigCar
y CalcularSigMov son procedimientos que realizan estas acciones mejor que
SigCar o SigMov (siguiente movimiento).
Utilizar formas del verbo sen> o estar para funciones lgicas. SonIgua-
les, EsCero, EsListo y EsVacio se utilizan como variables o funciones l-

glcas.
if Son Igual es (A . B)
. r' ..... ,.
Los nornhI'esde los objeto
, ' .'
, " , ., >,;
al lector
Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 31
1.8.4. Definir constantes con nombres
Se deben evitar constantes explcitas siempre que sea posible. Por ejemplo, no utilizar 7
para el da de la semana o 3.141592 para representar el valor de la constante n. En su
lugar, es conveniente definir constantes con nombre que permiten Pascal C ... , tal como:
Const pi = 3.141592;
Const
Const
NurnDiasSernana = 7 ,
Longitud = 45;
Este sistema tiene la ventaja de la facilidad para cambiar un valor determinado bien
por necesidad o por cualquier error tipogrfico
Const Longitud = 200;
Const pi = 3.141592654;
1.8.5. Evitar el uso de goto
Uno de los factores que ms contribuyen a disear programas bien estructurados es un
flujo de control ordenado que implica los siguientes pasos:
1. El flujo general de un programa es adelante o directo.
2. La entrada a un mdulo slo se hace al principio y se sale slo al final.
3. La condicin para la terminacin de bucles ha de ser clara y uniforme.
4. Los casos alternativos de sentencias condicionales han de ser claros y uniformes.
El uso de una sentencia got o casi siempre viola al menos una de estas condiciones.
Adems es muy dificil verificar la exactitud de un programa que contenga una sentencia
goto. Por consiguiente, en general, se debe evitar el uso de got o. Hay, sin embargo,
raras situaciones en las que se necesita un flujo de control excepcional, tales casos in-
cluyen aquellos que requieren o bien que un programa termine la ejecucin cuando ocurre
un error, o bien que un subprograma devuelve el control a su mdulo llamador. La inclu-
sin en Turbo Borland Pascal de sentencias hal t y exi t hacen innecesario en cual-
quier caso el uso de goto.
1.8.6. Uso adecuado de parmetros valor/variable
Un programa interacta se comunica de un modo controlado con el resto del programa
mediante el uso de parmetros. Los parmetros valor, que son declarados por defecto cuan-
do no se especifica la palabra reservada var, pasa los valores al subprograma, pero
ningn cambio que el programa hace a estos parmetros se refleja en los parmetros
reales de retomo a la rutina llamadora. La comunicacin entre la rutina llamadora y
el subprograma es de un solo sentido; por esta causa en el caso de mdulos aislados se
deben utilizar parmetros valor siempre que sea posible.
,
,
,

,
,
,
,
,
,
32 Estructura de datos
Cundo es adecuado usar parmetros variable? La situacin ms evidente es cuan-
do un procedimiento necesita devolver valores a la rutina llamadora. Sin embargo, si el
procedimiento necesita devolver slo un nico valor, puede ser ms adecuado usar una
funcin. Si una funcin no es adecuada, entonces utilizar parmetros variables.
Es conveniente utilizar un parmetro variable para comunicar un valor de retorno del
subprograma a la rutina llamadora. Sin embargo, los parmetros variable cuyos valores
permanecen inalterables hacen el programa ms dificil de leer y ms propenso a errores
si se requieren modificaciones. La situacin es anloga a utilizar una constante en lugar de
una variable cuyo valor nunca cambia. Por consiguiente, se debe alcanzar un compromiso
entre legibilidad y modificabilidad por un lado y eficiencia por otro. A menos que exista
una diferencia significativa en eficiencia, se tomar generalmente el aspecto de la legibi-
lidad y modificabilidad.
1.8.7. Uso adecuado de funciones
Pascal le proporciona un sistema para realizar tareas distintas a las funciones primitivas
incorporadas al lenguaje. El mecanismo de llamada a un procedimiento o funcin defi-
nida por el usuario se puede activar desde cualquier punto de un programa en el que se
necesite ese subprograma.
En el caso de una funcin, sta se debe utilizar siempre que se necesite obtener un
nico valor. Este uso corresponde a la nocin matemtica de funcin. Por consiguiente, es
muy extrao que una funcin realice una tarea diferente de devolver un valor y no debe
hacerlo.
, " ' " . '
' " , '
"nct.dct. , SIDO devolver el valor requ.erido. Es decir, una
""",'kla' r:l .. ,"- -. ' j 'j' :."i';: ':, .,.;':, !: . --,--" - - , _, ::,: ~ " , :', ';,' ", ':: , : r; ::T,' , , : ~ , : , : : : ", ',.--- - " -
. . . . . - . .
Una funcin no ,.,.,'" ...
' "' funcinnUrttll
, - - . - -
Qu funciones tienen potencial para producir efectos laterales?
Funciones con variables globales. Si una funcin referencia a una variable glo-
bal, presenta el peligro de un posible efecto lateral. En general, las funciones no
deben asignar valores a variables globales.
Funciones con parmetros variables. Un parmetro variable es aquel en que su
valor cambiar dentro de la funcin. Este efecto es un efecto lateral. En general,
las funciones no deben utilizar parmetros variables. Si se necesitan parmetros
variables utilizar procedimientos.
Funciones que realizan entrada/salida (E/S). Las E/S son efectos laterales. Las
funciones no deben realizar E/ S.
1.8.8. Tratamiento de errores
Un programa diseado ante fallos debe comprobar errores en las entradas y en su lgica
e intentar comportarse bien cuando los encuentra. El tratamiento de errores con frecuen-
I
,
------------ ---------------- - --_. , . __ ._. _ . - ,.
Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 33
cia necesita acciones excepcionales que constituirn un mal estilo en la ejecucin normal
de un programa. Por ejemplo, el manejo de funciones puede implicar el uso de funciones
con efectos laterales.
Un subprograma debe comprobar ciertos tipos de errores, tal como entradas no vli-
das o parmetros valor. Qu accin debe hacer un subprograma cuando se encuentra un
error? Un sistema puede, en el caso de un procedimiento, presentar un mensaje de error
y devolver un indicador o bandera lgica a la rutina llamadora para indicarle que ha
encontrado una lnea de datos no vlida; en este caso, el procedimiento deja la responsa-
bilidad de realizar la accin apropiada a la rutina llamadora. En otras ocasiones, es ms
adecuado que el propio subprograma tome las acciones pertinentes por ejemplo,-
cuando la accin requerida no depende del punto en que fue llamado el subprograma.
Si una funcin maneja errores imprimiendo un mensaje o devolviendo un indicador,
viola las reglas contra efectos laterales dadas anteriormente.
Dependiendo del contexto, las acciones apropiadas pueden ir desde ignorar los datos
errneos hasta continuar la ejecucin para terminar el programa. En el caso de un error
fatal que invoque la terminacin, una ejecucin de hal t puede ser el mtodo ms lim-
pio para abortar. Otra situacin delicada se puede presentar cuando se encuentra un error
fatal en estructuras condicionales if - then-else o repetitivas while, repeat. La
primera accin puede ser llamar a un procedimiento de diagnstico que imprima la infor-
macin necesaria para ayudarle a determinar la causa del error; pero despus de que el
procedimiento ha presentado toda esta informacin, se ha de terminar el programa. Sin
embargo, si el procedimiento de diagnstico devuelve el control al punto en el que fue
llamado, debe salir de muchas capas de estructuras de control anidadas. En este caso la
solucin ms limpia es que la ltima sentencia del procedimiento de diagnstico sea
hal t.
1.8.9. Legibilidad
Para que un programa sea fcil de seguir su ejecucin (la traza) debe tener una buena
estructura y diseo, una buena eleccin de identificadores, buen sangrado y utilizar l-
neas en blanco en lugares adecuados y una buena documentacin.
Como ya se ha comentado anteriormente se han de elegir identificadores que describan
fielmente su propsito. Distinguir entre palabras reservadas, tales como f or o procedu-
re, identificadores estndar, tal como real o integer e identificadores definidos
por el usuario. Algunas reglas que hemos seguido en el libro son:
Las palabras reservadas se escriben en minsculas negritas (en letra courier, en el
libro ).
Los identificadores, funciones estndar y procedimientos estndar en minsculas
con la primera letra en maysculas (Wr i t eLn).
Los identificadores definidos por el usuario en letras maysculas y minsculas.
Cuando un identificador consta de dos o ms palabras, cada palabra comienza con
una letra mayscula (LeerVector, ListaNumeros).

i

,

!
34 Estructura de datos
Otra circunstancia importante a considerar en la escritura de un programa es el san-
grado o indentacin de las diferentes lneas del mismo. Algunas reglas importantes a
seguir para conseguir un buen estilo de escritura que facilite la legibilidad son:
Los bloques deben ser sangrados suficientemente para que se vean con claridad
(3 a 5 espacios en blanco puede ser una cifra aceptable).
En una sentencia compuesta, las palabras beg i n - end deben estar alineadas:
begin
<sentencia1>
<sen tencia2>



<s ent encian>
end
Sangrado consistente. Sangrar siempre el mismo tipo de construcciones de igual
manera. Algunas propuestas pueden ser:
bucles while/repeat/for
while <condi cin>
<sen t encia>
Sentencias if-then-else
if <con d i cin>
then <sen tenci a1 >
elee <sen t encia2>
if <condicin>
then
<sentencias>
elee
<s entencias>
if <condicin>
then begin
<sent encias>
end
elee begin


end
while <condici n> do
begin
<s entencia>
end
while <condi cin> do
begin
<senten c ias>
end
if <condicin> then
<senten cia1>
elee
<sentencia2>
if <cond1 >
then <acci n 1>
elee if <cond2>
then <acci n2>
elee <cond2> if

Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 35
if <condl> tben inadecuada
<accinl>
else if <cond2> tben
<accin2>
else if <cond3> tben
<accin3>
1.9. LA DOCUMENTACiN
Un programa (un paquete de software) de computadora necesita siempre de una docu-
mentacin que permita a sus usuarios aprender a utilizarlo y mantenerlo. La documentacin
es una parte importante de cualquier paquete de software y, a su vez, su desarrollo es una
pieza clave en la ingeniera de software.
Existen tres grupos de personas que necesitan conocer la documentacin del progra-
ma: programadores, operadores y usuarios. Los requisitos necesarios para cada uno de
ellos suelen ser diferentes, en funcin de las misiones de cada grupo:
programadores
operadores

manual de mantenimiento del programa
manual del operador
operador: persona encargada de correr (ejecutar) el programa, in-
troducir datos y extraer resultados
usuariO manual del usuario
usuario: persona o seccin de una organizacin que explota el pro-
grama, conociendo su funcin, las entradas requeridas, el proceso a
ejecutar y la salida que produce
En entornos interactivos como el caso de Turbo Borland Pascal, las misiones del
usuario y operador suelen ser las mismas. As pues, la documentacin del programa se
puede concretar a:
manual del usuario,
manual de mantenimiento.
1.9.1. Manual del usuario
La documentacin de un paquete (programa) de software suele producirse con dos pro-
psitos: uno, explicar las funciones del software y describir el modo de utilizarlas (do-
cumentacin del usuario, que est diseada para ser leda por el usuario del programa);
dos, describir el software en s para poder mantener el sistema en una etapa posterior de
su ciclo de vida (documentacin del sistema o de mantenimiento)) 7.
7 Brookshear, Glen J.: Introduccin a las ciencias de la computacin, Addison-Wesley, 1995, pg. 272.

I
36 Estructura de datos
La documentacin de usuario es un instrumento comercial importante. Una buena
documentacin de usuario har al programa ms accesible y asequible. Hoy da es una
prctica habitual que muchos creadores de programas contratan escritores tcnicos para
elaborar esta parte del proceso de produccin de un programa. Esta documentacin adopta
la forma de un manual que presenta una introduccin a las funciones ms utilizadas del
software, una seccin que explica cmo instalar el programa y una seccin de referencia
que describe los detalles de cada funcin del software. Es frecuente que el manual se
edite en forma de libro, aunque cada vez es ms frecuente incluirlo adems, o en lugar,
del libro en el propio programa y suele denominarse manual de ayuda en lnea.
La documentacin del sistema o manual de mantenimiento es por naturaleza ms
tcnica que la del usuario. Antiguamente esta documentacin consista en los programas
fuente finales y algunas explicaciones sobre la construccin de los mismos. Hoy da esto
ya no es suficiente y es necesario estructurar y ampliar esta documentacin.
La documentacin del sistema abarca todo el ciclo de vida del desarrollo del software,
incluidas las especificaciones originales del sistema y aquellas con las que se verific el
sistema, los diagramas de flujo de datos (DFD), diagramas entidad-relacin (DER), diccio-
nario de datos y diagramas o cartas de estructura que representan la estructura modular
del sistema.
El problema ms grave que se plantea es la construccin prctica real de la docu-
mentacin y su continua actualizacin. Durante el ciclo de vida del software cambian
continuamente las especificaciones, los diagramas de flujo y de E/R (Entidad/Relacin)
o el diagrama de estructura; esto hace que la documentacin inicial se quede obsoleta o
incorrecta y por esta causa la documentacin requiere una actualizacin continua de
modo que la documentacin final sea lo ms exacta posible y se ajuste a la estructura
final del programa.
El manual de usuario debe cubrir al menos los siguientes puntos:

Ordenes necesarias para cargar el programa en memoria desde el almacenamiento
secundario (disco) y arrancar su funcionamiento.
Nombres de los archivos externos a los que accede el programa.
Formato de todos los mensajes de error o informes.
Opciones en el funcionamiento del programa.
Descripcin detallada de la funcin realizada por el programa.
Descripcin detallada, preferiblemente con ejemplos, de cualquier salida produ-
cida por el programa.
1.9.2. Manual de mantenimiento (documentacin
para programadores)
El manual de mantenimiento es la documentacin requerida para mantener un programa
durante su ciclo de vida. Se divide en dos categoras:
documentacin interna,
documentacin externa.

L,
Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 37
1.9.3. Documentacin interna
Esta documentacin cubre los aspectos del programa relativos a la sintaxis del lengua-
je. Esta documentacin est contenida en los comentarios, encerrados entre llaves { } o
bien parntesis/asteriscos (* *). Algunos tpicos a considerar son:
Cabecera de programa (nombre del programador, fecha de la versin actual, breve
descripcin del programa).
Nombres significativos para describir identificadores.
Comentarios relativos a la funcin del programa como en todo, as como los m-
dulos que comprenden el programa.
Claridad de estilo y formato [una sentencia por lnea, indentacin (sangrado)],
lneas en blanco para separar mdulos (procedimientos, funciones, unidades, etc.).
Comentarios significativos.
Ejemplos
var
Radio ... ( entrada, radi o de un c ircu lo )
( Calcu l ar Area)
Area : = pi * radio * rad i o ;
1.9.4. Documentacin externa
Documentacin ajena al programa fuente, que se suele incluir en un manual que acom-
paa al programa. La documentacin externa debe incluir:
Listado actual del programa fuente, mapas de memoria, referencias cruzadas, etc.
Especificacin del programa: documento que define el propsito y modo de fun-
cionamiento del programa.
Diagrama de estructura que representa la organizacin jerrquica de los mdulos
que comprende el programa.
Explicaciones de frmulas complejas.
Especificacin de los datos a procesar: archivos externos incluyendo el formato
de las estructuras de los registros, campos, etc.
Formatos de pantallas utilizados para interactuar con los usuarios.
Cualquier indicacin especial que pueda servir a los programadores que deben
mantener el programa.
1.9.5. Documentacin del programa
Un programa bien documentado es aquel que otras personas pueden leer, usar y modificar.
Existen muchos estilos aceptables de documentacin y, con frecuencia, los temas a in-
cluir dependern del programa especfico. No obstante, sealamos a continuacin algunas
caractersticas esenciales comunes a cualquier documentacin de un programa:

I
,
,
j




I
I
I

38 Estructura de datos
1. Un comentario de cabecera para el programa que incluye:
a) Descripcin del programa: propsito.
b) Autor y fecha.
c) Descripcin de la entrada y salida del programa.
d) Descripcin de cmo utilizar el programa.
e) Hiptesis sobre tipos de datos esperados.
j) Breve descripcin de los algoritmos globales y estructuras de datos.
g) Descripcin de las variables importantes.
2. Comentarios breves en cada mdulo similares a la cabecera del programa y que
contenga informacin adecuada de ese mdulo, incluyendo en su caso precondi-
ciones y postcondiciones. Describir las entradas y cmo las salidas se relacio-
nan con las entradas.
3. Escribir comentarios inteligentes en el cuerpo de cada mdulo que expliquen
partes importantes y confusas del programa.
4. Describir claramente y con precisin los modelos de datos fundamentales y las
estructuras de datos seleccionadas para representarlas as como las operaciones
realizadas para cada procedimiento.
Aunque existe la tendencia entre los programadores y sobre todo entre los princi-
piantes a documentar los programas como ltima etapa, esto no es buena prctica, lo
idneo es documentar el programa a medida que se desarrolla. La tarea de escribir un
programa grande se puede extender por periodos de semanas o incluso meses. Esto le ha
de llevar a la consideracin de que lo que resulta evidente ahora puede no serlo de aqu
a dos meses; por esta causa, documentar a medida que se progresa en el programa es una
regla de oro para una programacin eficaz.
Regla
Asegrese de que siempre se corresponden los comentarios y el.cdigo. Si se .hace
un cambio importante en el cdigo, asegrese de .que se realiza un cambio similar
en el comentario ..
,
1.10. OEPU RACION
Una de las primeras cosas que se descubren al escribir programas es que un programa
raramente funciona correctamente la primera vez. La ley de Murphy si algo puede ser
incorrecto, lo ser parece estar escrita pensando en la programacin de computadoras.
Aunque un programa funcione sin mensajes de error y produzca resultados, puede
ser incorrecto. Un programa es correcto slo si se producen resultados correctos para
todas las entradas vlidas posibles. El proceso de eliminar errores bugs se denomi-
na depuracin (debugging) de un programa.
Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 39
Cuando el compilador detecta un error, la computadora visualiza un mensaje de error,
que indica se ha producido un error y cul puede ser la causa posible del error. Desgra-
ciadamente, los mensajes de error son, con frecuencia, difciles de interpretar y son, a
veces, engaosos. Los errores de programacin se pueden dividir en tres clases: errores
de compilacin (sintaxis), errores en tiempo de ejecucin y errores lgicos (vase
apartado 1.12).
1.10.1. Localizacin y reparacin de errores
Aunque se sigan todas las tcnicas de diseo dadas a lo largo del libro y en este captulo,
en particular, y cualquier otra que haya obtenido por cualquier otro medio (otros libros, ex-
periencias, cursos, etc.), es prcticamente imposible e inevitable que su programa carezca
de errores. Afortunadamente los programas modulares, claros y bien documentados son
ciertamente ms fciles de depurar que aquellos que no lo son. Es recomendable utilizar
tcnicas de seguridad contra fallos, que protejan contra ciertos errores e informen de
ellos cuando se encuentran.
Con frecuencia el programador, pero sobre todo el estudiante de programacin, est
convencido de la bondad de sus lneas de programa, sin pensar en las mltiples opciones
que pueden producir los errores: el estado incorrecto de una variable lgica, la entrada
de una clusula then o else, la salida imprevista de un bucle por un mal diseo de su
contador, etc. El enfoque adecuado debe ser seguir la traza de la ejecucin del programa
utilizando las facilidades de depuracin de Turbo Borland Pascal o aadir sentencias
Wr i t e que muestren cul fue la clusula ejecutada. En el caso de condiciones lgicas,
si la condicin es falsa cuando se espera que es verdadera como el mensaje de error
puede indicar , entonces el siguiente paso es determinar cmo se ha convertido en falsa.
Cmo se puede encontrar el punto de un programa en que algo se ha convertido en
una cosa distinta a lo que se haba previsto? En Turbo Borland Pascal se puede hacer el
seguimiento de la ejecucin de un programa o bien paso a paso a travs de las sentencias
del programa o bien estableciendo puntos de ruptura (breakpoint). Se puede examinar
tambin el contenido de una variable especfica, bien estableciendo inspecciones/obser-
vaciones (watches) o bien insertando sentencias Wri te temporales (vase el Apndi-
ce). La clave para una buena depuracin es sencillamente utilizar estas herramientas que
indiquen lo que est haciendo el programa.
La idea principal es localizar sistemticamente los puntos del programa que causan
el problema. La lgica de un programa implica que ciertas condiciones sean verdaderas
en puntos diferentes del programa (recuerde que estas condiciones se llaman invarian-
tes). Un error (bug) significa que una condicin que pensaba iba a ser verdadera no lo es.
Para corregir el error, se debe encontrar la primera posicin del programa en la que una
de estas condiciones difiera de sus expectativas. La insercin apropiada de puntos de
ruptura, y de observacin o inspeccin o sentencias Wr i t e en posiciones estratgicas
de un programa tal como entradas y salidas de bucles, estructuras selectivas y subpro-
gramas sirven para aislar sistemticamente el error.
Las herramientas de diagnstico han de informarles si las cosas son correctas o equi-
vocadas antes o despus de un punto dado del programa. Por consiguiente, despus de
,

40 Estructura de datos
ejecutar el programa con un conjunto inicial de diagnsticos se ha de poder seguir el
error entre dos puntos. Por ejemplo, si el programa ha funcionado bien hasta la llamada
al procedimiento o funcin P 1, pero algo falla cuando se llama al procedimiento P 2,
nos permite centrar el problema entre estos dos puntos, la llamada a P2 y el punto con-
creto donde se ha producido el error en P 2. Este mtodo es muy parecido al de aproxi-
maciones sucesivas, es decir, ir acotando la causa posible de error hasta limitarla a unas
pocas sentencias.
Naturalmente, la habilidad para situar los puntos de ruptura, de observacin o sen-
tencias Wr i t e, depender del dominio que se tenga del programa y de la experiencia
del programador. No obstante, le damos a continuacin algunas reglas prcticas que le
faciliten su tarea de depuracin .
1.10.1.1. Uso de sentencias Wr it e
Las sentencias Wr i t e pueden ser muy adecuadas en numerosas ocasiones. Tales sen-
tencias sirven para informar sobre valores de variables importantes y la posicin en el
programa en que las variables toman esos valores. Es conveniente utilizar un comentario
para etiquetar la posicin.
(Posicin una)
WriteLn ('Est situado en posicin una del procedimiento Test');
WriteLn ('A=', a, lB = " b, le = " e);
1.10.1.2. Depuracin de sentencias if-then-else
Situar una parte de ruptura antes de una sentencia i f -then-else y examinar los
valores de las expresiones lgicas y de sus variables. Se pueden utilizar o bien puntos de
ruptura o sentencias Wr i t e para determinar qu alternativa de la sentencia i f se toma:
(Examinar valores de <condicin> y variables antes de if)
if <condicin>
then
begin
WriteLn ('Condicin verdadera: siga camino ' ) ;

end
elae
begin
WriteLn ('Condicin falsa: siga camino');

end;
1.10.1.3. Depuracin de bucles
Situar los puntos de ruptura al principio y al final del bucle y examinar los valores de las
variables importantes:
Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 41
{Examinar valores de m y n antes de entrar al bucle}
for i ~ m to n do
begin
{Examinar los valores de i y variables importantes final bucle}
end;
{Examinar los valores de m y n despus de salir del bucle}
1.10.1.4. Depuracin de subprogramas
Las dos posiciones clave para situar los puntos de ruptura son al principio y al final
de un subprograma. Se deben examinar los valores de los parmetros en estas dos
posiciones utilizando o bien sentencias Wr i t e o ventanas de inspeccin u observacin
(watches).
1.10.1.5. Lecturas de estructuras de datos completos
Las variables cuyos valores son arrays u otras estructuras puede ser interesante exami-
narlas. Para ello se recurre a escribir rutinas especficas de volcado (presentacin en
pantalla o papel) que ejecuten la tarea. Una vez diseada la rutina se llama a ella desde
puntos diferentes segn interesa a la secuencia de flujo de control del programa y los
datos que sean necesarios en cada caso.
1.10.2. Los equipos de programacin
En la actualidad es dificil y raro que un gran proyecto de software sea implementado
(realizado) por un solo programador. Normalmente, un proyecto grande se asigna a un
equipo de programadores, que por anticipado deben coordinar toda la organizacin glo-
bal del proyecto.
Cada miembro del equipo es responsable de un conjunto de procedimientos, algu-
nos de los cuales pueden ser utilizados por otros miembros del equipo. Cada uno de
estos miembros deber proporcionar a los otros las especificaciones de cada proce-
dimiento, condiciones pretest o postest y su lista de parmetros formales; es decir, la
informacin que un potencial usuario del procedimiento necesita conocer para poder
ser llamado.
Normalmente, un miembro del equipo acta como bibliotecario, de modo que a me-
dida que un nuevo procedimiento se termina y comprueba, su versin actualizada susti-
tuye la versin actualmente existente en la biblioteca. Una de las tareas del bibliotecario
es controlar la fecha en que cada nueva versin de un procedimiento se ha incorporado a
la librera, as como asegurarse de que todos los programadores utilizan la versin lti-
ma de cualquier procedimiento.
Es misin del equipo de programadores crear bibliotecas de procedimientos, que
posteriormente puedan ser utilizadas en otras aplicaciones. Una condicin importante
deben cumplir los procedimientos estar comprobados y ahorro de tiempo/memoria.
42 Estructura de datos
-
1.11. DISENO DE ALGORITMOS
Tras la fase de anlisis, para poder solucionar problemas sobre una computadora, debe
conocerse cmo disear algoritmos. En la prctica sera deseable disponer de un mtodo
para escribir algoritmos, pero, en la realidad, no existe ningn algoritmo que sirva para
realizar dicha escritura. El diseo de algoritmos es un proceso creativo. Sin embargo,
existen una serie de pautas o lneas a seguir que ayudarn al diseo del algoritmo (Ta-
bla 1.1).
Tabla 1.1. Pautas a seguir en el diseo de algoritmos
1. FOllnular una solucin precisa del problema que debc solucionar el algoritmo.
2. Ver si existe ya algn algoritmo para resolver el problema o bien se puede adaptar uno ya existente
(algoritmos conocidos).
3. Buscar si existen resolver el.problema.
4. Elegir una estructura de
. . " . . ..
5. Dividir el problelll!l 1:11 s\l:bP(Clbl!<lllas Y plic.arel mtodo a ca4a los subproblemas (di$eo .
. descendente). . ....
. . , .... ", '" ... ,:'
6. Si todo lo anterior falla, comIence de nuevo en el paso 1.
, ...._--- -- ---'-,,- .,. -
, ;, 1 . ' -:::.,: _,o:: __-._? __ - - ,
De cualquier forma, antes de iniciar el diseo del algoritmo es preciso asegurarse
que el programa est bien definido:
Especificaciones precisas y completas de las entradas necesarias.
Especificaciones precisas y completas de la salida.
Cmo debe reaccionar el programa ante datos incorrectos?
Se emiten mensajes de error? Se detiene el proceso?, etc.
Conocer cundo y cmo debe terminar un programa.
1.12. PRUEBAS (TESTING)
Aunque muchos programadores utilizan indistintamente los trminos prueba o comproba-
cin (testing) y depuracin, son, sin embargo, diferentes. La comprobacin (pruebas)
se refiere a las acciones que detellninan si un programa funciona correctamente. La depu-
racin es la actividad posterior de encontrar y eliminar los errores (bugs) de un programa.
Las pruebas de ejecucin de programas normalmente muestran claramente que el
programa contiene errores, aunque el proceso de depuracin puede, en ocasiones, resul-
tar dificil de seguir y comprender.
Edgar Dijkstra ha escrito que mientras las pruebas muestran efectivamente la presen-
cia de errores, nunca pueden mostrar su ausencia. Una prueba (test) con xito significa
solamente que ningn error se descubri en las circunstancias particulares probadas,
pero no dice nada sobre otras circunstancias. En teora, el nico medio de comprobar

I
,
,
,
"
Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 43
que un programa es correcto es probar todos los casos posibles (realizar una prueba
exhaustiva), situacin tcnicamente imposible, incluso para los programas ms simples.
Consideremos un caso sencillo: calcular la media aritmtica de las temperaturas de un
mes dado; una prueba exhaustiva requerir todas las posibles combinaciones de tempe-
raturas y das de un mes: tarea ardua, laboriosa y lenta.
No obstante, el anlisis anterior no significa que la comprobacin sea imposible;
al contrario, existen diferentes metodologas formales para las comprobaciones de pro-
gramas. Una filosofa adecuada para pruebas de programas incluye las siguientes con-
sideraciones:
1. Suponer que su programa tiene errores hasta que sus pruebas muestren lo contrario.
2. Ningn test simple de ejec4cin puede probar que un programa est libre de
error.
3. Trate de someter al programa a pruebas duras. Un programa bien diseado mani-
pula entradas con elegancia. Por este trmino se entiende que el programa no
produce errores en tiempo de ejecucin ni produce resultados incorrectos; por el
contrario, el programa, en la mayora de los casos, visualizar un mensaje de error
claro y solicita de nuevo los datos de entrada.
4. Comenzar la comprobacin antes de terminar la codificacin.
5. Cambiar slo una cosa cada vez.
Cada vez que se ejecuta un programa con algunas entradas, se prueba a ver cmo
funciona el trabajo para esa entrada particular. Cada prueba ayuda a establecer que el
programa cumpla las especificaciones dadas.
Seleccin de datos de prueba
Cada prueba debe ayudar a establecer que el programa cumple las especificaciones dadas.
Parte de la ciencia de ingeniera de software es la construccin sistemtica de un conjunto
de entradas de prueba que es idneo a descubrir errores.
Para que un conjunto de datos puedan ser considerados como buenos datos de prue-
ba, sus entradas de prueba necesitan cumplir dos propiedades.
Propiedades de buenos " datos de prueba
" " "
1. Se debe conocer qu 'salida debep'rOdliClr un 'pr'grarriti:correcto para cada
entrada de prueba.
2. ' Lasertrada.sde prUeba deben incluiraqueTls entradas que probablemente ori-
" ; -"., . __.,- _"_,, ,-- 'o _- . ' __ .. - _: - . . , ,_._ ,
ginen ms errores. " ' . .. . . ' . " ".
. ., .... , ,',. , . . .. ... . .
, " .:: ,:. : .. ' " .. :.' ' .. '
,,' .. ," :'" ::;'. '; ,,'
44 Estructura de datos
Se deben buscar numerosos mtodos para encontrar datos de prueba que produzcan
probablemente errores. El primer mtodo se basa en identificar y probar entradas deno-
minadas valores externos, que son especialmente idneos para causar errores. Un valor
externo o lmite de un problema en una entrada produce un tipo diferente de comporta-
miento. Por ejemplo, suponiendo que se tiene una funcin ver_hora que tiene un
parmetro hora y una precondicin:
Hora est comprendido en el rango 0-23
Los dos valores lmites de ver_hora son hora igual a O (dado que un valor menor
de O es ilegal) y hora igual a 23 (dado que un valor superior a 23-24 ... es ilegal). Puede
ocurrir que la funcin se comporte de modo diferente para horario matutino (O a 11) o
nocturno (12 a 23), entonces 11 y 12 sern valores extremos. Si se espera un comporta-
miento diferente para hora igual a O, entonces 1 es un valor extremo. En general no
existe una definicin precisa de valor extremo, pero debe ser aquel que muestre un com-
portamiento lmite en el sistema.
Valores de prueba extremos
Si no se p\le.Qenprobar to.Qas las entra.Qas pQsibles, probar al meno; los valores
extremos. Por ejemplo, .si el rango .Qeentradas legales va de cero a un milln,
asegrese probar la entrada()y la entrada 1.000.000. Es buena idea considerar
tambin 0,.1 Y -1 cQmo yalore.;limitessiempre que sean entrada; legales.
Otra tcnica de prueba de datos es la denominada perfilador que bsicamente consi-
dera dos reglas:
l. Asegrese de que cada lnea de su cdigo se ejecuta al menos una vez para algu-
nos de sus datos de prueba. Por ejemplo, puede ser una porcin de su cdigo que
maneje alguna situacin rara.
2. Si existe alguna parte de su cdigo que a veces se salte totalmente, asegrese, en
ese caso, que existe al menos una entrada de prueba que salte realmente esta
parte de su cdigo. Por ejemplo, un bucle en el que el cuerpo se ejecute, a veces,
cero veces. Asegrese de que hay una entrada de prueba que produce que el
cuerpo del bucle se ejecute cero veces.
1.12.1. Errores de sintaxis (de compilacin)
Un error de sintaxis o en tiempo de compilacin se produce cuando existen errores en la
sintaxis del programa, tales como signos de puntuacin incorrectos, palabras mal escri-
tas, ausencia de separadores (signos de puntuacin), o de palabras reservadas (ausencia



~


,


I


; .

,


"
,

Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 45
de un end). Si una sentencia tiene un error de sintaxis, no puede ser traducida y su pro-
. ,
grama no se ejecutara.
Cuando se detecta un error, Turbo Borland Pascal carga automticamente el archivo
fuente, sita el cursor en el error y visualiza un mensaje de error.
44 Field identifier expected
NOllnalmente, los mensajes de error son fciles de encontrar. El siguiente ejemplo pre-
senta dos errores de sintaxis: el punto y coma que falta al final de la primera lnea y la
palabra WritaLn mal escrita, debera ser WriteLn.
Suma := O
for 1 := O to 10 do
Suma := Suma + A[I];
WritaLn (Suma/lO);
1.12.2. Errores en tiempo de ejecucin
Los errores en tiempo de ejecucin o simplemente de ejecucin (runtime error)
suceden cuando el programa trata de hacer algo imposible o ilgico. Los errores de eje-
cucin slo se detectan en la ejecucin. Errores tpicos son: la divisin por cero, intentar
utilizar un subndice fuera de los lmites definidos en un array, etc.
X := l/N produce un error si N - O
Los mensajes de error tpicos son del tipo:
Run - Time error nnn at xxxx:yyyy
nnn nmero de error en ejecucin
xxxx:yyyy direccin del error en ejecucin (segmento y desplazamiento)
Los errores de ejecucin se dividen en cuatro categoras:
errores DOS, 1-99 (nmeros de mensaje)
errores //0, 100-149
errores crticos, 150-199
errores fatales, 200-255
1.12.3. Errores lgicos
Los errores lgicos son errores del algoritmo o de la lgica del programa. Son dificiles de
encontrar porque el compilador no produce ningn mensaje de error. Se producen cuan-
do el programa es perfectamente vlido y produce una respuesta .

46 Estructura de datos
Calcular la media de todos los nmeros ledos del teclado
Suma := o;
for i := O to 10 do
begin
ReadLn (Num);
Suma := Suma + Num
end;
Media := Suma / 10;
La media est calculada mal ya que existen once nmeros (O a 10) y no diez como se ha
escrito.
Si se desea escribir la sentencia:
Salario := Horas * Tasa;
y se escribe:
Salario := Horas + Tasa;
Es un error lgico (+ por *) ya que a priori el programa funciona bien, y sera dificil,
por otra parte, a no ser que el resultado fuese obvio, detectar el error.
1.12.4. El depurador
Turbo Borland Pascal tiene un programa depurador disponible para ayudarle a depurar
un programa; el programa depurador le permite ejecutar su programa, una sentencia cada
vez, de modo que se pueda ver el efecto de la misma. El depurador imprime un diagns-
tico cuando ocurre un error de ejecucin, indica la sentencia que produce el error y
permite visualizar los valores de variables seleccionadas en el momento del error. Asi-
mismo, se puede seguir la pista de los valores de variables seleccionadas durante la eje-
cucin del programa (traza), de modo que se pueda observar cmo cambian estas varia-
bles mientras el programa se ejecuta. Por ltimo se puede pedir al depurador que detenga
la ejecucin en determinados puntos (breakpoints); en esos momentos se pueden inspec-
cionar los valores de las variables seleccionadas a fin de determinar si son correctas.
El depurador tiene la gran ventaja de posibilitar la observacin de los diferentes va-
lores que van tomando las variables dentro del programa.
1.13. EFICIENCIA
La eficiencia de un programa es una medida de cantidad de recursos consumidos por el
programa. Tradicionalmente, los recursos considerados han sido el tiempo de ejecucin
y/o el almacenamiento (ocupacin del programa en memoria). Mientras menos tiempo
se utilice y menor almacenamiento, el programa ser ms eficiente.
El tiempo y almacenamiento (memoria) de la computadora suelen ser costosos y por
ello su ahorro siempre ser importante. En algunos casos la eficiencia es crticamente
,
,
Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 47
importante: control de una unidad de vigilancia intensiva de un hospital un retardo de
fracciones de segundo puede ser vital en la vida de un enfermo , un programa de control
de roturas en una prensa hidrulica la no deteccin a tiempo podra producir grandes
inundaciones , etc. Por el contrario, existirn otros casos en los que el tiempo no ser
factor importante: control de reservas de pasajeros en una agencia de viajes.
La mejora del tiempo de ejecucin y el ahorro en memoria se suelen conseguir con la
mejora de los algoritmos y sus programas respectivos. En ocasiones, un simple cambio
en un programa puede aumentar la velocidad de ejecucin considerablemente. Como
muestra de ello analicemos el problema siguiente desde el punto de vista de tiempo de
. . ,
eJecuclOn
Buscar en un array o lista de enteros una clave dada (un entero)
ArrayLi sta : Lista[Primero .. Ultimo] of integer
ALGORITMO Buscar el emento t
J := Pr i me ro;
while (T<> Lista [J] and (J < Ulti mo) do
J : = J + 1;
if T = Lista [J] then
Wri t e Ln ('el el ement o ', T, 'est en la li s t a ' )
elee
Writ eLn ('el element o ', T, 'no est en la lista')
El bucle va comprobando cada elemento de la lista hasta que encuentra el valor de T
o bien se alcanza el final de la lista sin encontrar T.
Supongamos ahora que la lista de enteros est ordenada.
45 73 8 1 1 20 1 6 0 321 450
En este caso el bucle puede ser ms eficiente si en lugar de la condicin
(T <> Lista[J]) and (J < Ultimo)
se utiliza
(T > Lista[J]) and (J < Ul timo)
Ello se debe a que si T es igual a Lis t a [J 1 , se ha encontrado el elemento, y si T es
menor que Lis t a [J 1 , entonces sabemos que T ser ms pequeo que todos los elementos
que le siguen. Tan pronto como se pruebe un valor de T y resulte menor que su correspon-
diente Lis t a [J 1 , esta condicin ser falsa y el bucle se terminar. De este modo, y
como trmino medio, se puede ahorrar alrededor de la mitad del nmero de iteraciones.
En el caso de que T no existe en la lista, el nmero de iteraciones de ambos algoritmos
es igual, mientras que si T no existe en la lista, el algoritmo 2 con (T > Lis t a [J 1 )
reducir el nmero de iteraciones en la mitad y por consiguiente ser ms eficiente.

If... ,
Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 49
Ejecucin
Introd uzca 10 ent eros en orde n ascendente :
2 5 8 12 23 37 4 5 89 1 12 234
I n tro duc ir n me r o a buscar :
27
el e l e mento 27 n o es t en l a l ista
Bus q ueda1 te rmi nada e n
10 i t e r ac i on es
el elemento 2 7 n o es t en l a lista
Bus queda2 t ermi nada en
6 i t eracione s
1.13.1. Eficiencia versus leg i bilidad (claridad)
Las grandes velocidades de los microprocesadores (unidades centrales de proceso)
actuales, junto con el aumento considerable de las memorias centrales (cifras tpicas
usuales superan siempre los 32/64 MB), hacen que los recursos tpicos tiempo y almace-
namiento no sean hoy da parmetros fundamentales para la medida de la eficiencia de
un programa.
Por otra parte es preciso tener en cuenta que a veces los cambios para mejorar
un programa puede hacerlo ms dificil de comprender: poco legibles o claros. En pro-
gramas grandes la legibilidad suele ser ms importante que el ahorro en tiempo y en
almacenamiento en memoria. Como norma general, cuando la eleccin en un programa
se debe hacer entre claridad y eficiencia, generalmente se elegir la claridad o la legibi-
lidad del programa.
1.14. TRANSPORTABILIDAD (PORTABILIDAD)
Un programa es transportable o portable si se puede trasladar a otra computadora sin
cambios o con pocos cambios apreciables. La forma de hacer un programa transportable
es elegir como lenguaje de programacin la versin estndar del mismo, en el caso de
Pascal: ANSI/IEEE estndar e ISO estndar.
Turbo Borland Pascal no sigue todas las normas del estndar y adems rene un
conjunto de caractersticas no disponibles en Pascal estndar. Esto significa que si desea
transportar sus programas a Pascal estndar, deber evitar en los mismos todas las carac-
tersticas propias de Turbo.
RESUMEN
La ingeniera de software trata sobre la creacin y produccin de programas a gran escala. El
ciclo de vida del software consta de las fases:
Anlisis de requisitos y especificacin.
Diseo.
Implementacin (codificacin y depuracin).
I
I
,
I

,
i
i
;


:
,
1
,

!
I
,
50 Estructura de datos
Prueba.
Evolucin.
Mantenimiento.
Si se desea crear buenos programas en Turbo Borland Pascal, los conceptos de unidades y progra-
macin modular sern vitales en el desarrollo de los mismos.
EJERCICIOS
1.1. Cul es el invariante del bucle siguiente?
I nd i ce := 1 ;
Suma : = A [ 1 ] ;
while Ind ic e < N hacer
begin
Indice : = Succ ( Ind i ce) ;
Suma := Suma + A[ Indice ]
end;
1.2. Considere el programa siguiente que interactivamente lee y escribe el nmero de identifica-
cin, nombre, edad y salario (en millares de pesetas) de un grupo de empleados. Cmo se
puede mejorar el programa?
program Test ;
var xl, x 2, x3 , i : integer ;
Nombre: array [ l .. 10 ] of char;
begin
while not eo f do
begin
Re ad ( xl ) ;
for i : = 1 to 8 do
Read ( Nombre [ i] ) ;
Rea d Ln ( x 2 , x 3 ) ;
Wr it e Ln ( x 1 , Nombr e ,x2 , x 3 )
end
end;
1.3. Cul es el error de la siguiente funcin? Cmo puede resolverse?
function Tangent e ( x : r eal) :real ;
begin
Ta ng e n te : = si n (x) / cos(x)
end;
1.4. Escribir una [uncin que devuelve el total de dgitos (n) distintos de cero en un nmero
entero arbitrario (Nmero). La solucin debe incluir un bucle while con el siguiente inva-
riante de bucle vlido.
{invariant e :
O <= Tota l <= n y Nme r o se ha div i d i d o por 10 veces To ta l }
y sta ser la asercin vlida (postcondicin)
{postcondicin : Total e s n }
-



'.


....... ,,' ,. __ .. ,._- ._.-
.. -
Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 51
1.5. Escribir un invariante de bucle para el siguiente segmento de cdigo
Produc t o : = 1 ;
Con tad o r := 2 ;
while Cont ador < 10 do
begin
Producto : = Producto * Contador;
Contador : = Contador + 1
end;
PROBLEMAS
1.1. Escribir un programa que lea una lista de 100 o menos enteros y a continuacin realice las
siguientes tareas: visualizar la lista ordenada desde el mayor hasta el menor; visualizar li sta
en orden inverso, calcular la media; calcular la mediana; listar las listas en orden creciente y
en orden decreciente, mostrando la diferencia de cada valor con la media y la mediana. Es
conveniente que cada tarea se realice con un mdulo y luego se integren todos en un pro-
grama.
1.2. A la entrada de un aparcamiento, un automovilista retira un ticket en el cual est indicado
su hora de llegada. Antes de abandonar el aparcamiento se introduce el ticket en una m-
quina que le indica la suma a pagar. El pago se realiza en una mquina automtica que
devuelve cambio.
Escribir un programa que simule el trabajo de la mquina. Se supone que:
La duracin del estacionamiento es siempre inferior a 24 horas.
La mquina no acepta ms que monedas de 200, 100, 50, 25, 5, 2 y l peseta.
Las tarifas de estacionamiento estn definidas por tramos semihorarios (1/2 hora).
1.3. Escribir un programa que contenga una serie de opciones para manipular un par de matri-
ces (suma, resta y multiplicacin). Cada procedimiento debe validar sus parmetros de en-
trada antes de ejecutar la manipulacin requerida de datos.
1.4. Un viajante de comercio debe visitar N ciudades. Parte de una de ellas y debe volver a su
punto de partida. Conoce la distancia entre cada una de las ciudades y desea hacer un viaje
lo ms corto posible. El sistema elegido de viaje es el siguiente:
A partir de cada ciudad, elige como ciudad siguiente la ms prxima entre las ciudades
que no ha visitado.
Se suponen datos: la lista de ciudades, las distancias (en kilmetros) entre cada una de ellas
y el nombre de la ciudad de partida. Elegir un algoritmo que calcule el recorrido ms corto.
1.5. Se tiene la lista de una clase que contiene un nombre de estudiante y las notas de cinco
exmenes. Se desea escribir un programa que visualice la media de cada alumno, la nota
media ms alta y la nota media ms baja, junto con los nombres correspondientes.
1.6. Se desea disear un programa que permita adiestrar a un nio en clculos mentales. Para
ello el nio debe elegir entre las cuatro operaciones aritmticas bsicas; la computadora le
presentar la operacin correspondiente entre dos nmeros, y el nio debe introducir desde
el teclado el resultado. El nio dispone de tres tentativas. Caso de acertar, la computadora
debe visualizar Enhorabuena, y en caso de fallo Lo siento, intntalo otra vez.

,
52 Estructura de datos
1.7. Escribir un programa que construya un directorio telefnico interactivo que contiene una
coleccin de nombres y nmeros de telfonos. Las caractersticas del directorio han de
ser: 1) poder insertar una nueva entrada en el directorio; 2) recuperar una entrada del direc-
torio; 3) cambiar una entrada del directorio, y 4) borrar una entrada del directorio. Nota: El
directorio debe estar ordenado alfabticamente.


,

,
,
,
I



;
,
}
,
,
,
CAPITULO
. ,
-,onstrucclon ran es ro ramas:
a es
, .
mo u os versus unl
, , - - -- "- - ,- ~ - -
-- -,
.

CONTENIDO
2.1. Concepto de unidad.
2.2. Estructura de una unidad.
2.3. Creacin de unidades.
2.4. Utilizacin de unidad estndar.
2.5. Situacin de las unidades en sus discos. Dnde busca Turbo Borland Pascal las uni-
dades?
2.6. Identificadores idnticos en diferentes unidades.
2.7. Sntesis de unidades.
2.8. Otros mtodos de estructurar programas: inclusin, solapamiento y encadenamiento.
RESUMEN.
EJERCICIOS.
REFERENCIAS BIBLIOGRFICAS.
Una de las caractersticas ms interesantes de Turbo Borland Pascal 5/
6/7 es la posibilidad de descomponer un programa grande en produc-
tos ms pequeos que se pueden compilar independientemente. Estos
mdulos se denominan unidades y eliminan el inconveniente de las
versiones anteriores a 4.0 de la limitacin de la memoria ocupada por
programas ejecutables a 64 K. Los lectores que hayan utilizado Modu-
la-2 encontrarn familiar el concepto unidad, ya que unidad (en Turbo
Borland Pascal) y mdulo (en Modula-2) representan el concepto de
compilacin separada y la posibilidad de construir grandes programas
enlazando unidades compiladas separadamente para construir un pro-
grama ejecutable. Como resultado de ello, cuando se realiza un cam-
bio en el cdigo fuente, slo se tiene que compilar el segmento al que
afecta la modificacin.
53
1

i
1
I
,
,
;
I
,


r

,

54 Estructura de datos
2.1. CONCEPTO DE UNIDAD
Una unidad es un conjunto de constantes, tipos de datos variables, procedimientos y
funciones. Cada unidad es como un programa independiente Pascal o bien una bibliote-
ca de declaraciones que se pueden poner en un programa y que permiten que ste se
pueda dividir y compilar independientemente. Una unidad puede utilizar otras unidades
y contiene una parte que puede contener instrucciones de iniciacin.
Una unidad contiene uno o ms procedimientos, funciones constantes definidas (y a
veces otros elementos). Se puede compilar, probar y depurar una unidad independien-
temente de un programa principal. Una vez que una unidad ha sido compilada y depurada,
no necesita compilarse ms veces, Turbo Borland Pascal se encarga de enlazar la unidad
al programa que utiliza esa unidad, empleando siempre en esta tarea menor tiempo que
en la propia compilacin. Los procedimientos, funciones y constantes que se definen en
una unidad pueden ser utilizados por cualquier futuro programa que escriba sin tener
que ser declarados en el programa.
Las unidades tienen una estructura similar a los programas y en consecuencia requieren
un formato estricto, y es preciso declararlas por el usuario como si se tratara de un pro-
grama o subprograma.
Turbo Borland Pascal proporciona siete unidades estndar para el uso del programador:
System, Graph, DOS, ert, Printer, Turbo3 y Graph3. Las cinco primeras sirven para
escribir sus programas, y las dos ltimas para mantener compatibilidad con programas y
archivos de datos creados con la versin 3.0 de Turbo Borland Pascal. Las siete unidades
estn almacenadas en el archivo TURBO.TPL (biblioteca de programas residente propia
del programa Turbo Borland Pascal). La versin 7.0 introdujo dos nuevas unidades: WinDos
y Strings.
2.2. ESTRUCTURA DE UNA UNIDAD
Una unidad est constituida de cuatro partes: cabecera de la unidad, seccin de interface
(interfaz), seccin implementation (implementacin) y seccin initialization (iniciali-
zacin) 1.
Formato
unit <identi ficado r>;
interface
uses <lista de unidades >; {opciona l}
{decl ara cione s pblicas Obje t os exportados }
implementation
{declaraci o nes privadas}
{defini cin de procedi mientos y fu nc i ones pbl i cas}
begin
{cdigo de inicializac i n } {opcional}
end.
I Aceptamos el tllnino inicializacin por su extensa difusin en la jerga infollntica, aun a sabiendas
que dicho trmino no es aceptado por el DRAE y su expresin correcta sera iniciacin.

,
,

;
,

,
,
,
,
;
,

i

i
,

I
1
I
1
,
,
,
j

J
1
,
1
,
1

,
,
i
i
I
1
,
,
i
,
,
,

,
i
1
1
1

<1
,
j
;

1
,


Construccin de grandes programas: mdulos versus unidades 55
2.2.1. Cabecera de la unidad
La cabecera de la unidad comienza con la palabra reservada uni t, seguida por el nom-
bre de la unidad (identificador vlido)2. Es similar a una cabecera de programa, donde la
palabra reservada unit reemplaza a la palabra reservada programo Por ejemplo, para crear
una unidad denominada MiUnidad se ha de utilizar la cabecera de la unidad: unit
MiUnidad.
El nombre de la unidad es arbitrario pero debe coincidir con el nombre del archivo
que contiene. Por ejemplo, si la unidad se denomina Test.
Un it Test;
el archivo que contiene el programa fuente de la unidad se debe llamar Te s t . P AS.
Cuando Turbo Borland Pascal compila la unidad, le asigna la extensin TPU (Turbo
Borland Pascal Uni t). Si el nombre de la unidad es diferente del nombre del ar-
chivo, el programa principal no podr encontrar el archivo TPU.
Una unidad puede utilizar otras unidades siempre que se incluyan en la clusula uses
que aparece inmediatamente despus de la palabra interface, y separadas por comas.
2.2.2. Seccin de interfaz
La seccin de interface (interfaz) es la parte de la unidad que sirve para conectar dicha
unidad con otras unidades y programas. Esta seccin se conoce como la parte pblica
de la unidad, ya que todos los objetos que figuren en esta seccin son visibles desde el
exterior o exportables. Las restantes unidades y programas tienen acceso a la informa-
cin contenida en la seccin de interface.
En la interfaz de la unidad se pueden declarar constantes, tipos de datos, variables
y procedimientos. Los procedimientos y funciones visibles a cualquier programa que uti-
lice la unidad se declaran aqu, pero sus cuerpos reales implementaciones se en-
cuentran en la seccin de implementacin. La seccin de interfaz indica a un progra-
mador cules procedimientos y funciones se pueden utilizar en un programa. La seccin
de implementacin indica al compilador cmo implementarlos .
Los identificadores declarados en la seccin de interfaz pueden ser referenciados por
un cliente de la unidad, de modo que se consideran visibles.
Ejemplo de declaracin
unit Rayo ;
interface
uses DOS , Graph, Crt ; (se utilizan las un i dade s DOS, Gr aph y Crt )
var
a , b, e : int ege r
function Exponencia l

(a, b : i n t eger) : rea l;
procedure Di v idir (x, y : integer ;var cociente: i nt eger) ;
2 El identificador puede tener de uno a ocho caracteres ms un punto y una extensin tal como .PAS .

I


56 Estructura de datos
En la seccin de interface se pueden declarar variables y elementos globales y otras
unidades.
Observaciones
l. La unidad Rayo puede utilizar cualqui er procedimiento o funcin presente en
las unidades estndar Dos, Gr aph o Cr t .
2. Se declaran tres variables globales; a, b, e (estn disponibles a otras unidades y
programas que utilicen la unidad Rayo). Se debe extremar el cuidado a la hora
de declarar variables globales en la seccin de interfaz de la unidad.
2.2.3. Seccin de implementacin
La tercera parte de una unidad, denominada implementation (implementacin) , es
estrictamente privada; su contenido no es exportable. Slo los procedimientos o fun-
ciones que aparecen en la seccin interface pueden ser invocados desde el exterior
de la unidad.
Esta seccin contiene el cuerpo de los procedimientos y funciones declarados en la
seccin de interface.
unit Rayo ;
interface
function Expon encia l (A, B : i n t eger ) : rea l;
procedure Di v i dir (X , Y: int eger ; var Cocient e : int eger) ;
implementation
function Expone n c i al (A, B : i nt eger) : real ;
var
P, I : integer;
begin
P : = 1 ;
for 1 := 1 to B do
P := P * A;
Expone nc ial
end;
' - P
. -

procedure Di vidi r (X , Y : integer ; var Coc i e n te : i n t e ger);


begin
Coc iente : = X d iv y
end;
o o o
endo
Ntese que la declaracin de una unidad est terminada por la palabra reservada
end y un punto.
Las variables globales pueden ser declaradas dentro de una seccin de implementacin,
pero estas variables sern globales a la unidad solamente y no accesibles a cualquier otra
unidad o programa.


,
,
,
!
,

Construccin de grandes programas: mdulos versus unidades 57
2.2.4. Seccin de iniciacin (inicializacin)
La cuarta parte de una unidad, llamada iniciacin, puede contener instrucciones
pero puede igualmente estar vaca. Estas instrucciones sirven, por ejemplo, para iniciali-
zar variables o abrir archivos. La ejecucin de estas instrucciones se efecta en el mo-
mento del lanzamiento o ejecucin de un programa que utiliza la unidad antes de la
ejecucin de la primera instruccin del cuerpo del programa.
En la seccin de iniciacin se inicializa cualquier estructura de datos (variables) que
utilice la unidad y las hace disponibles (a travs del interface) al programa que las utili-
za. Comienza con la palabra reservada beg in seguida por una secuencia de sentencias
y termina con end. (Al igual que en los programas ordinarios se requiere un punto a
continuacin de end).
Cuando un programa que utiliza esta unidad se ejecuta, la seccin de iniciacin se
llama antes que el cuerpo del programa se ejecute.
2.2.5. Ventajas de las unidades
La nocin de unidad acenta el carcter estructurado y modular de Turbo Borland Pascal
para el diseo de grandes programas. Las unidades que representan mdulos indepen-
dientes pueden ser compiladas aisladamente, con independencia de un programa. Estas
propiedades facilitan la creacin de libreras, estndar o personalizadas (por el usuario).
Turbo Borland Pascal dispone de varias unidades estndar predefinidas conectadas
a tareas especficas: grficos, gestin de pantalla, etc. Cualquier usuario puede, a su vez,
crear sus propias unidades, enriqueciendo as los recursos bsicos. En general una unidad
puede llamar a otras unidades.
,
2.3. CREACION DE UNIDADES
Una unidad tiene una estructura muy similar a la de un programa.
La clusula uses de la parte de interface slo es necesaria en el caso de que la
unidad actual llame a otras unidades. Todos los procedimientos y funciones en la sec-
cin de interfaz deben ser definidos en la seccin de implementacin.
El contenido de la parte de iniciacin es optativo; si figuran en ellas instrucciones, se
ejecutarn inmediatamente antes del principio de la ejecucin del programa que utiliza
esta unidad.
La cabecera de los procedimientos y funciones declaradas en la parte de interface
deben ser idnticos a la cabecera de las mismas funciones definidas en la parte de imple-
mentacin; sin embargo, es posible escribir la cabecera en forma abreviada en la seccin
de implementacin.
Una vez que se dispone el cdigo fuente de una unidad, se compila de igual forma
que un programa, pero el archivo obtenido no es ejecutable directamente. Se trata de un
archivo objeto con la extensin TPU (Turbo Borland Pascal Unit). As, por ejemplo, si la
unidad se graba con el nombre Demo . Pas, se guardar con el nombre Demo. TPU.

58 Estructura de datos
unit utilidad
interface
uses ert;
nombre de unidad
ha de corresponder
con nombre de archivo
opcional
procedure Frase(Texto : string);
implementation
uses Printer; opcional
var
MiVar : Integer
procedure Frase;
begin
ClrScr;
GotoXY ((80-Length (Texto)) div 2,1)
Write (texto);
end;
begin
Cabecera de la unidad
Seccin de interfaz
Seccin de implementacin
Mi Var : = o Seccin de iniciacin
end.
Figura 2.1. Estructura de una unidad.
Para utilizar una unidad en su programa, debe incluir una sentencia uses para indi-
car al compilador que est utilizando esa unidad.
program Prueba;
uses demo;
Turbo Borland Pascal espera que el nombre del archivo fuente tenga el mismo nom-
bre de la unidad. Por ejemplo, la unidad demo se encuentra en el archivo demo . tpu.
Si el nombre de la unidad fuera demostra. TPU, Turbo Borland Pascal tratar de en-
contrar un archivo demostra. TPU para evitar estas contrariedades se puede utilizar
una directiva del compilador ($ U) , que permite especificar el nombre del archivo en
que se encuentra la unidad. As, por ejemplo, si la unidad utilidad se encuentra en el
archivo VARIOS. PAS un programa puede llamar de la forma siguiente:
program Test;
uses
Crt, {SU VARIOS.PAS} utilidad;
Construccin de grandes programas: mdulos versus unidades 59
La directiva debe preceder inmediatamente al identificador de la unidad.
Cuando el compilador encuentra la clusula uses nombre-unidad, busca la unidad
nombre-unidad sucesivamente en:
Biblioteca de base TURBO. T PL .
El archivo n ombre-uni dad . TPU en el directorio actual , despus en el direc-
torio reservado a las unidades y especifica en el men Op tion s del entorno
de trabajo.
Pasos de compilacin de una unidad
l. Edicin de la unidad.
2. Seleccionar la orden Compile / Comp il e (o pulse ALT-C) .
Una vez sin errores, conviene activar la opcin Comp i le a d i sk y volver a compilar.
Turbo Borland Pascal crea un archivo con extensin T PU. Este archivo se puede
dejar o mezclarlo con TURBO . TPL.
EJEMPLO 2.1
Escribir una unidad que conste a su vez de un procedimiento para intercambiar los
valores de dos variables, as como calcular su valor mximo.
unit Demol;
interface
procedure I nter cambio (var I , J : int eger) ;
function Ma x imo (I , J : i ntege r) : i nt eger ;
implementation
procedure I n tercambio;
var
Aux : integer ;
begin
Aux
1
J
end;

-
-
-
-
-

-
function
begin
if I>J
then
else
end;
end.
I

,
J ;
Aux
Maximo;
Ma x imo
Maximo
- I
-
- J
-
Tras editar el programa, gurdelo en disco con el nombre Demo 1 . PAS , a continua-
cin compilar en disco. El cdigo objeto resultante ser Demo l . TPU. Un programa que
utiliza la unidad Demo 1 es:

,
60 Estructura de datos
program Prueba;
uses
Demo 1 ;
var
X, y : integer ;
begin
Write ('Introduc i r dos
ReadLn (X, Y);
,
nume r as enter os ' ) ;
Intercambio (X , y); Wr it eLn (X ,", Y) ;
WriteLn ('el valor mxi mo es ', Maxi mo( X, Y)) ;
end.
El programa Prueba utiliza la unidad Demo 1 y, en consecuencia, puede disponer
del procedimiento In t ercambi o y la funcin Maximo.
EJEMPLO 2.2
Construccin de una unidad con un procedimiento Intercambio y una funcin Potencia
o Exponenciacin (xn; x: real, n: entero).
unit Ca l cu lo;
interface {seccin de int erfaz}
procedure Intercambio (var X, Y : integer) ;
{intercambia los va l o res de X e Y}
function Potenc i a (X : real ; n : i nt eger) : real;
{devue l ve X a l a potencia n -esi ma }
implementation {sec cin de imp leme nt a cin}
procedure Inter cambio (var X, Y : integer) ;
var
Aux
begin
Aux
X
Y
end;
: Integer;
:= X;
:= Y;
:= Aux
( Intercambio )
function Potencia (X : real; n : i n teger) : rea l ;
var
I : integer;
Pr oducto: real;
begin (Po tenc i a)
Producto : = 1;
for I := 1 to n do
Producto : = Produ cto * X;
,
Potencia : = Pr oduc to
end; {Potencia}
end. {Clcul o}
El procedimiento Intercambio y la funcin Potencia de la seccin de imple-
mentacin pueden ser definidos de un modo abreviado.
Construccin de grandes programas: mdulos versus unidades 61
procedure I n tercambio ;
function
Sin embargo, el mtodo abreviado para declarar no es un estilo muy recomendado.
Reglas de compilacin
Una unidad se compila tal como se compila un programa completo. La compilacin
se realiza en memoria. Sin embargo, antes que la unidad pueda ser utilizada por un , .
programa o por otra unidad, debe ser compilado en disco. Normalmente el archivo
que contiene una unidad debe tener el mismo nombre que la unidad.
2.3.1. Construccin de grandes programas
La caracterstica de compilacin independiente de las unidades facilita considerable-
mente la programacin modular. Un programa grande se divide en unidades que agrupan
procedimientos y funciones afines. As, un programa puede ser dividido en diferentes
mdulos o unidades: A, B, e y D, Y la estructura del programa podra ser sta:
program Prueba;
uses
Do s , Cr t , Pr int er ,
A, B, e , D;
{declaraci o nes de procedimientos y funcione s de l progr ama}
begin {programa principa l}
end.
La compilacin independiente de las unidades permite tambin superar el tamao del
cdigo fuente de un programa de 64 K que viene limitado por el tamao de un segmento
del microprocesador 8086 (64 K); esta caracterstica significa que el programa principal
y cualquier segmento dado no pueden exceder un tamao de 64 K.
Turbo Borland Pascal manipula las unidades de forma que el lmite superior de alma-
cenamiento ocupado por un programa puede llegar al lmite mximo de memoria que puede
soportar la mquina y el sistema operativo: 640 K en la mayora de los Pe. Sin la
posibilidad de construccin de unidades, de Turbo Borland Pascal 4.0 y 5.0, los progra-
mas estn limitados a 64 K.
,

Turbo 80rtand diferencia unidades de programas por las palabras reservadas con
las que comienzan y acta de acuerdo con ellas.
2.3.2. Uso de unidades
Las unidades creadas por el usuario se almacenan con la extensin T PU, mientras que las
,
unidades estndar se almacenan en un archivo especial (TURBO. TPL) Y se cargan autom-
ticamente en memoria junto con el propio Turbo Borland Pascal.
62 Estructura de datos
El uso de una unidad o diferentes unidades aade muy poco tiempo (normalmente
menos de un segundo) al tiempo de compilacin de su programa. Si las unidades estn
cargadas en un archivo de disco independiente, se pueden necesitar unos segundos para
leerlas del disco.
Un programa puede utilizar ms de una unidad. En este caso todas las unidades se
listan en la sentencia uses, separadas por comas, como en el siguiente ejemplo:
program Prueba;
uses Ob j etos , Unidad2;
Slo las unidades realmente utilizadas en el programa necesitan ser listadas. Si Un i -
dad2 utiliza una unidad llamada ObViej os, pero el programa no incluye una llamada
a algo definido en ObViej os, no es necesario listar ObViej os en la sentencia uses .
Las unidades pueden ser listadas en cualquier orden. Aunque no exigible, una buena
regla a seguir es listar cada unidad antes de todas aquellas que la utilicen. As, por
ejemplo, si Unidad2 utiliza Obj etos, es buena prctica listar Obj etos antes que
Unidad2.
Si una unidad utiliza otra unidad, debe contener una clusula u s e s. Por ejemplo,
continuemos suponiendo que Unidad2 utiliza las dos unidades Obj etos y ObViej os,
entonces Un i dad2 debe incluir una clusula u s e s que indique al compilador su uso.
La clusula uses (si se necesita) se incluye normalmente en la seccin de int er f ace.
unit Unidad2 ;
interface
uses ObViejos, Objet os ;
2.3.3. Declaraciones/informacin pblica y privada
La seccin de interface no est limitada a contener slo procedimientos y cabeceras.
Puede contener declaraciones de tipos, constantes u otras clases.
Todos los objetos declarados en la seccin de interface es informacin pblica y
puede ser referenciada en cualquier programa (o unidad) que utilice la unidad. La infor-
macin que se desea ocultar del programa principal debe ser situada en la seccin de
implementacin.
Adems de los procedimientos y funciones cuyas cabeceras aparecen en la seccin
de interface de una unidad, sta puede tener tambin otros procedimientos, funciones,
constantes y/o otras declaraciones. Estas declaraciones se llaman, con frecuencia, decla-
raciones privadas. Son locales a la unidad y no se pueden ver referenciadas por cual-
quier programa (u otra unidad) que utilice la unidad. Por ejemplo, si un programa utiliza
la unidad Financa, puede utilizar el procedimiento Uno, el procedimiento Dos y la
constante Tasa. Sin embargo, no puede referenciar la constante Banda o la funcin
Conversin que aparece en la seccin de implementacin. Banda y Conversin
son locales a la unidad Financ a. Pueden ser utilizadas en la unidad Financa, pero
no tienen significado fuera de esa unidad .


Construccin de grandes programas: mdulos versus unidades 63
unit Fi n anc a;
{dec lar a procedimiento pa ra conve rt ir capit ales}
interface
const
Ta sa = 4. 25 ;
procedure Uno (Cap it al : r ea l) ;
procedure Dos(Cap it al : rea l ) ;
implementation
const
Banda = '*';
function Convers i o n (Capi ta 1 : rea 1 ) : r ea 1 ;
var
Fa ctorConvers i o n : integer;
Ca n tidadPagar : real ;
begin
FactorConvers i o n : = 65;
Ca n tidadPagar
Convers ion
end;
: = Capi t al * Fac torConve rs i on ;
: = CantidadPagar
procedure Uno (Capi ta l : r eal ) ;
begin
Writ e ( 'el inters es i gual a
WriteLn (Cap i ta l * 4. 2 5)
end;
procedure Do s (Capi tal : rea l) ;
. , ) .
. ,
begin
WriteLn (' e l inter s es i gua l a :',
end;
end. {fin de Financ a}
Cap it a l * 6) ;
La seccin de interface de una unidad es la seccin pblica y la seccin de imple-
mentacin es la seccin privada.
Un programa que utilice la unidad puede referenciar cualquier cosa de la parte pblica
(interface), pero no puede referenciar nada en la parte de implementacin. Este proceso
de ocultacin de la informacin es muy til en el diseo de grandes programas.
2.3.4. Clusula uses en la seccin de implementacin
En las versiones a partir de la 5.0 una clusula us es se puede situar en la seccin de
implementacin. Esta propiedad permite ocultacin adicional de la informacin. Por ejem-
plo, supngase que la unidad P utiliza la unidad Q. Esta clusula uses puede ser situa-
da en la seccin de interface o en la seccin de implementacin. Si la clusula uses se
utiliza en la seccin de implementacin, entonces las declaraciones dadas en la unidad Q
slo pueden situarse en la seccin de implementacin de la unidad P. Ellas no pueden
situarse en la seccin interface de la unidad P.
Cuando se utiliza una clusula uses en la seccin de imp.lementacin, se sita in-
mediatamente despus de la palabra reservada imp l e mentation.

64 Estructura de datos
unit P;
interface
uses A, B, C;

implementation
uses Q;
2.3.4.1. Uso circular de unidades
La versin 5.0 permite el uso circular de unidades. Es posible a la unidad P utilizar la
unidad Q y a la unidad Q utilizar la unidad P: se pueden construir unidades mutuamente
dependientes. En ambos casos la clusula uses se debe situar en la seccin de implemen-
. ,
taclOn.
Si se escriben unidades con referencia circular, se debe utilizar la orden Make del
men Compile en lugar de la orden Compile.
La orden Ka.ke gestiona las unidades, compilando
!..1_..1_ ".1;-
unlWlUl;;S nece ..... ",,"
2.3
El programa circular utiliza una unidad denominada Visualiz, que incorpora un procedi-
miento denominado EscribirEnPosicionXY, que a su vez se llama a otro procedimiento
denominado VerError que pertenece a una unidad denominada Errores, que contiene
una llamada a la unidad Visualizar.
program Circular;
{visualizar texto utilizando EscribirEnPosicionXY}
uses
Crt, Visualiz;
begin
ClrScr; {limpieza de la pantalla}
EscribirEnPosicionXY (1, 1, 'Test');
EscribirEnPosicionXY (90, 90,' Fuera de pantalla');
EscribirEnPosicionXY (10, 2, 'Retorno a pantalla')
end.
El procedimiento EscribirEnPosicionXY tiene tres parmetros; x, y, men-
saj e. x, y, coordenadas del punto en la pantalla de texto (de 25 x 80); mensaje, frase
a visualizar en la posicin (x, y).
Si las coordenadas (x, y) son vlidas, es decir, 1 <= x <= 80, Y 1 <= Y < 25 se escribe
el mensaje en la pantalla; si x e y no son vlidos (la posicin queda fuera de la pantalla),
se visualiza un mensaje de error. .

,
)
,
1
Construccin de grandes programas: mdulos versus unidades 65
unit Vi suali z;
interface

procedure Escribi r Enpos i cionXY (X,Y :integer; Me n sa j e :string) ;
implementation
uses Crt, Error ;
procedure Es cribirEnPosi cionXY (X ,Y:integer ; Men saje: string);
begin
if (X in [ 1 .. 80 ] ) and (Y in [1 .. 25])
then
end
end.
begin
GotoXY (X , Y, ) ;
Wr it e (Mensaje)
end
else
VerEr r or ( ' Coordenadas XY fue r a de rango ' )
El procedimiento VerError visualiza el mensaje' Error Fatal' en la lnea
25 de la pantalla.
unit Error;
interface
procedure VerEr r o r (Cadena : string)
implementation
uses Vis ual i z ;
procedure Ver Err or (Caden a : str i ng)
begin
Esc ri b i rEnPosicionXY ( 1, 25 , cadena)
end;
end.
Como habr observado en la clusula uses de las secciones de implementacin,
existen referencias mutuas (llamadas recprocas) de las unidades posibles porque Turbo
Borland Pascal puede compilar ambas secciones de interface completas.
"" ' . ~
.y ,"

la otra
L 1 ..
.

-.c_ < __ ,.
', :'.
, >"".
. - - .. ..
. . , .. c
"! " ,
, ,
2.4. UTILlZACION DE UNIDAD ESTANDAR
El archivo TURBO. T PL, que contiene todas las unidades estndar, se carga en memoria
central a la vez que el propio compilador y est disponible en cualquier momento, con
la ayuda de la clusula uses.
Un programa debe contener la clusula uses, situada inmediatamente despus de la
cabecera, cuando utiliza objetos declarados en una unidad.



66 Estructura de datos
program Test ;
uses
Crt, Proceso;
const
Mayor = 1 00 ;
type
Pal abra - string [ 2] ;
var
Expresion : rea l;



Recordemos que las unidades estndar son:
Syst em Ove rl ay Do s Crt Pr inter Gr a p h Graph3 Turbo3
En este captulo se har una breve introduccin a las diferentes unidades. Todas las
unidades contienen una serie de objetos que estn declarados en la seccin de interface
(constantes, variables, tipos, procedimientos y funciones) y que son exportables o visua-
lizables desde cualquier programa o unidad que utilice dichas unidades.
2.4.1. Unidad System
Esta unidad contiene todos los procedimientos y funciones estndar de Turbo Borland
Pascal relativas a entradas/salidas, cadena de caracteres, clculos en coma flotante, ges-
tin de memoria, etc.
La unidad S y s t em tiene una configuracin especial, se enlaza automticamente en
la compilacin de cada programa y no precisa ser referenciada por la clusula uses
system.
2.4.2. Unidad Crt
Esta unidad proporciona un conjunto especfico de declaraciones para entrada y salida:
constantes, variables, procedimientos y funciones, que permiten el acceso al control de
los modos de pantalla, al teclado, a los colores, al posicionamiento del cursor, etc.
La mayora de los programas Turbo Borland Pascal que hacen uso de la pantalla para
representaciones de salida recurren a la unidad Crt. Algunos procedimientos tpicos son:
ClrSc r
KeyPressed
Sou nd
wi ndow
EJEMPLO 2.4
Borra la pantalla.
Detecta la pulsacin de una tecla.
Hace sonar el altavoz interno.
Define una ventana de texto en la pantalla.
El siguiente programa permite comprobar la velocidad de presentacin de los caracte-
res en la pantalla, creando una ventana de JO. 000 caracteres aleatorios que se repiten
tres veces.

I
, ;
Construccin de grandes programas: mdulos versus unidades 69
Desplazamiento de objetos grficos.
Trazado de figuras geomtricas e histogramas.
2.5. SITUACiN DE LAS UNIDADES EN SUS DISCOS:
DNDE BUSCA TURBO BORLAND PASCAL
LAS UNIDADES?
Las unidades existen fisicamente en una de las dos formas siguientes: como archivo indepen-
diente con su nombre y una extensin TPU (Turbo Borland Pascal Uni t), o como
parte de un archivo llamado TURBO. TPL. Pueden existir muchos archivos con extensin
TPU, pero slo puede haber un archivo. TPL (Turbo Borland Pascal Library).
TURBO. TPL se carga en la memoria de la computadora siempre que se arranca el
programa TURBO Borland Pascal, de modo que todas las unidades predefinidas,
tales como Crt, Dos, etc., estn siempre disponibles. No importa cul sea la unidad de
disco activa o en qu directorio est situado, su programa puede utilizar cualquiera
de estas unidades y el programa TURBO encontrar la unidad. Si se conoce de antemano
que algunas de las unidades residentes en TURBO. TPL no se van a utilizar, se pueden
eliminar con la utilidad llamada TPUMOVER. EXE. Esta operacin har ms pequea
TURBO. TPL Y permitir que la memoria sea utilizada para otras cosas; es decir, se pue-
den aadir las unidades del usuario al archivo TURBO. TPL.
Las unidades que disea el programador, el sistema TURBO espera encontrarlas en el
directorio activo de la unidad de disco activa. Esto significa que si tiene una unidad con pro-
cedimientos que utiliza con frecuencia, deber transferir la unidad cada vez que cambia el
directorio, o en caso contrario perder el acceso a esa unidad cuando no est en el directorio
activo. Es preciso indicar entonces al sistema TURBO en qu directorio estn las unidades.
Desgraciadamente no se puede situar un especificador de unidad o de camino en la
sentencia uses. Las sentencias siguientes no son vlidas:
uses Crt, Dos, C:\UnidadesUsuario;
uses Crt, C:\Prueba\UnidadesUsuario;
Algunos mtodos para indicar al sistema TURBO en qu directorio estn las unida-
des son:
Si los archivos de su unidad estn en el directorio actual (por ejemplo, e: \ Prac-
ticas) y el compilador est en e: \TURBO, se puede invocar el compilador
desde e : \ P r a c tic a s, el compilador las encontrar.
Supongamos que estn todas las unidades del usuario en el directorio Pruebas en
la unidad de disco B y se desea indicar al sistema que busque siempre all para
encontrar las unidades. Las operaciones a realizar son:
1. Activar el men Options.
2. Elegir la orden Directories de ese men. Se produce una lista con los
tipos de directorios que se pueden especificar.
,
70 Estructura de datos
3. Elegir de esa lista Unit Directories y aparecer una ventana en la pan-
talla. Teclee B:\Pruebas y, tras pulsar RETURN, aparece:
Unit Dir ector ies
B: \ Pruebas
El sistema ya est preparado para buscar en ese directorio las unidades que
haya escrito. Cuando se encuentra una clusula uses, el sistema busca la unidad
en TURBO. TPL, si no la encuentra, busca en el directorio activo de la unidad de
disco activa. Si no se encuentra en ninguna de esas posiciones, entonces busca en
el directorio que se referenci como Uni t Directories, es decir, en el ejemplo
Pruebas, en la unidad B. En caso negativo el sistema produce un error.
Se pueden utilizar directorios mltiples. En este caso se pueden listar todos los
directorios separados por puntos y comas:
unit directories:B: \ Pr a c ti c as; B: \ Pruebas; C: \ De moUno
En esta ocasin TURBO busca, como siempre, en TURBO. TPL Y a continuacin
en el directorio activo para encontrar una unidad. Si no tiene xito la bsqueda, se
busca en el directorio Practicas de la unidad B. Si no existe ninguna unidad,
entonces se busca en Pruebas de la unidad B. Si tampoco tiene xito en la bs-
queda, entonces se busca en el directorio DemoUno de la unidad c. Si tampoco
tiene xito la bsqueda, se producir un mensaje de error.
La directiva $U prioridad sobre unidades del directorio actual o de los
directorios especificados en el men Opt ions, de modo que si tiene una unidad
idntica en su directorio actual, $U permite seleccionar una unidad del mismo
nombre almacenada en cualquier parte de su disco.
TURBO supone que el nombre de la unidad y el nombre del archivo que con-
tiene a la unidad son idnticos (por ejemplo, unidad Demo y archivos Demo. Pas
y Demo . TPU).
Reglas de funcionamiento
, " < - ,-, - :,-,,_ ,:;-' - .. '----:----. ::-.,-.--,:" _; '_ -- ;-.-.-----, ' - . - -'- '-- , '- ,-'l-
, '" Cuando aparece"tiri qomnre' d undatt"'ell' uilll"directiva .esta
unidad (ldll)' , (. ' ' '< ;.; ',
'" , ., _ _ .. . -.. -" _--. ', .. ,,"' , ,,::" : ,,.,, :",- '._ .,' l' ," .. ' . ' ;',', ,,':' ,
1. ' Entre las unid.des la biblioteca TURBO. TPL.
2. En o el directorio actual; "o' 'c o , .o, L, ,; , i , '
3. Los,ditectoris' citads -l menOpt iorts: ! ' "
",' , , ;
- --, .
-

. "'" """ , , _ - V. ' ->_-:-
y > , "
.-, ., .
---------------------------------------------------------------------------------------
Construccin de grandes programas: mdulos versus unidades 71
El programa TPUMOVER
Las unidades estndar residen en la biblioteca TURBO. TPL Y se cargan automtica-
mente cuando arranca Turbo Borland Pascal. Al objeto de ahorrar memoria se pueden
transferir unidades poco utilizadas, tales como Turbo3 y Graph, fuera del archivo
TURBO. TPL, mediante la utilidad TPUMOVER. En otras palabras, esta utilidad se pue-
de utilizar para aadir o borrar desde TURBO. TPL.
2.6. IDENTIFICADORES IDNTICOS EN DIFERENTES UNIDADES
Es vlido tener identificadores idnticos dentro de dos unidades y utilizar ambas unida-
des en el mismo programa. Es decir, es posible tener una unidad llamada Pan t a 1 1 a
que contenga un procedimiento denominado ClrScr, de igual nombre que el procedi-
miento, ya conocido, de borrado de la pantalla de la unidad estndar Crt.
uses DOS , Crt, Pant alla;
En este caso se dispondra de dos procedimientos ClrScr. Cul utilizar? Turbo
Borland Pascal utiliza el ltimo procedimiento ClrScr que se encuentra al explorar las
unidades en la sentencia uses. En este ejemplo explora primero Crt y luego Pantalla,
y por consiguiente, se emplea el procedimiento ClrScr escrito por el usuario. Si se
intercambian los nombres de las unidades
uses DOS , Pan talla, Crt ;
el compilador utilizar ahora el procedimiento estndar ClrScr.
Un sistema de diferenciar los identificadores idnticos es utilizar el identificador de
la unidad y un punto.
program Pruebas ;
uses
Dos , Crt, Pantall a ;
begin
Crt. ClrScr ; {l i mp ieza de l a pantalla de t exto)
ClrScr; {li mp ieza de c u a l q u ier otra pantall a de texto)

end.
Con este mtodo es posible referenciar y diferenciar identificadores idnticos en
unidades diferentes. En el caso de que ningn nombre de unidad preceda al identificador
o referencia, se asigna la ltima unidad encontrada en la exploracin de unidades en la
sentencia uses.
,
2.7. SINTESIS DE UNIDADES
Una vez visualizadas todas las caractersticas de las unidades, vamos a realizar una sn-
tesis de las mismas al objeto de que el lector pueda asimilar totalmente y comenzar a
modularizar sus programas con la mxima eficiencia a partir de ese momento.
i
,
,
J
,
,
J
,
I
I
72 Estructura de datos
, , " ._" ,
. ,',' -' - -
-, .- , > ,
,
;:.
Un programapuede disponer d.econstantes, definiciones, de tiposy subprogr:amas
,tma dl 'fa, cbecra de ul1 pro-
" ' _ : .::: ............ .... '.i ' ," ' _: . . . ,, -" .:' ; t ., -! . OA . .. . ,
grama . .. ,' '" ,,',,"",">'" ':';' "':"''':':--:'' . . ,'. .. ...., ' "" ' ':, "' ,
- " : . . . ':":",',"':',;:.':" ,': . . :< - <;;:'::; ': :;',:' '" ,: . . ,
2.7.1. Estructura de una unidad
Una unidad es un mdulo. No es un programa ejecutable. Existen unidades estndar
(por ejemplo, Crt; si desea acceder a procedimientos de esa unidad como e l r S e r,
W i ndow, debe incluir mediante una clusula uses la unidad e r t: uses e r t) Y unidades
creadas por el usuario.
Una unidad tiene una estructura ya conocida que contiene una cabecera, una parte
interface, una parte implementation y, evidentemente, una parte de iniciacin.
Los identificadores que aparecen en la seccin de interface son visibles desde cual-
quier programa que utiliza la unidad, pero los detalles de su estructura interna slo se
pueden conocer en la seccin de implementacin.
Desde el punto de vista profesional, usted puede proteger su cdigo fuente, distribu-
yendo en la documentacin del programa slo la seccin de interface y reservndose los
algoritmos y el cdigo fuente de la seccin de implementacin.
La cabecera de los procedimientos y funciones declaradas en la seccin de interface
debe ser idntica a la cabecera de las mismas funciones definidas en la seccin de imple-
mentacin; sin embargo, es posible escribir la cabecera en forma abreviada en la seccin
de implementacin. Los dos modelos de la unidad Ba s e que siguen despus en los mo-
delos son correctos y equivalentes.
unit <identi f icador >; {cabecera obli gator i a}
{e l identif i cado r se u t il i za como n ombre del archivo
de l a u n idad ya compi l ada; l a e x ten s i n es .TPU}
interface
uses <li s t a de u ni dades > {op cional}
{dec l a r aciones pbl icas o visibles son opc i on a l es}
cons t .... .
type ..... .
var ..... .
procedure ... {sl o cabecera}
function ... {slo cabecera}
implementation
{dec l a r acion es privad as : l ocales a l a u n i d a d }
uses <li s t a de unida des >
const ... .
type .... .
var .....
Construccin de grandes programas: mdulos versus unidades 73
procedure .... {cabecer a y c u erpo de l procedimien to}
furiction .... {cabecera y cue r po de la func i n }
[begin {se l ecc i n de i ni c ial izacin : opc i onal}



endo
Modelo 1
unit Base ;
interface
uses
Crt ;
{obligatoria , fin de i mp l ement acin }
procedure Mens aje (Texto : string);
implementation
procedure Mensaj e ;
begin
ClrScr ;
GotoXY ((80 - Lengt h (Texto)) div 2 , 4 ) ;
Wr i te (Text o )
end;
begin
o o o
endo
Modelo 2
unit Base ;
interface
uses
Crt ;
procedure Me n saje (Text o : string );
implementation
procedure Men saje (Text o: string ) ;;
begin
Cl rScr ;
GotoXY ((80 - Length (Texto)) div 2 , 4) ;
Write (Text o)
end;
begin
. . ...
endo
2.7.2. Excepciones en la escritura de unidades
Al escribir unidades debe tener en cuenta estas limitaciones:
La declaracin forward de los subprogramas no est permitida (no es necesa-
ria) en una unidad . .
,
,
,
,
,

:
,
l,
74 Estructura de datos
Si un subprograma se declara como inline, su definicin de cdigo debe apa-
recer en la seccin de interface y el identificador del subprograma no debe apare-
cer en la seccin implementacin.
Si un subprograma es declarado external, su identificador no debe aparecer
en la seccin implementation.
2.7.3. Compilacin de unidades
La compilacin de una unidad se efecta del mismo modo que la compilacin de un
programa, con la diferencia de que al compilar el programa se obtiene un archivo aut-
nomo ejecutable (. EXE) y al compilar una unidad se obtiene un archivo en cdigo obje-
to (no ejecutable) como resultado, con extensin .TPU (Turbo Borland Pascal
Uni t), aunque con el mismo nombre que el archivo de cdigo fuente. Este cdigo obje-
to de un archivo. TPU slo es enlazable (linkable) por el compilador de Turbo BorIand
Pascal y no es compatible con archivos OBJ creados por otros compiladores.
Para crear unidades que pueda automticamente recompilar con las opciones Make
y Bui ld de Turbo BorIand Pascal se deben seguir estas reglas:
El identificador de unidad (especificado) en la cabecera debe ser el mismo que el
nombre del archivo fuente (sin incluir la extensin . PAS).
El nombre del archivo fuente debe tener una extensin (. PAS).
El archivo. TPU debe estar en el directorio actual o en un directorio especificado
con las opciones Options/Directories/Unit directories. El cdigo del
programa fuente debe estar en el directorio actual.
2.8. OTROS MTODOS DE ESTRUCTURAR PROGRAMAS:
rNCLUSIN, SOLAPAMIENTOS y ENCADENAMIENTO
Adems de las unidades, existen dos mtodos para estructurar o construir grandes pro-
gramas a partir de Turbo Borland Pascal 5.0: los archivos de inclusin (inelude) y los
solapamientos (overlays). Aunque es necesario hacer constar que si bien en las versio-
nes 3.0 y anteriores eran imprescindibles, su utilidad ha decado en 5.0, 6.0 Y 7.0 en
beneficio de las unidades.
2.8.1. Los archivos de inclusin o incluidos (include)
Como ya conoce el lector, la directiva Incluir Archivos (include) ($I) permite incluir
cdigo fuente en el programa que est en memoria, a partir de archivos externos de dis-
cos. El cdigo del programa ejecutable acta como si el cdigo incluido estuviera fsica-
mente presente en el archivo que se est compilando.
La directiva $I<nombrearchivo> permite incluir el archivo denominado
,
<nombrearchi vo> durante la compilacin. Este es un mtodo para dividir su cdi-
go fuente en segmentos ms pequeos. Cuando el compilador encuentra la directiva
Construccin de grandes programas: mdulos versus unidades 75
$I<nombrearchi vo>, abre el archivo del disco <nombrearchi vo> y comienza
a compilarlo. El archivo <nombrearchi vo> no se lee realmente en memoria como
un todo; el compilador lee simplemente lnea a lnea, compila la lnea a cdigo mquina
y a continuacin lee la siguiente lnea .

Utilizar hIclusin, para bibliQtecas de ..


... ... .. ... ..... .. . .. ,,,,,,' .... " ,.", '. .. ...... , .......... , ,'"
El uso actual de ls archivos de inclusin se suele reducir a archivos que contienen
procedimientos o funciones sencillas; o incluso la definicin de uno o ms tipos de da-
tos; como ejemplos tpicos: procedimientos o funciones de bsqueda, ordenacin, etc.
2.8.2. Los solapamientos (overlays)
Si se desarrollan grandes aplicaciones que deban correr sobre sistemas con recursos de
memoria limitados (640 K o menos), la tcnica de solapamientos es indispensable.
Los solapamientos (overlays) son partes de un programa que comparten una zona
de memoria comn. Slo las partes del programa que se requieren para una funcin dada
residen en memoria al mismo tiempo; se cargan (sobreescriben) una sobre otra durante
la ejecucin. Los solapamientos pueden reducir significativamente los requisitos totales
de memoria de un programa en tiempo de ejecucin. De hecho, con solapamientos se
pueden ejecutar programas que son mucho ms grandes que la memoria total disponible,
ya que slo partes del programa residen en memoria en un instante dado.
La idea bsica del solapamiento es sta: se divide un programa en partes y se prepara
de modo que diferentes partes compartan el mismo lugar en memoria. Cuando el progra-
ma principal comienza la ejecucin, un solapamiento (segmento de programa) se carga
en una zona libre (sial) de la memoria. Cuando se requiere el segundo solapamiento, se
carga en memoria en la misma zona que el primer solapamiento, superponiendo el pri-
mer solapamiento. Posteriormente, cuando un tercero, cuarto o quinto solapamiento se
requieren, simplemente se cargan en la parte superior de cualquier solapamiento que
hubiese ocupado anteriormente la zona del solapamiento. De este modo, se pueden ma-
nejar megabytes de cdigo que pueden correr sobre memorias de 640 K, 256 K o incluso
menos. Simplemente necesita dividir esos megabytes de cdigo en un nmero suficiente
de solapamientos.
2.8.2.1. Gestin de los solapamientos
El sistema de solapamientos de la versin 7.0 y anteriores est basado en unidades. La
gestin de los mismos se realiza a nivel de unidad; sta es la parte ms pequea de un
programa que se puede hacer en un solapamiento. Cualquier nmero de unidades puede
ser especificado como solapamiento, lo que significa que cada uno ocupar la misma
regin de memoria cuando se cargan.
Todas las unidades especificadas como solapamientos (overlays) se enlazan en un
archivo independiente, con el mismo nombre que el programa principal, pero con una
i
I
,

,


r
f

I
,
76 Estructura de datos
extensin .OVR. En otras palabras, si un programa con solapamientos MI PROG . PAS
se compila, Turbo Borland Pascal genera un archivo de solapamiento (MI PROG . OVR) y
un archivo ejecutable (MI PROG . EXE). El archivo . EXE contiene las partes estticas
(no recubiertas) del programa y el archivo. OVR contiene todas las unidades de solapa-
miento que se intercambiarn en la memoria durante la ejecucin del programa.
Existe una sola zona de memoria para solapamientos, se denomina memoria inter-
media de solapamiento (overlay buffer), que reside en memoria entre el segmento de la
pila (stack) y el segmento para variables dinmicas (heap). Inicialmente el tamao de la
memoria intermedia de solapamiento se hace tan grande como sea necesaria, de modo
que puede contener la unidad de solapamiento ms grande; posteriormente puede incre-
mentarse su tamao, si as se desea. Si no existe bastante memoria disponible cuando se
carga la unidad, se visualizarn mensajes de error:
Program too big to fit in memory
Not enough memory to rum program
El gestionador de solapamientos tiene la posibilidad de cargar el archivo recubierto
en memoria ampliada o expandida (EMS) cuando exista espacio disponible suficiente.
Si la librera en tiempo de ejecucin detecta memoria EMS (Expanded Memory Specifi-
cation) libre, el archivo de solapamiento se sita en la memoria EMS RAM.
La Figura 2.2. muestra el sistema de funcionamiento de los solapamientos.
2.8.3. La unidad Overlay (generacin de solapamientos)
Turbo Borland Pascal proporciona un gestionador de archivos que manipulan acceso a
solapamientos en una unidad llamada Overlay. Si se trata de utilizar solapamientos,
se debe incluir Overlay en su sentencia Uses, antes de todas las unidades a recubrir.
Para disear programas con solapamientos se deben seguir las siguientes reglas:
1. Una unidad especificada como solapamiento debe ser compilada con la directiva
$0. Esta directiva define una unidad como un solapamiento.
La directiva $0 tiene dos formatos: un formato de tipo conmutador y un
formato de parmetro .
formato conmutador {$O+}
{$O-}
formato parmetro {$Oparmetro}
$0+ situada en la unidad del archivo fuente, se activa su uso como
un solapamiento, pero no se requiere su uso como solapamien-
to; puede ser enlazada, todava, normalmente si se desea.
$0 Xmodem indica al programa principal que la unidad llamada Xmodem se
trate como un solapamiento.
Las. directivas
Construccin de grandes programas: mdulos versus unidades 77
program Mortime r;
{$ F+ }
uses overlay, Dos , Crt, Circu l os , Xmodem, Kermit, Parser;
( SO Xmodem)
{SO Kermit}
{SO Parser }
2. En el ejemplo anterior se observa la directiva $F+. La razn es que todas las
unidades utilizadas por el programa, as como el propio programa, deben ser
compiladas con la directiva Far Calla activada ({$F+}). Por esta causa,
$F+ se sita inmediatamente despus de la sentencia programo
3. Inicializar el gestionador (manipulador) de solapamientos. El cdigo de inicia-
cin se debe situar antes de la primera llamada a una rutina de solapamiento, y
en particular al principio de la parte de sentencias del programa. La llamada se
realiza con Ov r I n i t, cuyo formato es Ovr I ni t (nambrearchi va).

MIPROG . EXE
Heap
fondo
overlay buffer (debe ser
tan grande como el
mayor solapamiento

cima
Stack
Memoria principal
(DOS)
Unit Tee;
Unit Tie;
Unit Toe;
Unit Tum;
Unit Tea;
Unit Tir;
Unit Tas;
Memoria EMS
(si existe)
Figura 2.2. Archivos y memorias de solapamiento.
Ejemplo
begin
Ov rI n i ti ' MIPROG . OVR' )
end;
MIPROG . OVR
Unit Tee;
Unit Tie;
Unit Toe;
Unit Tum;
Unit Tea;
Unit Tir;

Unit Tas;
Almacenamiento
en disco (DOS)
,
,
,
, ' " , " . A-" ,,". ,," _ . . ~ , . , , ' ~ ~ , ' ~ ' ' ' _ __ ' ____________________ _
o.. _
78 Estructura de datos
2.8.3.1. Constantes y variables de la unidad Overlay
const
Ov r Ok
- o;
-
Ov rEr r o r
-
- 1 ;
-
OvrNot Found - -2; -
Ovr NoMemory - - 3 ;
-
Ovr loError - - 4 i -
OvrNo EMSDri ve r - - 5 ;
-
OvrNoEMSMemo r y - - 6 ;
-
var
Ovr Res ult : integer;
2.8.3.2. Procedimientos y funciones de la unidad Overlay
Procedimientos
Ov r l n it
OvrlnitEMS
Ovr Se t Buf
Ov r Cl e a r Buf
OvrClearBuf
Funciones
Ovr Ge tBuf
Este procedimiento permite borrar temporalmente la memoria intellnedia de solapamiento;
esta operacin se debe realizar cuando se necesite utilizar la memoria que ocupa.
OvrClearBuf
OvrGetBuf
Devuelve el tamao actual de la memoria inte/media de solapamiento, en VarLonglnt.
VarLonglnt:= OvrGetBuf
Ovrlnit
Inicializa el gestionador de solapamientos y abre el archivo de solapamiento.
Ovrlnit (nombrearchivo)
OvrlnitEMS
Verifica que existe un controlador EMS y suficiente memoria EMS para contener el
archivo de solapamiento.
OvrlnitEMS
,
--------------------------
Construccin de grandes programas: mdulos versus unidades 79
OvrSetBuf
Establece el tamao de la memoria intermedia de solapamiento (o ver/ay buffer).
OvrSetBuf (VarLonglnt)
VarLonglnt variable de tipo /ongint
2.8.4. Encadenamiento de archivos compilados
Turbo Borland Pascal produce archivos. EXE en lugar de los archivos ms simples. COM
que producir la versin 3; por esta razn no puede soportar encadenamiento de progra-
mas con datos compartidos. Se puede utilizar el procedimiento Exec de Turbo Borland
Pascal 5, 6 Y 7 para transferir el control de un programa a otro, pero cada programa
tendr su propio segmento de datos.
RESUMEN
Una unidad es una coleccin de procedimientos y funciones de propsito general, guardadas en
disco de forma compilada. Las unidades se pueden utilizar para construir su propia librera de
procedimientos y funciones predefinidas. Esta librera puede ser utilizada en diferentes proyectos
y por diferentes equipos de programadores.
Las unidades refuerzan el concepto de abstraccin de datos. Esto se consigue situando los deta-
lles sobre procedimientos implementados en una unidad, y por consiguiente ocultando estos detalles.
Sintaxis de una unidad
unit <nombre>
interface
uses <lista de unidades utilizadas por esta unidad>
{s e omite si no se uti liza ninguna unidad}
<cabeceras de procedimientos y f unc i o nes >
<o tras declaraciones >
implementation
<declaraciones compl etas de procedimientos y funciones >
begin {no se necesita si n o existen sentencias de i nicializac i n}



end.
EJERCICIOS
2.1. Disear una unidad Lib 1 que defina las tres funciones siguientes, que puedan ser utilizadas
posteriormente por cualquier programa:
"
"
80 Estructura de datos
function Mn (Xl, X2 : integer) : integer;
{devuelve el elemento ms pequeo de Xl y X2}
function Mx (Xl,X2 : integer) : integer;
{devuelve el elemento mayor de Xl y X2}
function Media (Xl, X2 : integer): real;
{devuelve la media de Xl y X2}
Escribir un programa que haga uso de la unidad.

2.2. Construir una unidad que contenga las siguientes funciones estadsticas de un vector x de n
elementos.


Desviacin media (DM =
n
~
x-x
I
i = 1
donde x =
I es el valor absoluto
n
Media cuadrtica (MC) = #. L xl
1 = 1
Media armnica (MA) = ___ n-,----,--
n l
L x
. 1 I
1=
2.3. Escribir una unidad llamada Grados que incluya funciones para convertir grados sexagesi-
males y centesimales a radianes. Disear un programa que permita calcular los valores de
las funciones trigonomtricas seno, coseno y tangente de una tabla de valores angulares
dados en grados sexagesimales y centesimales (incremento del ngulo en la tabla, 1 grado).
2.4. Dadas dos matrices, A y B, donde
all a 12 al
n
b
ll
b
12
b
lm
a
21 a22 a2n
b
21
b
22
b
2m
A=

y B=

ami a
m
2
a
mn
b
ml
b
m2
b
mn
Disear una unidad que contenga los procedimientos o funciones: producto y suma de
A y B.
2.5. Disear una unidad que soporte las siguientes dos funciones de tiempo:
Fecha (convierte los parmetros numricos proporcionados por el procedimiento Ge t-
Date en una cadena con el formato DaSemana Da Mes Ao: ds DD MMAA).
Hora (convierte valores numricos proporcionados por el procedimiento Ge t Time en
una cadena de formato: 'hh mm ss').
Construccin de grandes programas: mdulos versus unidades 81
Nota
Y
,
o. , ' .
. ' ' , .
,
--.-
2.6. Escribir una unidad que manipule tipos de datos abstractos Enteros grandes (enteros de al
menos 2 dgitos). Debe proporcionar nmeros positivos y negativos, y las operaciones de
suma, resta, multiplicacin y divisin.
2.7. Escribir una unidad cuyos subprogramas bsicos deben ser:
Operacin traspuesta de una matriz.
Multiplicaciones de dos matrices cuadradas.
Suma de dos matrices cuadradas.
2.8. Crear una unidad que se componga de procedimientos y funciones que realicen las tareas
siguientes:
Hacer el cursor visible o invisible.
Emitir un sonido (pitido bip).
Borrar la parte de pantalla situada entre dos lneas.
Convertir las letras de una cadena de caracteres en maysculas.
Convertir un valor numrico en una cadena de caracteres.
Insertar caracteres.
2.9. Escribir una unidad que contenga los procedimientos de cambios de base de numeracin:
paso de base 2 a base 16, base 2 a base 1 O Y base 10 a base 2.
2.10. Escribir una unidad que contenga procedimientos y funciones que efecten las tareas si-
guientes:
Desplazar una cadena de caracteres en la pantalla, de izquierda a derecha o viceversa
y de velocidad ajustable.
Visualizar una ventana.
Mover el cursor por la pantalla.
2. 11. Escribir la unidad Prueba que contenga dos funciones para asegurar divisiones correc-
tas y evitar la divisin por cero, que produce un error irrecuperable en la ejecucin del
programa. Aplicacin prctica: Escribir un programa Demo Prueba que utilice las fun-
ciones creadas en la unidad Prueba.
2.12. Crear una unidad Aleatori que contenga tres funciones que proporcionen valores ge-
nerados aleatoriamente de tres tipos diferentes: enteros, cadenas y lgicos. Las funciones
a definir se denominan EnterasA, cadenasA. LagicasA.
EnterasA
CadenaA
LagicasA
Proporciona un entero comprendido en un intervalo de valores especfi-
cos Min y Max.
Enteros (Min y Max).
En t e ro sA ( 5 , 5 O) genera un entero aleatorio entre 5 y 50.
Proporciona una cadena de letras maysculas arbitrarias.
CadenaA (n) n, nmero de letras.
Proporciona un valor lgico aleatorio.
,
,
!
,
,
,
,
,
,
I
,
I
,

82 Estructura de datos
2. 13. Escribir un programa que visualice seis lneas que contengan cada una de ellas un entero
entre 300 y 400, una cadena de ocho letras y un valor true o false, todos ellos aleatorios.
325
346
37l
382
MNRPQANT
LOIVRSTN
MSPBVTRL
NZJMKSBC
true
false
true
false
343 FGRILTRP true
Nota: Utilice la unidad Aleatori.
2.14. El programa siguiente lee un archivo de entrada (programa fuente en Pascal) y lo convier-
te en otro archivo de salida (programa fuente en Pascal) con las palabras reservadas de
Turbo Borland Pascal en negritas y maysculas.
,
REFERENCIAS BIBLlOGRAFICAS
1. Borland: Reference Guide. Turbo Borland Pascal 5.0. Captulo 13.
Si desea trabajar con solapamientos, este captulo le complementar las ideas expuestas en la
seccin 2.8.
2. Dunteman, Jeff: Complete Turbo Borland Pascal. Third Edition. Scott Foreman, 1989.
Es una excelente obra para profundizar en Turbo Borland Pascal. Recomendada para usuarios
expertos y como ampliacin de conocimientos tras la lectura de esta obra.
3. Joyanes, Luis: Turbo/Borland Pascal 7. Iniciacin y Referencia, Madrid, McGraw-Hilll, 1997.
-
,
CAPITULO
. ,
stracclon

e atos: ti os a stractos

atos o etos

. , '.
CONTENIDO
3.1. El papel (el rol) de la abstraccin.
3.2. Un nuevo paradigma de programacin.
3.3. Modularidad.
3.4. Diseo de mdulos.
3.5. Tipos de datos.
3.6. Abstraccin en lenguajes de programacin.
3.7. Tipos abstractos de datos.

3.8. Tipos abstractos de datos en Turbo Borland Pascal.


3.9. Orientacin a objetos.
3.10. Reutilizacin de software.
3.11. Lenguajes de programacin orientados a objetos.
3.12. Desarrollo tradicional frente a orientado a objetos.
3.13. Beneficios de las tecnologas de objetos (TO).
RESUMEN.
EJERCICIOS.
En este captulo examinaremos los conceptos de modularidad y abs-
traccin de datos. La modularidad es la posibilidad de dividir una
aplicacin en piezas ms pequeas llamadas mdulos. Abstraccin de
datos es la tcnica de inventar nuevos tipos de datos que sean ms ade-
cuados a una aplicacin y, por consiguiente, facilitar la escritura del
programa. La tcnica de abstraccin de datos es una tcnica potente de
propsito general que cuando se utiliza adecuadamente, puede produ-
cir programas ms cortos, ms legibles y flexibles.
Los lenguajes de programacin soportan en sus compiladores tipos
de datos fundamentales o bsicos (predefinidos), tales como int, char
y float en e y C++, o bien integer, real o boolean en
Pascal. Algunos lenguajes de programacin tienen caractersticas que
permiten ampliar el lenguaje aadiendo sus propios tipos de datos.
83
84 Estructura de datos
Un tipo de dato definido por el programador se denomina tipo abs-
tracto de dato, TAD (abstract data type, ADT). El trmino abstracto se
refiere al medio en que un programador abstrae algunos conceptos de
programacin creando un nuevo tipo de dato.
La modularizacin de un programa utiliza la nocin de tipo abs-
tracto de dato (TAD) siempre que sea posible. Si el TAD soporta los
tipos que desea el usuario y el conjunto de operaciones sobre cada tipo,
se obtiene un nuevo tipo de dato denominado objeto .

3.1. EL PAPEL (EL ROL) DE LA ABSTRACCION
Los programadores han tenido que luchar con el problema de la complejidad durante
mucho tiempo desde el nacimiento de la informtica. Para comprender lo mejor posible
la importancia de las tcnicas orientadas a objetos, revisemos cules han sido los dife-
rentes mecanismos utilizados por los programadores para controlar la complejidad. En-
tre todos ellos se destaca la abstraccin. Como describe Wulft: Los humanos hemos
desarrollado una tcnica excepcionalmente potente para tratar la complejidad: abstraer-
nos de ella. Incapaces de dominar en su totalidad los objetos complejos, se ignora los
detalles no esenciales, tratando en su lugar con el modelo ideal del objeto y centrndo-
nos en el estudio de sus aspectos esenciales.
En esencia, la abstraccin es la capacidad para encapsular y aislar la informacin,
del diseo y ejecucin. En otro sentido, las tcnicas orientadas a objetos se ven como
resultado de una larga progresin histrica que comienza en los procedimientos y sigue
en los mdulos, tipos abstractos de datos y objetos.
3.1.1. La abstraccin como un proceso mental natural
Las personas normalmente comprenden el mundo construyendo modelos mentales de
partes del mismo, tratan de comprender cosas con las que pueden interactuar: un modelo
mental es una vista simplificada de cmo funciona de modo que se pueda interactuar
contra ella. En esencia, este proceso de construccin de modelos es lo mismo que el
diseo de software; aunque el desarrollo de software es nico, el diseo de software
produce el modelo que puede ser manipulado por una computadora.
Sin embargo, los modelos mentales deben ser ms sencillos que el sistema al cual
imitan, o en caso contrario sern intiles. Por ejemplo, consideremos un mapa como un
modelo de su territorio. A fin de ser til, el mapa debe ser ms sencillo que el territorio
que modela. Un mapa nos ayuda, ya que abstrae slo aquellas caractersticas del territo-
rio que deseamos modelar. Un mapa de carreteras modela cmo conducir mejor de una
posicin a otra. Un mapa topogrfico modela el contorno de un territorio, quizs para
planear un sistema de largos paseos o caminatas.
De igual forma que un mapa debe ser ms pequeo significativamente que su te-
rritorio e incluye slo informacin seleccionada cuidadosamente, as los modelos

Abstraccin de datos: tipos abstractos de datos y objetos 85
mentales abstraen esas caractersticas de un sistema requerido para nuestra compren-
sin, mientras ignoran caractersticas irrelevantes. Este proceso de abstraccin es psico-
lgicamente necesario y natural, la abstraccin es crucial para comprender este comple-
jo mundo.
La abstraccin es esencial para el funcionamiento de una mente humana normal, y es
una herramienta muy potente para tratar la complejidad. Considerar por ejemplo el ejer-
cicio mental de memorizar nmeros. Un total de nueve dgitos se puede memorizar con
ms o menos facilidad. Sin embargo, si se agrupan y se denominan nmeros de telfono,
los dgitos individuales se relegan en sus detalles de ms bajo nivel, crendose un nivel
abstracto y ms alto, en el que los nueve dgitos se organizan en una nica entidad (el
nmero de telfono). Utilizando este mecanismo, se pueden memorizar algunos nme-
ros de telfonos de modo que la agrupacin de diferentes entidades conceptuales es un
mecanismo potente al servicio de la abstraccin.
3.1.2. Historia de la abstraccin del software
La abstraccin es la clave para disear buen software. En los primeros das de la infor-
mtica, los programadores enviaban instrucciones binarias a una computadora, manipu-
lando directamente interrupciones en sus paneles frontales. Los nemotcnicos del len-
guaje ensamblador eran abstracciones diseadas para evitar que los programadores tuvieran
que recordar las secuencias de bits que componen las instrucciones de un programa. El
siguiente nivel de abstraccin se consigue agrupando instrucciones primitivas para for-
mar macroinstrucciones.
Por ejemplo, un conjunto se puede definir por abstraccin como una coleccin no
ordenada de elementos en el que no existen duplicados. Utilizando esta definicin, se
pueden especificar si sus elementos se almacenan en un array, una lista enlazada o cual-
quier otra estructura de datos. Un conjunto de instrucciones realizadas por un usuario se
pueden invocar por una macroinstruccin. Una macroinstruccin instruye a la mquina
para que realice muchas cosas. Tras los lenguajes de programacin ensambladores apa-
recieron los lenguajes de programacin de alto nivel, que supusieron un nuevo nivel de
abstraccin. Los lenguajes de programacin de alto nivel permitieron a los programado-
res distanciarse de las interioridades arquitectnicas especficas de una mquina dada.
Cada instruccin en un lenguaje de alto nivel puede invocar varias instrucciones mqui-

na, dependiendo de la mquina especfica donde se compila el programa. Esta abstrac-
cin permita a los programadores escribir software para propsito genrico, sin preocu-
parse sobre qu mquina corre el programa.
Secuencias de sentencias de lenguajes de alto nivel se pueden agrupar en procedi-
mientos y se invocan por una sentencia. La programacin estructurada alienta el uso de
abstracciones de control tales como bucles o sentencias if-then que se han incorporado
en lenguajes de alto nivel. Estas sentencias de control permitieron a los programadores
abstraer las condiciones comunes para cambiar la secuencia de ejecucin.
El proceso de abstraccin fue evolucionando desde la aparicin de los primeros len-
guajes de programacin. El mtodo ms idneo para controlar la complejidad fue au-
mentar los niveles de abstraccin. En esencia, la abstraccin supone la capacidad de

86 Estructura de datos
encapsular y aislar la informacin de diseo y ejecucin. En un determinado sentido, las
tcnicas orientadas a objetos pueden verse como un producto natural de una larga pro-
gresin histrica que va desde las estructuras de control, pasando por los procedimien-
tos, los mdulos, los tipos abstractos de datos y los objetos.
En las siguientes secciones describiremos los mecanismos de abstraccin que han
conducido al desarrollo profundo de los objetos: procedimientos, mdulos, tipos abs-
tractos de datos y objetos .

3.1.3. Procedimientos
Los procedimientos y funciones fueron uno de los primeros mecanismos de abstrac-
cin que se utilizaron ampliamente en lenguajes de programacin. Los procedimientos
permitan tareas que se ejecutaban rpidamente, o eran ejecutados slo con ligeras varia-
ciones, que se reunan en una entidad y se reutilizaban, en lugar de duplicar el cdigo
varias veces. Por otra parte, el procedimiento proporcion la primera posibilidad de ocul-
tacin de informacin. Un programador poda escribir un procedimiento o conjunto de
procedimientos, que se utilizaban por otros programadores. Estos otros programa-
dores no necesitaban conocer con exactitud los detalles de la implementacin, slo ne-
cesitaban el interfaz necesario. Sin embargo, los procedimientos no resolvan todos los
problemas. En particular, no era un mecanismo efectivo para ocultar la informacin y
para resolver el problema que se produca al trabajar mltiples programadores con nom-
bres idnticos.
Para ilustrar el problema, consideremos un programador que debe escribir un con-
junto de rutinas para implementar una pila. Siguiendo los criterios clsicos de diseo de
software, nuestro programador establece en primer lugar el interfaz visible a su trabajo,
es decir, cuatro rutinas: meter, sacar, pilavaca y pilallena. A continuacin implementa
los datos rutinas mediante arrays, listas enlazadas, etc. Naturalmente los datos conteni-
dos en la pila no se pueden hacer locales a cualquiera de las cuatro rutinas, ya que se
deben compartir por todos. Sin embargo, si las nicas elecciones posibles son variables
locales o globales, entonces la pila se debe mantener en variables globales; por el con-
trario, al ser las variables globales, no ,existe un mtodo para limitar la accesibilidad o
visibilidad de dichas variables. Por ejemplo, si la pila se representa en un array denomi-
nado datospila, este dato debe ser conocido por otros programadores, que puedan desear
crear variables utilizando el mismo nombre pero relativo a las referidas rutinas. De modo
similar las rutinas citadas estn reservadas y no se pueden utilizar en otras partes del
programa para otros propsitos. En Pascal existe el mbito local y global. Cualquier
mbito que permite acceso a los cuatro procedimientos debe permitir tambin el acceso
a sus datos comunes. Para resolver este problema, se ha desarrollado un mecanismo de
estructuracin diferente.

3.1.4. Mdulos
Un mdulo es una tcnica que proporciona la posibilidad de dividir sus datos y procedi-
mientos en una parte privada slo accesible dentro del mdulo y parte pblica

,
,


!
t
r
,
,
;
t
,
r

Abstraccin de datos: tipos abstractos de datos y objetos 87
-accesible fuera del mdulo . Los tipos, datos (variables) y procedimientos se pueden
definir en cualquier parte.
El criterio a seguir en la construccin de un mdulo es que si no se necesita algn
tipo de informacin, no se debe tener acceso a ella. Este criterio es la ocultacin de
informacin.
Los mdulos resuelven algunos problemas, pero no todos los problemas del desarro-
llo de software. Por ejemplo, los mdulos petmitirn a nuestros programadores ocultar
los detalles de la implementacin de su pila, pero qu sucede si otros usuarios desean
tener dos o ms pilas? Supongamos que un programador ha desarrollado un tipo de dato
e omp 1 e j o (representacin de un nmero complejo) y ha definido las operaciones arit-
mticas sobre nmeros 'complejos suma, resta, multiplicacin y divisin ; asimismo
ha definido rutinas para convertir nmeros convencionales a complejos. Se presenta un
problema: slo puede manipular un nmero complejo. El sistema de nmeros complejos
no ser til con esta restriccin, pero es la situacin en que se encuentra el programador
con mdulos simples.
Los mdulos proporcionan un mtodo efectivo de ocultacin de la informacin, pero
no permiten realizar instanciacin, que es la capacidad de hacer mltiples copias de las
zonas de datos.
3.1.5. Tipos abstractos de datos
Un tipo abstracto de datos (TAD) es un tipo de dato definido por el programador que se
puede manipular de un modo similar a los tipos de datos definidos por el sistema. Al
igual que los tipos definidos por el sistema, un tipo de dato abstracto corresponde a un
conjunto (puede ser de tamao indefinido) de valores legales de datos y un nmero de
operaciones primitivas que se pueden realizar sobre esos valores. Los usuarios pueden
crear variables con valores que estn en el rango de valores legales y pueden operar
sobre esos valores utilizando las operaciones definidas. Por ejemplo, en el caso de la
pila ya citada, se puede definir dicha pila como un tipo abstracto de datos y las operacio-
nes sobre la pila como las nicas operaciones legales que estn peIluitidas para ser rea-
. lizadas sobre instancias de la pila.
Los mdulos se utilizan frecuentemente como una tcnica de implementacin para
tipos abstractos de datos, y el tipo abstracto de datos es un concepto ms terico. Para
construir un tipo abstracto de datos se debe poder:
1. Exponer una definicin del tipo.
2. Hacer disponible un conjunto de operaciones que se pueden utilizar para mani-
pular instancias de ese tipo.
3. Proteger los datos asociados con el tipo de modo que slo se puede actuar sobre
ellas con las rutinas proporcionadas.
4. Hacer instancia mltiples del tipo.
Los mdulos son mecanismos de ocultacin de infoIlnacin y no cumplen bsica-
mente ms que los apartados 2 y 3. Los tipos abstractos de datos se implementan con
mdulos en Modula-2 y paquetes en CLU o Ada .

_____________________ ~ ~ _ _ o ..... " _ _ _ _
88 Estructura de datos
3.1.6. Objetos
Un objeto es sencillamente un tipo abstracto de datos al que se aaden importan-
tes innovaciones en comparticin de cdigo y reutilizacin. Los mecanismos bsicos de
orientacin a objetos son: objetos, mensajes y mtodos, clases e instancias y herencia.
Una idea fundamental es la comunicacin de los objetos a travs de paso de mensa-
jes. Adems de esta idea, se aaden los mecanismos de herencia y polimorfismo. La
herencia permite diferentes tipos de datos para compartir el mismo cdigo, permitiendo
una reduccin en el tamao del cdigo y un incremento en la funcionalidad. El polimor-
fismo permite que un mismo mensaje pueda actuar sobre objetos diferentes y comportar-
se de modo distinto.
La persistencia se refiere a la permanencia de un objeto, esto es, la cantidad de tiem-
po para el cual se asigna espacio y permanece accesible en la memoria del compu-
tador.
Conceptos
clave
Abstraccin
Herencia
Encapsulacin
Polimorfismo
Entidades bsicas
Objeto
Mensajes
Mtodos
Persistencia
Genericidad
Herencia
Jerarqua
Figura 3.1. Principios bsicos de la orientacin a objetos.
3.2. UN NUEVO PARADIGMA DE PROGRAMACiN
La programacin orientada a objetos (POO) I se suele conocer como un nuevo paradig-
ma de programacin. Otros paradigmas conocidos son: el paradigma de la progra-
macin imperativa (con lenguajes tales como Pascal o C), el paradigma de la progra-
I En ingls, OOP (Object Oriented Prograrnrning).


Abstraccin de datos: tipos abstractos de datos y objetos 89
macin lgica (PROLOG) y el paradigma de la programacin funcional (Lisp). El sig-
nificado de paradigma 2 (paradigma, en latn; paradigma, en griego) en su origen signi-
ficaba un ejemplo ilustrativo, en particular enunciado modelo que mostraba todas las
inflexiones de una palabra. En el libro The Structure of Scientific Revolutions el historia-
dor Thomas Kuhn 3 [Kuhn 70] describa un paradigma como un conjunto de teoras,
estndar y mtodos que juntos representan un medio de organizacin del conocimiento:
es decir, un medio de visualizar el mundo. En este sentido la programacin orientada a
objetos es un nuevo paradigma. La orientacin a objetos fuerza a reconsiderar nuestro
pensamiento sobre la computacin, sobre lo que significa realizar computacin y sobre
cmo se estructura la informacin dentro del computador.
Jenkins y Glasgow observan que la mayora de los programadores trabajan en un
lenguaje y utilizan slo un estilo de programacin. Ellos programan en un paradigma
forzado por el lenguaje que utilizan. Con frecuencia, no se enfrentan a mtodos alterna-
tivos de resolucin de un problema, y por consiguiente tienen dificultad en ver la ventaja
de elegir un estilo ms apropiado al problema a manejar. Bobrow y Stefik definen un
estilo de programacin como un medio de organizacin de programas sobre la base
de algn modelo conceptual de programacin y un lenguaje apropiado para hacer
programas en un estilo claro. Sugiere que existen cuatro clases de estilos de progra-
. ,
maClOn:
Orientados a procedimientos
Orientados a objetos
Orientados a lgica
Orientados a reglas
Algoritmos
Clases y objetos
Expresado en clculo de predicados
Reglas if-then
No existe ningn estilo de programacin idneo para todas las clases de pro-
gramacin. La orientacin a objetos se acopla a la simulacin de situaciones del mun-
do real.
En POO, las entidades centrales son los objetos, que son tipos de datos que encapsu-
lan con el mismo nombre estructuras de datos y las operaciones o algoritmos que mani-
pulan esos datos.
3.3. MODULARIDAD
La programacin modular trata de descomponer un programa en un pequeo nmero de
abstracciones coherentes que pertenecen al dominio del problema y cuya complejidad
interna es susceptible de ser enmascarada por la descripcin de un interfaz.
2 Un ejemplo que sirve como modelo o patrn: Dictionary of Science and Techn%gy, Academic
Press, 1992.
3 Kuhn, Thomas S.: The Structure of Scientific Revo/ution, 2." e d ~ University of Chicago Press, Chi-
cago, 1970.
90 Estructura de datos
Si las abstracciones que se desean representar pueden, en ciertos casos, correspon-
der a una nica accin abstracta y se implementan en general con la nocin de objeto
abstracto (o tipo abstracto) caracterizado en todo instante por:
Un estado actual, definido por un cierto nmero de atributos.
Un conjunto de acciones posibles.
En consecuencia, la modularidad es la posibilidad de subdividir una aplicacin
en piezas ms pequeas (denominadas mdulos) cada una de las cuales debe ser tan
independiente como sea posible, considerando la aplicacin como un todo, as como de
las otras piezas de las cuales es una parte. Este principio bsico desemboca en el princi-
pio bsico de construir programas modulares. Esto significa que, aproximadamente, ha
de subdividir un programa en piezas ms pequeas, o mdulos, que son generalmente
independientes de cada una de las restantes y se pueden ensamblar fcilmente para
construir la aplicacin completa. En esencia, las abstracciones se implementan en mdu-
los, conocidos en la terminologa de Booch como objetos, que agrupan en una sola
entidad:
Un conjunto de datos. .
Un conjunto de operaciones que actan sobre los datos.
Liskov define la modularizacin como el proceso de dividir un programa en mdu-
los que se pueden compilar separadamente, pero que tienen conexiones con otros m-
dulos. Pamas va ms lejos y dice que las conexiones entre mdulos deben seguir el
criterio de ocultacin de la informacin: un sistema se debe descomponer de acuerdo al
criterio general, de que cada mdulo oculta alguna decisin de diseo del resto del siste-
ma; en otras palabras, cada mdulo oculta un secreto.
Si un programa se descompone (o subdivide en mdulos) de modo consistente con el
criterio de Pamas es decir, aplicando el principio de ocultacin de la informacin se

reduce la complejidad de cada mdulo que compone la solucin. Estos se constituyen,
en cierto modo, independientes de los restantes y, por consiguiente, se reduce la necesi-
dad de tomar decisiones globales, operaciones y datos.
3.3.1. La estructura de un mdulo
Un mdulo se caracteriza fundamentalmente por su interfaz y por su implementacin.
Pamas define el mdulo como un conjunto de acciones denominadas, funciones o sub-
mdulos que corresponden a una abstraccin coherente, que compartan un conjunto de
datos comunes implantadas estticamente llamadas atributos, eventualmente asociadas
a definiciones lgicas de tipos. Las acciones o funciones de un mdulo que son suscep-
tibles de ser llamadas desde el exterior se denominan primitivas o puntos de entrada del
mdulo. Los tipos lgicos eventualmente definidos en la interfaz permiten representar
los parmetros de estas primitivas.
Interfaz
Seccin
privada
Abstraccin de datos: tipos abstractos de datos y objetos 91
Primitivas de acceso
Descripcin de propiedades de los datos
Atributos Algoritmos
Representacin Parmetros actuales
Figura 3.2. Estructura de un mdulo.
3.3.2. Reglas de modularizacin
En primer lugar, un mtodo de diseo debe ayudar al programador a resolver un proble,.
ma dividiendo el problema en subproblemas ms pequeos, que se puedan resolver in-
dependientemente unos de otros. Debe, tambin, ser fcil conectar los diferentes mdu-
los a los restantes, dentro del programa que est escribiendo.
Cada mdulo tiene un significado especfico propio y se debe asegurar que cualquier
cambio a su implementacin no afecte a su exterior (o al menos, lo mnimo). De igual
modo los errores posibles, condiciones de lmites o frontera, comportamientos errticos
no se propaguen ms all del mdulo (o como mximo, a los mdulos que estn directa-
mente en contacto con el afectado).
Para obtener mdulos con las caractersticas anteriores, se deben seguir las siguien-
tes reglas:
Unidades modulares
El lenguaje debe proporcionar estructuras modulares con las cuales se puedan des-
cribir las diferentes unidades. De este modo, el lenguaje (y el compilador) puede reco-
nocer un mdulo y debe ser capaz de manipular y gobernar su uso, adems de las ven-
tajas evidentes relativas a la legibilidad del cdigo resultante. Estas construcciones
modulares pueden, como en el caso de los lenguajes orientados a objetos, mostrar carac-
tersticas que facilitan la estructura del programa, as como la escritura de programas.
En otras palabras, nos referimos a las unidades modulares lingsticas que en el caso de
C++ se conocen como clases y en Turbo Borland Pascal, los mdulos se denominan
unidades. La sintaxis de las unidades diferencia entre el interfaz y la implementacin
del mdulo. Las dependencias entre unidades se pueden declarar slo en un interfaz del
mdulo. Ada va ms lejos y define el paquete en dos partes: la especificacin del paque-
te y el cuerpo del paquete. Al contrario que Object Pascal, Ada permite que la conexin
entre mdulos se declaren independientemente en la especificacin y en el cuerpo de un
paquete.
92 Estructura de datos
,
Interfaces adecuados
En la estructuracin de un programa en unidades es beneficioso que existan pocos inter-
faces y que estos sean pequeos. Es conveniente que existan pocos enlaces entre los
diferentes mdulos en que se descompone un programa. El interfaz de un mdulo es la
parte del mdulo (datos, procedimientos, etc.) que es visible fuera del mdulo.
Los interfaces deben ser tambin pequeos (esto es, su tamao debe ser pequeo con
respecto al tamao de los mdulos implicados). De este modo, los mdulos estn aco-
plados dbilmente; se enlazarn por un nmero pequeo de llamadas (Figura 3.3).
Pocos Muchos
interfaces interfaces
Figura 3.3. Interfaces adecuados (pocos-muchos).
Parte
Interfaces visible
grandes
Interfaces
pequeos
Parte
visible
Figura 3.4. Interfaces adecuados (grandes-pequeos).
Abstraccin de datos: tipos abstractos de datos y objetos 93
Interfaces explcitos
La interfaz o parte visible externamente de un mdulo se debe declarar y describir expl-
citamente; el programa debe especificar cules son los datos y procedimientos que un
mdulo trata de exportar y cules deben permanecer ocultos del exterior. La interfaz
debe ser fcilmente legible, tanto para el programador como para el compilador. Es de-
cir, el programador debe comprender cmo funciona el programa y el compilador ha de
poder comprobar si el cdigo que accede al mdulo se ha escrito correctamente.
Ocultacin de la informacin
Todos los mdulos deben seguir el principio de ocultacin de la informacin; cada m-
dulo debe representarse al menos un elemento de diseo (por ejemplo, la estructura de
un registro, un algoritmo, una abstraccin, etc.).
Otro criterio a tener en cuenta es la subdivisin de un sistema en mdulos, es el
principio denominado abierto-cerrado 4, formulado por Meyer. Este principio entiende
que cada mdulo se considerar cerrado (esto es, terminado y, por consiguiente, til o
activo desde dentro de otros mdulos) y, al mismo tiempo, debe ser abierto (esto es,
sometido a cambios y modificaciones). El principio abierto-cerrado debe producirse
sin tener que reescribir todos los mdulos que ya utilizan el mdulo que se est modifi-
cando.
, ',' , " "

_. - '-_._ . - -'-:'-,:',,'" :.,.


. ~ . 1, ,;,<: '
-" ----.,-_. -
" o -c :, __ -._.

En diseo estructurado, la modularizacin como ya se ha comentado se centra
en el agrupamiento significativo de subprogramas, utilizando el criterio de acoplamiento
y cohesin.
En diseo orientado a objetos, el problema es sutilmente diferente: la tarea consiste
en decidir dnde se empaquetan flsicamente las clases y objetos de la estructura lgica
del diseo, que son claramente diferentes de los subprogramas.
4 Sobre el principio abierto-cerrado y su implementacin en C++ y Eiffel, se puede consultar la biblio-
grafia de Miguel Katrib. Algunos ttulos destacados sobre orientacin a objetos son: Programacin Orien-
tada a Objetos a travs de C++ y Eiffel. V Escuela Internacional en Temas Selectos de Computacin.
Zacatecas, Mxico, 1994 (esta Escuela est organizada por la UN AM. Mxico); Programacin Orientada a
Objetos en C++. Infosys, Mxico, 1994; Collections and Iterators in Eiffel, Joop, vol. 6, nm. 7, noviem-
bre-diciembre 1993.

I
94 Estructura de datos
- .
3.4. DISENO DE MODULOS
Aunque el diseo modular persigue la divisin de un sistema grande en mdulos ms
pequeos y a la vez manejables, no siempre esta divisin es garanta de un sistema bien
organizado. Los mdulos deben disearse con los criterios de acoplamiento y cohesin.
El primer criterio exige independencia de mdulos y el segundo criterio se corresponde
con la idea de que cada mdulo debe realizarse con una sola funcin relacionada con el
problema.
Desde esta perspectiva Booch s define la modularidad como la propiedad de un siste-
ma que ha sido descompuesto en un conjunto de mdulos cohesivos y dbilmente aco-
plados.
3.4.1. Acoplamiento de mdulos
El acoplamiento es una medida del grado de interdependencia entre mdulos, es decir,
el modo en que un mdulo est siendo afectado por la estructura interna de otro mdu-
lo. El grado de acoplamiento se puede utilizar para evaluar la calidad de un diseo de
sistema. El objetivo es minimizar el acoplamiento entre mdulos, es decir, minimizar su
interdependencia, de modo que un mdulo sea afectado 10 menos posible por la estruc-
tura de otro mdulo. El acoplamiento entre mdulos vara en un amplio rango. Por un
lado, el diseo de un sistema puede tener una jerarqua de mdulos totalmente desaco-
plados. Sin embargo, dado que un sistema debe realizar un conjunto de funciones o ta-
reas de un modo organizado, no puede constar de un conjunto de mdulos totalmente
desacoplados. En el otro extremo, se tendr una jerarqua de mdulos estrechamente
acoplados; es decir, hay un alto grado de dependencia entre cada pareja de mdulos del
diseo.
Tal como define Booch, un sistema modular dbilmente acoplado facilita:
l. La sustitucin de un mdulo por otro, de modo que slo unos pocos mdulos
sern afectados por el cambio.
2. El seguimiento de un error y el aislamiento del mdulo defectuoso que produce
ese error.
Existen varias clases de. acoplamiento entre dos mdulos (Tabla 3.1). Examina-
remos los cinco tipos de acoplamiento, desde el menos deseable (esto es, acoplamiento
estrecho o impermeable) al ms deseable (esto es, acoplamiento ms dbil). La fuerza
de acoplamiento entre dos mdulos est influenciada por el tipo de conexin, el tipo de
comunicacin entre ellos y la complejidad global de su interfaz .

5 Booch, Grady: Object-Oriented Design with applications, Benjamin Cummings, 1991, pg. 52.
Abstraccin de datos: tipos abstractos de datos y objetos 95
Tabla 3.1. Clasificacin del acoplamiento del mdulo
l'ipCl d ~ Jito G d de 1 i ..... G.,.lIo. d,. ptanteDibilid.d
. . C)p ro

aC:j)p a p ~ . ..
.
. . . .'. . ra .. 0. ..' ac:. ."pe",..
. ': :

Por contenido Alto (Fuerte) Bajo
Comn
De control
Por sellado (estampado)
Datos
Sin acoplamiento
Bajo (Dbil) Alto
3.4.2. Cohesin de mdulos
La cohesin es una extensin del concepto de ocultamiento de la informacin. Dicho de
otro modo, la cohesin describe la naturaleza de las interacciones dentro de un mdulo
software. Este criterio sugiere que un sistema bien modularizado es aquel en el cual los
interfaces de los mdulos son claros y simples. Un mdulo cohesivo ejecuta una tarea
sencilla de un procedimiento de software y requiere poca interaccin con procedimien-
tos que ejecutan otras partes de un programa. En otras palabras, un mdulo cohesivo
slo hace (idealmente) una cosa.
La cohesin y el acoplamiento se miden como un espectro que muestra las escalas
que siguen los mdulos. La Tabla 3.1 muestra la clasificacin de acoplamientos de m-
dulos y su grado de acoplamiento. La Tabla 3.2 muestra los grados de cohesin: baja
cohesin (no deseable) y alta cohesin (deseable), as como los diferentes tipos de cohe-
. ,
SlOn.
Idealmente se buscan mdulos altamente cohesivos y dbilmente acoplados.
Tabla 3.2. Clasificacin de cohesin de mdulos
, . . :.

. . .
:. :.:.:.: . .." .. ,
l'ipC)$ de cohesin. .. Gra" dec:o'hesin '

.... G ... dode mantenimiento


.: .. .

..... :::: ":.: ,. :.;".:<::.::: .... : .. ::. ... " .. "... . .":.: ..... :.::. :. : ...
.
Por coincidencia Bajo Bajo
Lgica
Temporal
Por procedimientos
Por

,
comUnIcaCIOnes
Secuencial
Funcional
Informacional . Alto Alto
96 Estructura de datos
3.5. TIPOS DE DATOS
Todos los lenguajes de programacin soportan algn tipo de dato. Por ejemplo, el len-
guaje de programacin convencional Pascal soporta tipos base tales como enteros, rea-
les y caracteres, as como tipos compuestos tales como arrays (vectores y matrices) y
registros. Los tipos abstractos de datos extienden la funcin de un tipo de datos; ocul-
tan la implementacin de las operaciones definidas por el usuario asociadas con el
tipo de datos. Esta capacidad de ocultar la infonnacin permite el desarrollo de compo-
nentesde software reutilizables y extensibles.
Un tipo de dato es ",n conjunto de va/ores, y un conjunto de operaciones definidas
por esos valores.
Un valor depende de su representacin y de la interpretacin de la representacin,
por lo que una definicin informal de un tipo de dato es: Representacin + Operaciones.
Un tipo de dato describe un conjunto de objetos con la misma representacin. Exis-
ten un nmero de operaciones asociadas con cada tipo. Es posible realizar aritmtica
sobre tipos de datos enteros y reales, c o n c t ~ n r cadenas o recuperar o modificar el va-
lor de un elemento.
La mayora de los lenguajes tratan las variables y constantes de un programa como
instancias de un tipo de dato. Un tipo de dato proporciona una descripcin de sus ins-
tancias que indican al compilador cosas como cunta memoria se debe asignar para una
instancia, cmo interpretar los datos en memoria y qu operaciones son permisibles so-
bre esos datos. Por ejemplo, cuando se escribe una declaracin tal como f 1 oa t z en C
o C++, se est declarando una instancia denominada z del tipo de dato f loa t. El
tipo de datos float indica al compilador que reserve, por ejemplo, 32 bits de memo-
ria, y qu operaciones tales como sumar y multiplicar estn permitidas, mientras
que operaciones tales como el el resto (mdulo) y desplazamiento de bits no lo son.
Sin embargo, no se necesita escribir la declaracin del tipo float el autor de compila-
dor lo hizo por nosotros y se construyen en el compilador . Los tipos de datos que se
construyen en un compilador de este modo, se conocen como tipos de datos fundamen-
tales (predefinidos), y por ejemplo en C y C++ son entre otros: int, char y float.
Cada lenguaje de programacin incorpora una coleccin de tipos de datos funda-
mentales, que incluyen normalmente enteros, reales, carcter, etc. Los lenguajes de pro-
gramacin soportan tambin un nmero de constructores de tipos incorporados que per-
miten generar tipos ms complejos. Por ejemplo, Pascal soporta registros y arrays.
En lenguajes convencionales tales como C, Pascal, etc., las operaciones sobre un
tipo de dato son composiciones de constructores de tipo y operaciones de tipos bases.
-,-.--',--'
-- ,-,.,
-- -"."
Operaciones .:=:. Operacioqes constructor + Operaciones base ...
,-,
Algunos tipos de constructores incluyen registros, arrays, listas, conjuntos, etc.
-
Abstraccin de datos: tipos abstractos de datos y objetos 97
3.6. ABSTRACCiN EN LENGUAJES DE PROGRAMACiN
Los lenguajes de programacin son las herramientas mediante las cuales los diseadores
de lenguajes pueden implementar los modelos abstractos. La abstraccin ofrecida por
los lenguajes de programacin se puede dividir en dos categoras: abstraccin de datos
(perteneciente a los datos) y abstraccin de control (perteneciente a las estructuras de
control).
Desde comienzos del decenio de los sesenta, en que se desarrollaron los prime-
ros lenguajes de programacin de alto nivel, ha sido posible utilizar las abstracciones
ms primitivas de ambas categoras (variables, tipos de datos, procedimientos, control
de bucles, etc.). Ambas categoras de abstracciones han producido una gran cantidad de
lenguajes de programacin no siempre bien definidos.
3.6.1 . Abstracciones de control
,
Los microprocesadores ofrecen directamente slo dos mecanismos para controlar el flu-
jo y ejecucin de las instrucciones: secuencia y salto. Los primeros lenguajes de progra-
macin de alto nivel introdujeron las estructuras de control: sentencias de bifurcacin
( i f) y bucles (for, while, do-l oop, etc.).
Las estructuras de control describen el orden en que se ejecutan las sentencias o
grupos de sentencia (unidades de programa). Las unidades de programa se utilizan como
bloques bsicos de la clsica descomposicin descendente. En todos los casos, los
subprogramas constituyen una herramienta potente de abstraccin ya que durante su
implementacin, el programador describe en detalle cmo funcionan los subprogramas.
Cuando el subprograma se llama, basta con conocer lo que hace y no cmo 10 hace. De
este modo, los subprogramas se convierten en cajas negras que amplan el lenguaje de
programacin a utilizar. En general , los subprogramas son los mecanismos ms amplia-
mente utilizados para reutilizar cdigo, a travs de colecciones de subprogramas en bi-
bliotecas.

Las abstracciones y estructuras de control se clasifican en estructuras de control a
nivel de sentencia y a nivel de unidades. Las abstracciones de control a nivel de unidad
se conoce como abstraccin procedimental.
Abstraccin procedimental (por procedimientos)
Es esencial para disear software modular y fiable. La abstraccin procedimental se
basa en la utilizacin de procedimientos o funciones sin preocuparse de cmo se imple-
mentan. Esto es posible slo si conocemos qu hace el procedimiento; esto es; conoce-
mos la sintaxis y semntica que utiliza el procedimiento o funcin. El nico mecanismo
en Pascal estndar para establecer abstraccin procedimental es el subprograma (proce-
dimientos y funciones). La abstraccin aparece en los subprogramas debido a las si-
guientes causas:
98 Estructura de datos
Con el nombre de los subprogramas, un programador puede asignar una des-
cripcin abstracta que captura el significado global del subprograma. Utili-
zando el nombre en lugar de escribir el cdigo permite al programador aplicar la
accin en tIlninos de su descripcin de alto nivel en lugar de sus detalles de bajo
nivel.
Los subprogramas en Pascal proporcionan ocultacin de la informacin. Las va-
riables locales y cualquier otra definicin local se encapsulan en el subprograma,
ocultndolos realmente de forma que no se pueden utilizar fuera del subprogra-
ma. Por consiguiente, el programador no tiene que preocuparse sobre las defini-
ciones locales; sin embargo, pueden utilizarse los componentes sin conocer nada
sobre sus detalles.
Los parmetros de los subprogramas, junto con la ocultacin de la informacin
anterior, permiten crear subprogramas que constituyen entidades de software pro-
pias. Los detalles locales de la implementacin pueden estar ocultos mientras que
los parmetros se pueden utilizar para establecer el interfaz pblico.
Otros mecanismos de abstraccin de control
La evolucin de los lenguajes de programacin ha permitido la aparicin de otros meca-
nismos para la abstraccin de control, tales como manejo de excepciones, corrutinas,
unidades concurrentes, plantillas (<<templates). Estas construcciones son soportadas por
los lenguajes de programacin basados y orientados a objetos, tales como Modula-2,

Ada, C++, Smalltalk o Eiffel.


3.6.2. Abstraccin de datos
Los primeros pasos hacia la abstraccin de datos se crearon con lenguajes tales como
FORTRAN, COBOL Y ALGOL 60, con la introduccin de tipos de variables diferentes,
que manipulan enteros, nmeros reales, caracteres, valores lgicos, etc. Sin embargo,
estos tipos de datos no podan ser modificados y no siempre se ajustaban al tipo de uno
para el que se necesitaban. Por ejemplo, el tratamiento de cadenas es una deficiencia en
FORTRAN, mientras que la precisin y fiabilidad para clculos matemticos es muy
alta.
La siguiente generacin de lenguajes, incluyendo Pascal, SIMULA-67 y AL-
GOL 68, ofreci una amplia seleccin de tipos de datos y permiti al programador mo-
dificar y ampliar los tipos de datos existentes mediante construcciones especficas (por
ejemplo, arrays y registros). Adems, SIMULA-67 fue el primer lenguaje que mezcl
datos y procedimientos mediante la construccin de clases, que eventualmente se con-
virti en la base del desarrollo de programacin orientada a objetos.
La abstraccin de datos es la tcnica de programacin que permite inventar o definir
nuevos tipos de datos (tipos de datos definidos por el usuario) adecuados a la aplicacin
que se desea realizar. La abstraccin de datos es una tcnica muy potente que permite
disear programas ms cortos, legibles y flexibles. La esencia de la abstraccin es simi-
Abstraccin de datos: tipos abstractos de datos y objetos 99
lar a la utilizacin de un tipo de dato, cuyo uso se realiza sin tener en cuenta cmo est
representado o implementado.
Los tipos de datos son abstracciones y el proceso de construir nuevos tipos se llaman
abstracciones de datos. Los nuevos tipos de datos definidos por el usuario se llaman
tipos abstractos de datos.
El concepto de tipo, tal como se defini en Pascal y ALGOL 68, ha constituido un
hito importante hacia la realizacin de un lenguaje capaz de soportar programacin es-
tructurada. Sin embargo, estos lenguajes no soportan totalmente una metodologa. La
abstraccin de datos til para este propsito, no slo clasifica objetos de acuerdo a su
estructura de representacin; sino que se clasifican de acuerdo al comportamiento espe-
rado. Tal comportamiento es expresable en trminos de operaciones que son significati-

vas sobre esos datos, y las operaciones son el nico medio para crear, modificar y acce-
der a los objetos.
En trminos ms precisos, Ghezzi indica que un tipo de dato definible por el usuario
se denomina tipo abstracto de dato (TAD) si:
Existe una construccin del lenguaje que le permite asociar la representacin de
los datos con las operaciones que lo manipulan.
La representacin del nuevo tipo de dato est oculta de las unidades de programa
que lo utilizan [Ghezzi 87].
Las clases en SIMULA slo cumplan la primera de las dos condiciones, mientras
que otros lenguajes actuales cumplen las dos condiciones: Ada, Modula-2 y C++.
Los tipos abstractos de datos proporcionan un mecanismo adicional mediante el cual
se realiza una separacin clara entre la interfaz y la implementacin del tipo de dato. La
implementacin de un tipo abstracto de dato consta de:
l. La representacin: eleccin de las estructuras de datos.
2. Las operaciones: eleccin de los algoritmos.
La interfaz del tipo abstracto de dato se asocia con las operaciones y datos visibles al
exterior del TAD.
3.7. TIPOS ABSTRACTOS DE DATOS (TAO)
Algunos lenguajes de programacin tienen caractersticas que nos permiten ampliar el
lenguaje aadiendo sus propios tipos de datos. Un tipo de dato definido por el programa-
dor se denomina tipo abstracto de datos (TAD) para diferenciarlo del tipo fundamental
(predefinido) de datos. Por ejemplo, en Turbo Borland Pascal un tipo Punto, que repre-
senta a las coordenadas x e y de un sistema de coordenadas rectangulares, no existe. Sin
embargo, es posible implementar el tipo abstracto de datos, considerando los valores
que se almacenan en las variables y qu operaciones estn disponibles para manipular
estas variables. En esencia un tipo abstracto de datos es un tipo de datos que consta de
100 Estructura de datos

datos (estructuras de datos propias) y operaciones que se pueden realizar sobre esos
datos. Un TAD se compone de estructuras de datos y los procedimientos o funciones
que manipulan esas estructuras de datos.
TAD = Representacin (datos) + Operaciones (funciones y procedimientos)
Las operaciones desde un enfoque orientado a objetos se suelen denominar mtodos.
La estructura de un tipo abstracto de dato (clase), desde un punto de vista global, se
compone del interfaz y de la implementacin (Figura 3.5).
Las estructuras de datos reales elegidas para almacenar la representacin de un tipo
abstracto de datos son invisibles a los usuarios o clientes. Los algoritmos utilizados para
implementar cada una de las operaciones de los TAO estn encapsuladas dentro de los
propios TAO. La caracterstica de ocultamiento de la informacin del TAO significa que
los objetos tienen interfaces pblicos. Sin embargo, las representaciones e implementa-
ciones de esos interfaces son privados.
Mtodo 1
Mtodo 3
...
Interfaz pblico
Representacin:
estructura de datos
(variables de instancia)
Mtodo 1
Mtodo 3
Implementacin de mtodos:
Cdigo del mtodo 1
Cdigo del mtodo 2
Cdigo del mtodo 3
Cdigo del mtodo 4
...
Implementacin privada

Figura 3.5. Estructura de un tipo abstracto de datos (TAO).
Abstraccin de datos: tipos abstractos de datos y objetos 101
3.7.1. Ventajas de los tipos abstractos de datos
Un tipo abstracto de datos es un modelo (estructura) con un nmero de operaciones que
afectan a ese modelo. Es similar a la definicin que daremos en el captulo siguiente de
objeto y, de hecho, estn unidos ntimamente. Los tipos abstractos de datos proporcio-
nan numerosos beneficios al programador, que se pueden resumir en los siguientes:
l. Permite una mejor conceptualizacin y modelado del mundo real. Mejora la re-
presentacin y la comprensibilidad. Clarifica los objetos basados en estructuras
y comportamientos comunes.
2. Mejora la robustez del sistema. Si hay caractersticas subyacentes en los lengua-
jes permiten la especificacin del tipo de cada variable, los tipos abstractos
de datos permiten la comprobacin de tipos para evitar errores de tipo en tiem-
po de ejecucin.
3. Mejora el rendimiento (prestaciones). Para sistemas tipeados, el conocimiento
de los objetos permite la optimizacin de tiempo de compilacin.
4. Separa la implementacin de la especificacin. Permite la modificacin y mejo-
ra de la implementacin sin afectar al interfaz pblico del tipo abstracto de dato.
5. Permite la extensibilidad del sistema. Los componentes de software reutiliza-
bles son ms fciles de crear y mantener.
6. Recoge mejor la semntica del tipo. Los tipos abstractos de datos agrupan o
localizan las operaciones y la representacin de atributos.
3.7.2. Implementacin de los TAO
Los lenguajes convencionales, tales como Pascal, permiten la definicin de nuevos tipos
y la declaracin de procedimientos y funciones para realizar operaciones sobre objetos
de los tipos. Sin embargo, tales lenguajes no permiten que los datos y las operaciones
asociadas sean declaradas juntos como una unidad y con un solo nombre. En los lengua-
jes en el que los mdulos (TAD) se pueden implementar como una unidad, stos reciben
nombres distintos:

Turbo Borland Pascal


Modula-2
Ada
C++
Java
unidad, objeto
mdulo
paquete
clase
clase
En estos lenguajes se definen la especificacin del TAD, que declara las operaciones
y los datos ocultos al exterior, y la implementacin, que muestra el cdigo fuente de las
operaciones y que permanece oculto al exterior del mdulo.
Las ventajas de los TAD se pueden manifestar en toda su potencia, debido a que las
dos partes de los mdulos (especificacin e implementacin) se pueden compilar por
separado mediante la tcnica de compilacin separada (<<separate compilation).

102 Estructura de datos


3.8. TIPOS ABSTRACTOS DE DATOS EN TURBO BORLAND
PASCAL
Una pila es una de las estructuras de datos ms utilizadas en el mundo de la compila-
cin. Una pila es un tipo de dato clsico utilizado frecuentemente para introducir al
concepto de tipo abstracto de datos; es una lista lineal de elementos en la que los ele-
mentos se aaden o se quitan por un solo extremo de la lista. La pila almacena elemen-
,
tos del mismo tipo y actan sobre ella las operaciones clsicas de Meter y Sacar elemen-
tos en dicha pila, teniendo presente la estructura lgica LIFO (ltimo en entrar, primero
en salir).
En Turbo Borland Pascal, los TAD se implementan mediante estructuras tipo uni-
dad. Recordemos que una unidad es una biblioteca de func.iones y procedimientos que
pueden ser utilizados por cualquier programa con la condicin de incluir el nombre de la
unidad en la clusula uses de su sintaxis.
Pila
unit <nombre unidad>;
interface
<c lausula uses >
<constantes, tipos y variables publicas >
<cabeceras de procedimientos y funciones publicas>
implementation
<clausula uses >
<constantes , tipos y variables privadas >
<procedimientos / funciones privadas y cuerpos de
procedimientos / f un c i ones publicas>
begin
<secuencia de sent e nc ias para inicializacion>
end.
Estructura de datos
Almacena una serie de elementos del tipo elemento. La pila est inicialmente vaca y los elementos
se meten o sacan en la pila por el mismo extremo.
Operaciones (Procedimientos que actan sobre la estructura de datos).
Meter
Sacar
Crear
Destruir
Pilavacia
Cima
Sacar
Meter
-
- ,
Fondo vi C\. CA , .
Figura 3.6. Estructura de datos Pila.
Abstraccin de datos: tipos abstractos de datos y objetos 103
La implementacin de una pila con capacidad para 1.000 elementos del tipo en-
tero es:

unit Pila;
interface .
const
MaxPila = 1000;
type
TipoElemento = int eger;
ListaElementos = array (l .. MaxPilal of TipoElemento;
tipo = record
Elems : ListaElementos; ,
Cima: integer;
end;
procedure Crear (var S:tipo);
(* S s e inic ializa y se limpia o vaca * )
procedure Destruir (var S:tipo);
(* Se libera memoria asignada a S * )
(* S no est inicializada *)
.
procedure Meter (var S:tipo; Item: t ipoEl ement o);
(* Se aade un elemento a la cima de la pila *)
procedure Sacar (var S:tipo;var Item:tipoElemento);
(*quitar un elemento de la pila *)
function PilaVacia (S:tipo)
(*devuelve true si S es vaca; false en caso contrario *)
implementation
procedure Crear (var S:tipo);
begin
S.Cima := O;
end;
procedure Destruir (var S:tipo);
begin
(*no ha c e nada *)
end;
procedure Meter ( var S:tipo; Item:TipoElemento);
begin
S.Cima := S.Cima + 1;
S .Elems(S.Cimal := Item;
end;
.
procedure Sacar (var S:tipo; var Item:TipoElemento);
begin
Item := S.Elems(S.Cimal;
S.Cima
end;
:= S.Cima-l


,
1

I
,
,


104 Estructura de datos
function pil aVacia (S :tipo) :bool ean;
begin
PilaVacia : = ( S . Cima =O) ;
end;
end.
Una vez que se ha implementado el tipo de dato p i 1 a , ste puede ser utilizado en
cualquier programa con tal de invocar en la clusula uses a dicho tipo de dato Pil a .
3.8.1. Aplicacin del tipo abstracto de dato pila
El siguiente programa lee una secuencia de enteros, uno por lnea, tales como stos:
100
4567
- 2 0
25 0
y genera la misma secuencia de nmeros en orden inverso (los saca de la pila).
250
-20
4567
10 0

Esta tarea se consigue metiendo nmeros en la pila y a continuacin vaciando dicha
pila.
program Numer o s ;
uses
Pi l a ;
var
S : Pila .Ti po ;
procedure LeeryAlmacenarNume ros( var NumPi la : Pil a.Tipo } ;
var
Aux : pil a.TipoEl emento ;
begin
while not eof do
begin
end;
readln (Aux) ;
Pi l a . Meter(NumPi l a , Aux} ;
end;
procedure VerNumeros( var NumPi l a : pil a.Ti po} ;
var
Aux : pi la.Ti poElemento;
begin
while not Pi l a . Pil avacia(NumPil a} do

Abstraccin de datos: tipos abstractos de datos y objetos 105


begin
Pi l a . Sacar( NumPi l a . Aux ) ;
Wr i teLn( Aux ) ;
end; ( * whi le *)
end; ( * Ve rNumer os * )
begin (* programa pr inc ipal * )
Pil a . Crear(S)
LeeryAl macenarNume r os( S ) ;
Ve rNumeros(S) ;
Pil a . Des tru i r (S) ;
end. (* fi n de p r inci p a l * )
Al igual que se ha definido el tipo pi 1 a con estructuras estticas tipo array, se

poda haber realizado con estructuras dinmicas tales como listas enlazadas. De igual
modo se pueden implementar otros tipos de datos abstractos tales como, por ejemplo, las
colas que se utilizan en muchas aplicaciones: sistemas operativos, sistemas de comuni-
caciones, etc.
3.9. ORIENTACiN A OBJETOS
La orientacin a objetos puede describirse como el conjunto de disciplinas (ingeniera)
que desarrollan y modelan software que facilitan la construccin de sistemas complejos
a partir de componentes.
El atractivo intuitivo de la orientacin a objetos es que proporciona conceptos y he-
rramientas con las cuales se modela y representa el mundo real tan fielmente como sea
posible. Las ventajas de la orientacin a objetos son muchas en programacin y modela-
cin de datos. Como apuntaban Ledbetter y Cox (1985):
La programacin orientada a objetos pellnite una representacin ms directa del modelo
de mundo real en el cdigo. El resultado es que la transformacin radical nOllnal de los
requisitos del sistema (definido en tllninos de usuario) a la especificacin del sistema
(definido en trminos de computador) se reduce considerablemente.
La Figura 3.7 ilustra el problema. Utilizando tcnicas convencionales, el cdigo ge-
nerado para un problema de mundo real consta de una primera codificacin del proble-
ma y a continuacin la transformacin del problema en trminos de un lenguaje de com-
putador Von Newmann. Las disciplinas y tcnicas orientadas a objetos manipulan la
transformacin automticamente, de modo que el volumen de cdigo que codifica el
problema y la transformacin se minimiza. De hecho, cuando se compara con estilos de
programacin convencionales (procedimentales por procedimientos), las reducciones
de cdigo van desde un 40 por 100 hasta un orden de magnitud elevado cuando se adop-
ta un estilo de programacin orientado a objetos.
Los conceptos y herramientas orientadas a objetos son tecnologas que permiten que
los problemas del mundo real sean expresados de modo fcil y natural. Las tcnicas
orientadas a objetos proporcionan mejoras metodolgicas para construir sistemas de soft-
ware complejos a partir de unidades de software modularizado y reutilizable .

106 Estructura de datos
Problema del
mundo real
Transformacin de Von Newman
Programa
Codificacin del programa
Figura 3.7. Construccin de software.
Se necesita un nuevo enfoque para construir software en la actualidad. Este nuevo
enfoque debe ser capaz de manipular, tanto sistemas grandes como pequeos, y debe
crear sistemas fiables que sean flexibles, mantenibles y capaces de evolucionar, para
cumplir las necesidades de cambio.
La tecnologa orieritada a objetos puede cubrir estos cambios y algunos otros ms en
el futuro. La orientacin a objetos trata de cumplir las necesidades de los usuarios fina-
les, as como las propias de los desarrolladores de productos software.
Estas tareas se realizan mediante la modelizacin del mundo real. El soporte funda-
mental es el modelo objeto. Los cuatro elementos (propiedades) ms importantes de este
modelo 6 son:
Abstraccin.
Encapsulacin.

Modularidad .
Jerarqua.
Como sugiere Booch, si alguno de estos elementos no existe, se dice que el modelo
no es orientado a objetos.
6 Booch, Grady: Object-Oriented Ana/ysis and Design with App/ications, Benjamin/Cummings,
1994.
Abstraccin de datos: tipos abstractos de datos y objetos 107
3.9.1. Abstraccin
La abstraccin es uno de los medios ms importante mediante el cual nos enfrentamos
con la complejidad inherente al software. La abstraccin es la propiedad que permite
representar las caractersticas esenciales de un objeto, sin preocuparse de las restantes
caractersticas (no esenciales).
Una abstraccin se centra en la vista externa de un objeto, de modo que sirva para
separar el comportamiento esencial de un objeto, de su implementacin. Definir una
abstraccin significa describir una entidad del mundo real, no importa lo compleja que
pueda ser, y a continuacin utilizar esta descripcin en un programa.
El elemento clave de la programacin orientada a objetos es la clase. Una clase se
puede definir como una descripcin abstracta de un grupo de objetos, cada uno de los
cuales se diferencia por su estado especfico y por la posibilidad de realizar una serie de
operaciones. Por ejemplo, una pluma estilogrfica es un objeto que tiene un estado (lle-
na de tinta o vaca) y sobre la cual se pueden realizar algunas operaciones (por ejemplo,
escribir, poner/quitar el capuchn, llenar de tinta si est vaca).
La idea de escribir programas definiendo una serie de abstracciones no es nueva,
pero el uso de clases para gestionar dichas abstracciones en lenguajes de programacin
ha facilitado considerablemente su aplicacin.
3.9.2. Encapsulacin
.
La encapsulacin o encapsulamiento es la propiedad que permite asegurar que el conte-
nido de la informacin de un objeto est oculta al mundo exterior: el objeto A no conoce
lo que hace el objeto B, y viceversa. La encapsulacin (tambin se conoce como oculta-
cin de la informacin), en esencia, es el proceso de ocultar todos los secretos de un
objeto que no contribuyen a sus caractersticas esenciales.
La encapsulacin permite la divisin de un programa en mdulos. Estos mdulos se
implementan mediante clases, de forma que una clase representa la encapsulacin de
una abstraccin. En la prctica, esto significa que cada clase debe tener dos partes: un
interfaz y una implementacin. La interfaz de una clase captura slo su vista externa y la
implementacin contiene la representacin de la abstraccin, as como los mecanismos
que realizan el comportamiento deseado.

3.9.3. Modularidad
La modularidad es la propiedad que permite subdividir una aplicacin en partes ms
pequeas (llamadas mdulos), cada una las cuales debe ser tan independiente como sea
posible de la aplicacin en s y de las restantes partes.
La modularizacin, como indica Liskov, consiste en dividir un programa en mdulos

que se pueden compilar por separado, pero que tienen conexiones con otros mdulos. Al
igual que la encapsulacin, los lenguajes soportan la modularidad de diversas formas.
Por ejemplo, en C++ los mdulos son archivos compilados por separado. La prctica
usual es situar las interfaces de los mdulos en archivos con nombres con extensin .h
108 Estructura de datos
(archivos de cabecera) y las implementaciones de los mdulos se sitan en archivos con
nombres con extensin . cpp.
En Ada, el mdulo se define como paquete (package). Un paquete tiene dos partes:
la especificacin del paquete y el cuerpo del paquete, tambin se pueden compilar por
separado.
La modularidad es la propiedad de un sistema que permite su descomposicin en un
conjunto de mdulos cohesivos y dbilmente acoplados .

3.9.4. Jerarqua

La jerarqua es una propiedad que permite una ordenacin de las abstracciones. Las dos
jerarquas ms importantes de un sistema complejo son: estructura de clases [jerarqua
es-un (is-a): generalizacin/especializacin] y estructura de objetos [jerarqua par-
te-de (part-o.!): agregacin].
No.sedebe
, ,-'.- ' .. ,' -- "" .c..
. . azul.no .
atrlbut6df .. ...
.
_ .. ,----
. ,-- -
Las jerarquas de generalizacin/especializacin se conocen como herencia. Bsica-
mente, la herencia define una relacin entre clases, en donde una clase comparte la es-
tructura o comportamiento definido en una o ms clases (herencia simple y herencia
mltiple, respectivamente).
La agregacin es el concepto que permite el agrupamiento fisieo de estructuras rela-
cionadas lgicamente. As, un camin se compone de ruedas, motor, sistema de transmi-
sin y chasis; en consecuencia, camin es una agregacin y ruedas, motor, transmisin y
chasis son agregados de camin.
3.9.5. Polimorfismo
La quinta propiedad significativa de los lenguajes de programacin orientados a objetos
es el polimorfismo. Esta propiedad no suele ser considerada como fundamental en los
diferentes modelos de objetos propuestos, pero dada su importancia, no tiene sentido
considerar un objeto modelo que no soporte esta propiedad.
Polimorfismo es la propiedad, que indica, literalmente, la posibilidad de que una
entidad tome muchas formas. En trminos prcticos, el polimorfismo permite referirse
a objetos de clases diferentes mediante el mismo elemento de programa y realizar
la misma operacin de diferentes formas, segn sea el objeto que se referencia en ese
momento.
Por ejemplo, cuando se qescribe la clase mamferos, se puede observar que la opera-
cin comer es una operacin fundamental en la vida de los mamferos, de modo que
cada tipo de mamfero debe poder realizar la operacin o funcin comer. Por otra parte,
una vaca o una cabra que pastan en un campo, un nio que se come un bombn o cara-
Abstraccin de datos: tipos abstractos de datos y objetos 109
me lo y un len que devora a otro animal, son diferentes formas que utilizan los distintos
mamferos, para realizar la misma funcin (comer).
El polimorfismo implica la posibilidad de tomar un objeto de un tipo (mamfero, por
ejemplo) e indicarle que ejecute comer; esta accin se ejecutar de diferente forma se-
gn sea el objeto mamfero sobre el que se aplica.
Clases, herencia y polimorfismo son aspectos claves en la programacin orientada a
objetos y se reconocen a estos elementos como esenciales en la orientacin a objetos. El
polimorfismo adquiere su mxima expresin en la derivacin o extensin de clases; es
decir, cuando se obtiene una clase a partir de una clase ya existente, mediante la propie-
dad de derivacin de clases o herencia. As, por ejemplo, si se dispone de una figura que
represente figuras genricas, se puede enviar cualquier mensaje tanto a un tipo derivado
(elipse, crculo, cuadrado, etc.) como al tipo base. Por ejemplo, una clase figura , pueden
aceptar los mensajes dibujar, borrar y mover. Cualquier tipo derivado de una figura es
un tipo de figura y puede recibir el mismo mensaje. Cuando se enva un mensaje, por
ejemplo dibujar, esta tarea ser distinta segn que la clase sea un tringulo, un cuadrado
o una elipse. Esta propiedad es el polimorfismo, que permite que una misma funcin se
comporte de diferente forma segn sea la clase sobre la que se aplica. La funcin dibujar
se aplica igualmente a un crculo, un cuadrado o un tringulo y el objeto ejecutar el
cdigo apropiado dependiendo del tipo especfico.
El polimorfismo requiere ligadura tarda o postergada (tambin llamada dinmica),
y esto slo se puede producir en lenguajes de programacin orientados a objetos. Los
lenguajes no orientados a objetos soportan ligadura temprana o anterior; esto significa
que el compilador genera una llamada a un nombre especfico de funcin y el enlazador
(linker) resuelve la llamada a la direccin absoluta del cdigo que se ha de ejecutar. En
POO, el programa no puede determinar la direccin del cdigo hasta el momento de la
ejecucin; para resolver este concepto, los lenguajes orientados a objetos utilizan el con-
cepto de ligadura tarda. Cuando se enva un mensaje a un objeto, el cdigo que se
llama no se determina hasta el momento de la ejecucin. El compilador asegura que la
funcin existe y realiza verificacin de tipos de los argumentos y del valor de retomo,
pero no conoce el cdigo exacto a ejecutar.
Para realizar la ligadura tarda, el compilador inserta un segmento especial de cdigo
en lugar de la llamada absoluta. Este cdigo calcula la direccin del cuerpo de la funcin
para ejecutar en tiempo de ejecucin utilizando informacin almacenada en el propio
objeto. Por consiguiente, cada objeto se puede comportar de modo diferente de acuerdo
al contenido de ese puntero. Cuando se enva un mensaje a un objeto, ste realmente
sabe qu ha de hacer con ese mensaje.
3.9.6. Otras propiedades
El modelo objeto ideal no slo tiene las propiedades anteriollllente citadas al principio
del apartado, sino que es conveniente soporte, adems, estas otras propiedades:
Concurrencia (multitarea).
Persistencia. '" '
_ _ ....... ,
110 Estructura de datos
Genericidad.
Manejo de excepciones.
Muchos lenguajes soportan todas estas propiedades y otros slo algunas de ellas.
As, por ejemplo, Ada soporta concurrencia y Ada y C++ soportan genericidad y manejo
de excepciones. La persistencia o propiedad de que las variables y por extensin, a los
objetos existan entre las invocaciones de un programa, es posiblemente la propiedad
menos implantada en los LPOO, aunque ya es posible considerar la persistencia en len-
guaje tales como Smalltalk y C+, lo que facilitar el advenimiento de las bases de datos
orientadas a objetos como as est sucediendo en esta segunda mitad de la dcada de los
noventa.
3.10. REUTILIZACiN DE SOFTWARE
Cuando se construye un automvil, un edificio o un dispositivo electrnico, se ensam-
blan una serie de piezas independientes de modo que estos componentes se reutilizan en
vez de fabricarlos cada vez que se necesita construir un automvil o un edificio. En la
construccin de software, esta pregunta es continua: Por qu no se utilizan programas
ya construidos para formar programas ms grandes? Es decir, si en electrnica, los com-
putadores y sus perifricos se fonuan esencialmente con el ensamblado de circuitos in-
tegrados, existe algn mtodo que permite realizar grandes programas a partir de la
utilizacin de otros programas ya realizados? Es posible reutilizar estos componentes
de software?
Las tcnicas orientadas u objetos proporcionan un mecanismo para construir compo-
nentes de software reutilizables que posteriormente puedan ser interconectados entre s
y formar grandes proyectos de software 7.
En los sistemas de programacin tradicionales y en particular en los basados en
lenguajes de programacin estructurados (tales como FORTRAN, C, etc.) exis-
ten las bibliotecas de funciones, que contienen funciones (o procedimientos, segn
el lenguaje) que pueden ser incorporados en diferentes programas. En sistemas orien-
tados a objetos se pueden construir componentes de software reutilizables, al estilo
de las bibliotecas de funciones, normalmente denominados bibliotecas de software o
paquetes de software reutilizables. Ejemplos de componentes reutilizables comer-
cialmente disponibles son: Turbo Visin de Turbo Borland Pascal, OLE 2.0 de C++,
jerarqua de clases Smalltalk, clases MacApp para desarrollo de interfaces grficos
de usuario en Object Pascal, disponibles en Apple, la coleccin de clases de Objec-
tive-C, etc.
7 Brad COX, en su ya clsico libro Object-Oriented Programming An Evolutionary Approach [Cox,
Novobilski , 91] , acu el tllllino chip de software (Software-IC), o componentes de software, para definir
las clases de objetos como componentes de software reutilizables. Existe versin en espaol de Addison-
Wesley/Daz de Santos, 1993, con el ttulo Programacin orientada a objetos. Un enfoque evolutivo.



I


Abstraccin de datos: tipos abstractos de datos y objetos 111
En el futuro inmediato, los ingenieros de software dispondrn de catlogos de pa-
quetes de software reutilizable, al igual que sucede con los catlogos de circuitos inte-
grados electrnicos como les ocurre a los ingenieros de hardware.
Las tcnicas orientadas a objetos ofrecen una alternativa de escribir el mismo pro-
grama una y otra vez. El programador orientado a objetos modifica una funcionalidad
del programa sustituyendo elementos antiguos u objetos por nuevos objetos, o bien co-
nectando simplemente nuevos objetos en la aplicacin.
La reutilizacin de cdigo en programacin tradicional se puede realizar copiando y
editando mientras que en programacin orientada a objetos se puede reutilizar el cdigo,
creando automticamente una subclase y anulando alguno de sus mtodos.
Muchos lenguajes orientados a objetos fomentan la reutilizacin mediante el uso de
bibliotecas robustas de clases preconstruidas, as como otras herramientas como hojea-
dores o navegadores (<<browser), para localizar clases de inters y depuradores interac-
tivos para ayudar al programador.
3.11. LENGUAJES DE PROGRAMACiN ORIENTADOS
A OBJETOS
El primer lenguaje de programacin que introdujo el concepto de clase fue Simula-67,
como entidad que contena datos y las operaciones que manipulaban los datos. Asimis-
mo, introdujo tambin el concepto de herencia.
El siguiente lenguaje orientado a objetos, y seguramente el ms popular desde un
enfoque conceptual exclusivamente de objetos, es Smalltalk, cuya primera versin co-
mercial se desarroll en 1976, y en 1980 se populariz con la aparicin de Smalltalk-80.
Posteriormente, se ha popularizado gracias al desarrollo de SmalltalklV de la casa Digi-
tal, que recientemente se ha implementado bajo entorno Windows. El lenguaje se carac-
teriza por soportar todas las propiedades fundamentales de la orientacin a objetos, den-
tro de un entorno integrado de desarrollo, con interfaz interactivo de usuario basado en

menus.
Entre los lenguajes orientados a objetos que se han desarrollado a partir de los
ochenta, destacan extensiones de lenguajes tradicionales tales como C++ y Objective-C
(extensiones de C), Modula-2 y Object Pascal (extensin de Pascal) y reciente-
mente Object Cobol, que a lo largo de 1994 han aparecido sus primeras versiones co-
merciales.
Otro lenguaje orientado a objetos puros es Eiffel, creado por Bertrand Meyer y que
soporta todas las propiedades fundamentales de objetos. Hasta ahora no ha adquirido
popularidad ms que en ambientes universitarios y de investigacin. Sin embargo, la
aparicin en el ao 1995 de la versin 3, que corre bajo Windows, seguramente aumen-
tar su difusin.
Ada ha sido, tambin, un lenguaje en este caso basado en objetos que soporta la
mayora de las propiedades orientadas a objetos. Sin embargo, la nueva versin Ada-95
ya soporta herencia y polimorfismo.

112 Estructura de datos
Algol
Simula
CLU Pascal
Smalltalk C
BASIC
4
Object Pascal
Ada
Actor
Objective-C C++
Visual BASIC 3
Ada-9S Visual BASIC 4
Borland Pascal
Delphi
. Java
Figura 3.8. Evolucin de los lenguajes orientados a objetos.
En los ltimos aos han aparecido lenguajes con soporte de objetos que cada vez se
estn popularizando ms: Clipper 5.2 (ya en claro desuso), Visual BASIC, etc.
De cualquier forma, existe un rE)' actual en los lenguajes orientados a objetos: C++.
La normalizacin por ANSI y AT &T de la versin 3.0 y las numerosas versiones de
diferentes fabricantes, tales como Borland C++ 4.0/4.5/5, Turbo C++ 3.0/3.1 y 4.5, Vi-
sual C++ 4.114.2/5, Symantec 6.0/7.0, etc., hacen que en la segunda mitad de los noven-
ta, c++ ser el lenguaje orientado a objetos ms popular y utilizado en el mundo de la
programacin. A C++ se le ha unido recientemente Java, un lenguaje evolucin de C++,
creado especficamente para programar en Internet pero que puede ser utilizado tambin
en aplicaciones de propsito general.
La evolucin de los lenguajes orientados a objetos se muestra en la Figura 3.8, en
la que se aprecia el tronco comn a todos los lenguajes modernos Algol y las tres
lneas fundamentales: enfoque en Pascal (Ada, Object Pascal), enfoque puro de orien-
tacin a objetos (Simula/Smalltalk) y enfoque en e (Objective-C, C++, Java y Ada-95).
3.11.1. Clasificacin de los lenguajes orientados a objetos
Existen varias clasificaciones de lenguajes de programacin orientados a objetos, aten-
diendo a criterios de construccin o caractersticas especficas de los mismos. Una clasi-
ficacin ampliamente aceptada y difundida es la dada por Wegner y que se ilustra en la
Figura 3.10 8.
8 Wegner, Peter [1987]: Dimensions ofObject-Based Languajes Design. Nmero especial de SIGPLAN
Notices, 1987.

j
I
Abstraccin de datos: tipos abstractos de datos y objetos 113
1957
1958
ALGOL 58
FORTRAN I
FORTRAN 11
1959 LlSP
1960
1961
1962
1963
1964
1965
1966 ALGOL-W
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
Pascal

Oberon
Ada-90
LGOL60
BASIC // CPL
SIMULA I
SIMULA 67
ALGOL
B
Prolog

Smalltalk 80
Object-P
ANSIC++

Modula-3

Prolog++
Quick
Basic
COMTRAN
COBOL
FORTRAN 77

90
LlSP

I

Common
LlSP

EiHel
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
Visual BASle
Object-COBOl
(00 COBOL)
Ada-9S --- _;-_____ _
Delphi

Java
Figura 3.9. Genealoga de los lenguajes de objetos segn Sebesta 9.
9 Esta tecnologa ha sido extrada y modificada ligeramente con lenguajes de los noventa de Robert
W. Sebesta: Concepts o/ Programming Languages, Addison-Wesley, 2." ed., 1993.
114 Estructura de datos
Basados
en objetos
Basados
en clases
+herencia
Orientados
a objetos
Figura 3.10. Clasificacin de lenguajes 00 de Wegner.
La clasificacin de Wegner divide los lenguajes en tres categoras:
l. Lenguajes basados en objetos que soportan objetos. Es decir, disponen de com-
ponentes caracterizados por un conjunto de operaciones (comportamiento) y un
estado.
2. Lenguajes basados en clases que implican objetos y clases. Es decir, disponen
de componentes tipo clase con operaciones y estado comn. Una clase de un
objeto se construye con una interfaz que especifica las operaciones posibles y
un cuerpo que implementa dichas operaciones.
3. Lenguajes orientados a objetos que adems de objetos y clases ofrecen meca-
nismos de herencia entre clases. Esto es, la posibilidad de derivar operaciones y
atributos de una clase (superclase) a sus subclases.
La definicin anterior, pese a su antigedad sigue teniendo vigencia. Existen otras
clasificaciones similares, pero con la inclusin de la propiedad de polimorfismo en la
categora 3, como requisito para ser lenguaje orientado a objetos.
De cualquier forma, hoy da es posible ampliar esa clasificacin de acuerdo a crite-
rios puramente tcnicos y hacer una nueva clasificacin de la categora 3:
3.1. Lenguajes orientados a objetos puros. Soportan en su totalidad el paradigma
de orientacin a objetos:
Smalltalk Eiffel Simula
Abstraccin de datos: tipos abstractos de datos y objetos 115
3.2. Lenguajes orientados a objetos hbridos. Soportan en su totalidad el paradig-
ma de orientacin a objetos sobre un ncleo de lenguaje hbrido:
C++ (extensin de C: Borland C++, Microsoft C++, Turbo C++, Visual C++,
Symantec, Watcom ... ).
Objective-C (extensin de C).
Object COBOL (extensin de COBOL).
Object Pascal (extensin de Pascal: Turbo Borland Pascal).
Visual Object (extensin de Clipper).
Delphi (extensin de Turbo Borland Pascal 7.0).
Java (extensin mejorada de C++).
Ada-95 (extensin de Ada-83).
De cualquier forma, Meyer, creador del lenguaje Eiffel, proporciona unos criterios
para considerar la bondad 10 de un lenguaje orientado a objetos, cuyos complementos
configuran, de hecho, una nueva clasificacin. En este sentido, los criterios recogidos en
[Meyer 88] son los siguientes:
1. La modularizacin de los sistemas ha de realizarse mediante estructuras de da-
tos apropiadas.
2. Los objetos se describen como la implementacin de tipos abstractos de datos.
3. La memoria se gestiona (administra) automticamente.
4. Existe una correspondencia entre tipos de datos no elementales y clases.
5. Las clases se pueden definir como extensiones o restricciones de otras clases ya
existentes mediante herencia.
6. Soportan polimorfismo y ligadura dinmica.
7. Existe herencia mltiple y repetida.
De acuerdo con los criterios de Meyer recogemos en la Tabla 3.3 el cumplimiento de
dichos criterios en los lenguajes 00 y basados en objetos ms populares.
Tabla 3.3. Criterios de Meyer en lenguajes 00 y basados en objetos
1. Modularizacin S S S S S
2. Tipos abstractos de datos S S S S S
3. Gestin automtica de memoria S S En parte S S
4. Slo clases S S En parte S S
5. Herencia No S S S S
6. Polimorfismo (ligadura dinmica) No S S S S
7. Herencia mltiple y repetida No No S S No
10 Meyer, Bertrand: Object Oriented Software Construction, Englewood Cliffs NJ, Prentice-Hall, 1988.


I
116 Estructura de datos
3.12. DESARROLLO TRADICIONAL FRENTE A DESARROLLO
ORIENTADO A OBJETOS
El sistema tradicional del desarrollo del software para un determinado sistema, es la
subdivisin del mismo en mdulos, a la cual deben aplicarse criterios especficos de
descomposicin, los cuales se incluyen en metodologas de diseo. Estos mdulos se
refieren a la fase de construccin de un programa, que en el modelo clsico sigue a la
definicin de los requisitos (fase de anlisis).
El modelo clsico del ciclo de vida del software no es el nico modelo posible,
dado que es posible desarrollar cdigo de un modo evolutivo, por refinamiento y proto-
tipos sucesivos. Existen numerosos lenguajes de programacin y metodologas que se
han desarrollado en paralelo a los mismos, aunque, normalmente, con independencia
de ellos.
En esta seccin nos centraremos en la metodologa ms utilizada denominada desa-
rrollo estructurado, que se apoya esencialmente en el diseo descendente y en la pro-
gramacin estructurada.
La programacin estructurada es un estilo disciplinado de programacin que se si-
gue en los lenguajes procedimentales (por procedimientos) tales como FORTRAN, BA-
SIC, COBOL, C y C++.
Las metodologas diseo descendente (o descomposicin funcional) se centran en
operaciones y tienden a descuidar la importancia de las estructuras de datos. Se basan
en la clebre ecuacin de Wirth:
Datos + Algoritmos = Programas
La idea clave del diseo descendente es romper un programa grande en tareas ms
pequeas, ms manejables. Si una de estas tareas es demasiado grande, se divide en
tareas ms pequeas. Se contina con este proceso hasta que el programa se comparti-
mentaliza en mdulos ms pequeos y que se programan fcilmente. Los subprogramas
facilitan el enfoque estructurado, y en el caso de lenguajes como C, estas unidades de
programas, llamadas funciones, representan las citadas tareas o mdulos individuales.
Las tcnicas de programacin estructuradas reflejan, en esencia, un modo de resolver un
programa en trminos de las acciones que realiza.
Para comprender mejor las relaciones entre los algoritmos (funciones) y los datos,
consideremos una comparacin con el lenguaje natural (por ejemplo Espaolo Ingls),
que se compone de muchos elementos, pero que reflejar poca expresividad si slo se
utilizan nombres y verbos. Una metodologa que se basa slo en datos o slo en proce-
dimientos es similar a un lenguaje (idnea) en el que slo se utilizan nombres o verbos.
Slo enlazando nombres o verbos correctos (siguiendo las reglas semnticas), las expre-
siones tomarn formas inteligibles y su proceso ser ms fcil.
Las metodologas tradicionales se vuelven poco prcticas cuando han de aplicarse a
proyectos de gran tamao. El diseo orientado a objetos se apoya en lenguajes orienta-
dos a objetos, que se sustentan fundamentalmente en los tipos de datos y operaciones
Abstraccin de datos: tipos abstractos de datos y objetos 117
que se pueden realizar sobre los tipos de datos. Los datos no fluyen abiertamente en un
sistema, como ocurre en las tcnicas estructuradas, sino que estn protegidos de modifi-
caciones accidentales. En programacin orientada a objetos, los mensajes (en vez
de los datos) se mueven por el sistema. En lugar del enfoque funcional (invocar una
funcin con unos datos), en un lenguaje orientado a objetos, se enva un mensaje a un
objeto.
De acuerdo con Meyer, el diseo orientado a objetos es el mtodo que con-
duce a arquitecturas de software basadas en objetos que cada sistema o subsistema
evala.
Recordemos, qu son los objetos? Un objeto es una entidad cuyo comportamiento
se caracteriza por las acciones que realiza. Con ms precisin, un objeto se define como
una entidad caracterizada por un estado; su comportamiento se define por las operacio-
nes que puede realizar; es una instancia de una clase; se identifica por un nombre; tiene
una visibilidad limitada para otros objetos; se define el objeto mediante su especifica-
cin y su implementacin.
Una definicin muy elaborada se debe a Meyer: Diseo orientado a objetos, es la
construccin de sistemas de software como colecciones estructuradas de implementa-
ciones de tipos de datos abstractos.
La construccin de un sistema se suele realizar mediante el ensamblado ascen-
dente (abajo-arriba) de clases preexistentes. Las clases de un sistema pueden tener entre
s relaciones de uso (cliente), relaciones de derivacin (herencia) o relaciones de agre-
gacin (composicin) o, incluso, slo relaciones de asociacin. As, por ejemplo, con
una relacin de cliente, una clase puede utilizar los objetos de otra clase; con una rela-
cin de herencia, una clase puede heredar o derivar sus propiedades definidas en otra
clase.
El hardware se ensambla a partir de componentes electrnicos, tales como circuitos
integrados (chips), que se pueden utilizar repetidamente para disear y construir conjun-
tos mucho ms grandes, que son totalmente reutilizables. La calidad de cada nivel de
diseo se asegura mediante componentes del sistema que han sido probados previamen-
te a su utilizacin. El ensamblado de componentes electrnicos se garantiza mediante
interfaces adecuados.
Estos conceptos se aplican tambin con tecnologas de objetos. Las clases (tipos de
objetos) son como los chips de hardware, Cox les llam chips de software, que no slo
se pueden enlazar (ensamblar) entre s, sino que tambin se pueden reutilizar (volver a
utilizar). Las clases se agruparn, normalmente, en bibliotecas de clases, que son com-
ponentes reutilizables, fcilmente legibles.
En la actualidad, existen gran cantidad de software convencional, en su mayora es-
crito normalmente para resolver problemas especficos; por esta razn, a veces es ms
fcil escribir nuevos sistemas que convertir los existentes.
Los objetos al reflejar entidades del mundo real permiten desarrollar aplicaciones
creando nuevas clases y ensamblndolas con otras ya existentes. Normalmente, los de-
sarrolladores experimentados gastan un porcentaje alto de su tiempo (20 al 40 por 100)
en crear nuevas clases y el tiempo restante en ensamblar componentes probados de siste-
mas, construyendo sistemas potentes y fiables.
118 Estructura de datos
3.13. BENEFICIOS DE LAS TECNOLOGAS DE OBJETOS
Una pregunta que hoy da se hacen muchos informticos es: Cul es la razn para
introducir mtodos de ro en los procesos de desarrollo? La principal razn, sin lugar a
dudas, son los beneficios de dichas TO: aumento de la fiabilidad y productividad del
desarrollador. La fiabilidad se puede mejorar debido a que cada objeto es simplemente
una caja negra con respecto a objetos externos con los que debe comunicarse. Las
estructuras de datos internos y mtodos se pueden refinar sin afectar a otras partes de un
sistema (Figura 3.11).
Los sistemas tradicionales, por otra parte, presentan, con frecuencia, efectos latera-
les no deseados. Las tecnologas de objetos ayudan a los desarrolladores a tratar la com-
plejidad en el desarrollo del sistema.
La productividad del desarrollador se puede mejorar debido a que las clases de obje-
tos se pueden hacer reutilizables de modo que en cada subclase o instancia de un objeto
se puede utilizar el mismo cdigo de programa para la clase. Por otra parte, esta produc-
tividad tambin aumenta debido a que existe una asociacin ms natural entre objetos
del sistema y objetos del mundo real.
Objeto
Mtodos
Datos
Figura 3.11. El objeto como caja negra.
Programa Programa
Datos
Figura 3.12. Proceso tradicional de datos.
Abstraccin de datos: tipos abstractos de datos y objetos 119
Taylor" considera que los beneficios del modelado y desarrollo de objetos son:
l. Desarrollo ms rpido.
2. Calidad ms alta.
3. Mantenimiento ms fcil.
4. Coste reducido.
5. Incremento en escalabilidad.
6. Mejores estructuras de informacin.
7. Incremento de adaptabilidad.
Sin embargo, Taylor
'2
tambin considera algunos inconvenientes, aunque algunos de
ellos ya han sido superados o al menos reducido su impacto.
l. Inmadurez de la tecnologa (hoy da ya no se puede considerar as).
2. Necesidades de estndares (el grupo OMG es una realidad).
3. Necesidad de mejores herramientas.
4. Velocidad de ejecucin.
5. Disponibilidad de personal cualificado.
6. Coste de conversin.
7. Soporte para modularidad a gran escala.
La Figura 3.13 muestra los beneficios genricos de las tecnologas de objetos.
Reutilizacin. Las clases se construyen a partir de otras clases.
Sistemas ms fiables.
Proceso de desarrollo ms rpido.
Desarrollo ms flexible.
Modelos que reflejan mejor la realidad.
Mejor independencia e interoperatividad de la tecnologa.
Mejor informtica distribuida y cliente-servidor.
Bibliotecas de clases comerciales disponibles.
Mejor relacin con los clientes.
Mejora la calidad del producto software terminado.
Figura 3.13. Beneficios de las tecnologas de objetos.
11 Taylor, David A. : Object-Ori ented Technology Reading, MA: Addison-Wesley, 1992, pgi-
nas 103-107.
12 [bd., pgs. 108-113.
120 Estructura de datos
RESUMEN
Este captulo examina el concepto fundamental de la orientacin a objetos, el tipo abstracto de
datos. Los tipos abstractos de datos (TAD) describen un conjunto de objetos con la misma repre-
sentacin y comportamiento. Los tipos abstractos de datos representan una separacin clara entre
la interfaz externa de un tipo de datos y su implementacin interna. La implementacin de un tipo
abstracto de datos est oculta. Por consiguiente, se pueden utilizar implementaciones alternativas
para el mismo tipo abstracto de dato sin cambiar su interfaz.
En la mayora de los lenguajes de programacin orientados a objetos, los tipos abstractos de
datos se implementan mediante clases (unidades en Pascal, mdulos en Modula-2, paquetes en
Ada).
En este captulo se considera tambin una introduccin a los mtodos de desarrollo orien-
tados a objetos. Se comienza con una breve revisin de los problemas encontrados en el desa-
rrollo tradicional de software, que condujeron a la crisis del software y que se han mantenido
hasta los aos actuales. El nuevo modelo de programacin se apoya esencialmente en el concepto
de objetos.
La orientacin a objetos modela el mundo real de un modo ms fcil a la perspectiva del
usuario que el modelo tradicional. La orientacin a objetos proporciona mejores tcnicas y para-
digmas para construir componentes de software reutilizables y bibliotecas ampliables de mdulos
de software. Esta caracterstica mejora la extensibilidad de los programas desarrollados a travs
de metodologas de orientacin a objetos. Los usuarios finales, programadores de sistemas y de-
sarrolladores de aplicaciones, se benefician de las tecnologas de modelado y programacin orien-
tadas a objetos.
Los conceptos fundamentales de orientacin a objetos son tipos abstractos de datos, herencia
e identidad de los objetos. Un tipo abstracto de datos describe una coleccin con la misma estruc-
tura y comportamiento. Los tipos abstractos de datos extienden la nocin de tipos de datos ocul-
tando la implementacin de operaciones definidas por el usuario (mensajes) asociados con los
tipos de datos. Los tipos abstractos de datos se implementan a travs de clases. Las clases pueden
heredar unas de otras. Mediante la herencia, se pueden construir nuevos mdulos de software
(tales como clases) en la parte superior de una jerarqua existente de mdulos. La herencia permi-
te la comparticin de cdigo (y por consiguiente reutilizacin) entre mdulos de software. La
identidad es la propiedad de un objeto que diferencia cada objeto de los restantes. Con la identi-
dad de un objeto, los objetos pueden contener o referirse a otros objetos. La identidad del objeto
organiza los objetos del espacio del objeto manipulado por un programa orientado a objetos.
Este captulo examina el impacto de las tecnologas orientadas a objetos en lenguajes de pro-
gramacin, as como los beneficios que producen en el desarrollo de software.
Los conceptos de la programacin orientada a objetos se examinan en el captulo; si no ha
ledo hasta ahora nada sobre tecnologas de objetos, deber examinar con detenimiento todos los
elementos conceptuales del captulo.
EJERCICIOS
3.1. Construir un tipo abstracto lista enlazada de nodos que contienen enteros.
3.2. Disear un tipo abstracto de datos pila de nmeros enteros y que al menos soporte las si-
guientes operaciones:
Borrar:
Copiar:
Meter:
Sacar:
Longitud:
Llena:
Vaca:
Igual:
Abstraccin de datos: tipos abstractos de datos y objetos 121
Eliminar todos los nmeros de la pila.
Hace una copia de la pila actual.
Aadir un nuevo elemento en la cima de la pila.
Quitar un elemento de la pila.
Devuelve un nmero natural igual al nmero de objetos de la pila.
Devuelve verdadero si la pila est llena (no existe espacio libre en la pila).
Devuelve verdadero si la pila est vaca y falso en caso contrario.
Devuelve verdadero si existen dos pilas que tienen la misma profundidad y las
dos secuencias de nmeros son iguales cuando se comparan elemento a ele-
mento desde sus respectivas cimas de la pila; falso en caso contrario.
3.3. Crear un tipo abstracto Cola que sirva para implementar una estructura de datos cola.
3.4. Crear un TAD para representar:
Un vector (representacin grfica y operaciones).
Una matriz y sus diferentes operaciones.
Un nmero complejo y sus diferentes operaciones.
3.5. Crear un TAD que represente un dato tipo cadena (string) y sus diversas operaciones:
clculo, longitud, buscar posicin de un carcter dado, concatenar cadenas, extraer una sub-
cadena, etc.

PARTE

,
CAPITULO
structuras e atos
. , .
lnamlcas:
,
un teros
[,'., :", . . '0 , .,- .:.-._;_, .'_ _ _ _M ~ _
" ' , -- - -- f J , "
1. 'F:i-., '. ,. - -,":.--
CONTENIDO
4.1. Estructuras de datos dinmicas.
4.2. Punteros (apuntadores).
4.3. Operaciones con variables puntero: los procedimientos new y dispose.
4.4. El tipo genrico puntero (pointer).
4.5. La asignacin de memoria en Turbo Pascal.
RESUMEN.
EJERCICIOS.
PROBLEMAS.
Los punteros son el ltimo de los tipos de datos incorporados a Pascal.
Un puntero es un tipo de dato simple que contiene la direccin de una
variable o estructura en vez de un valor de dato. Los punteros tienen
dos propsitos principales: hacer los programas ms eficientes y cons-
truir estructuras muy complejas. En el captulo se examina tambin la
gestin dinmica de memoria y el modo en que se puede manipular. Se
ver cmo utilizar variables dinmicas para construir estructuras de
datos que pueden crecer y disminuir conforme se ejecuta el programa.
Las estructuras de datos dinmicas son una coleccin de elemen-
tos (denominados nodos) que son nodos, en contraste a un array que
siempre contiene almacenamiento para un nmero fijo de elementos.
4.1. ESTRUCTURAS DE DATOS DINMICAS
Todas las variables y estructuras de datos que se han considerado hasta este momento
han sido estticas. Con una variable esttica, la cantidad de memoria (espacio) ocupada
debe ser declarado por anticipado y no puede ser incrementado durante la ejecucin del
programa si se necesitara ms espacio de memoria.
125

126 Estructura de datos


Un array de requisitos es esttico dado que la cantidad exacta de memoria se fija por
la declaracin del tamao del array. Esta falta de flexibilidad puede ser una desventaja
notable. As, por ejemplo, si en un array de registros se declara para un tamao mximo
de 1.000 registros, el programa no funcionar si se deben almacenar ms de 1.000 regis-
tros en ese array. Por otra parte, si el tamao mximo declarado para un array es mucho
mayor que el total de espacio de memoria requerido, el programa utilizar ineficiente-
mente la memoria, dado que la cantidad de memoria especificada en la declaracin se
reservar, incluso aunque slo se utilice una pequea parte.
Los punteros (apuntadores) 1 permiten la creacin de estructuras de datos dinmi-
cas: estructuras de datos que tienen capacidad de variar en tamao y ocupar tanta
memoria como utilicen realmente. Las variables que se crean y se destruyen durante la
ejecucin se llaman variables dinmicas (tambin annimas). As, durante la ejecu-
cin de un programa, puede haber una posicin de memoria especfica asociada con
una variable dinmica y posteriormente puede no existir ninguna posicin de memoria

asociada con ella.
Pascal proporciona los mtodos para asignar y liberar espacio de memoria utilizando
punteros y los procedimientos predefinidos new y dispose.
Al contrario que las estructuras de datos estticas, tales como arrays cuyos tamaos
y posiciones de memoria asociados se fijan en tiempo de compilacin, las estructuras
dinmicas de datos se amplan (expanden) o reducen (contraen) a medida que se requie-
ra durante la ejecucin y cambia sus posiciones de memoria asociada.
Una estructura de datos dinmica es una coleccin de elementos llamados nodos de
la estructura normalmente de tipo registro que se enlazan o encadenan juntos. Este .
enlace se establece asociando con cada nodo un puntero que apunta al nodo siguiente de
la estructura.
Existen diferentes tipos de estructuras dinmicas de datos, siendo las ms notables y
significativas las listas enlazadas, los rboles y los grafos.
Las estructuras de datos dinmicas son tiles especialmente para almacenar y proce-
sar conjuntos de datos cuyos tamaos cambian durante la ejecucin del programa, por
ejemplo, el conjunto de trabajos que se han introducido en una computadora y estn
esperando su ejecucin o el conjunto de nombres de pasajeros y asignacin respectiva
de asientos de un vuelo de avin determinado. En este captulo se estudiarn los punte-
ros y los procedimientos new y dispose, as como el mtodo que se puede utilizar
Siguiente Siguiente Siguiente Siguiente
Datos Datos Datos Datos
Nodo1 Nodo2 Nodo3 Nodo4 ...
Figura 4.1. Representacin de una lista enlazada.
I En Latinoamrica, el trmino utilizado para definir este concepto es apuntador.

Estructuras de datos dinmicas: punteros 127
para construir y procesar estructuras dinmicas de datos, junto con la estructura dinmi-
ca de datos, por excelencia, la lista enlazada.
4.2. PUNTEROS (APUNTADORES)
En una computadora cada posicin de memoria tiene una direccin y un valor especfico
almacenado en esa posicin. Se han utilizado nombres de variables en lugar de direccio-
nes porque los nombres son ms fciles de recordar. Para almacenar un nuevo valor en
memoria se asigna a una variable, y la computadora enva una direccin a la memoria
seguida por el valor a almacenar en esa posicin.
El tipo puntero es un tipo de datos simple en Pascal; es simple debido a que no se
puede romper en otros componentes pequeos como es el caso de un array o un registro.
Los punteros en esencia son un tipo especial de variable (esttica) que se utiliza para
almacenar la direccin de memoria de otra variable, o 10 que es igual, su valor es una
direccin de una posicin de memoria donde est almacenada otra variable. Las varia-
bles utilizadas para almacenar direcciones en vez de valores convencionales se denomi-
nan variables puntero o simplemente puntero (apuntador).

1747 (direccin)
2014 (valor)
un puntero
p
2014 (direccin)
2587 (valor)
una var dinmica
pl\
Al definir un tipo puntero se debe indicar el tipo de valores que se almacenarn en
las posiciones designadas por los punteros. La razn es que los diferentes tipos de datos
requieren diferentes cantidades de memoria para almacenar sus constantes, una variable
puntero puede contener una direccin de una posicin de memoria adecuada slo para
un tipo dado. Por esta razn se dice que un puntero apunta a una variable particular, es
decir, a otra posicin de memoria.
, . ,.
. . . , .
. . . . .. ..
Una
.. ,"," .. -'"""'
4.2.1. Declaracin de punteros
Un puntero es una variable que se utiliza para almacenar la direccin de otra variable.
Sin embargo, el puntero en s no es normalmente lo que le interesa ms; sino que el
inters reside en la celda (direccin de memoria) apuntada por l. Es decir, es preciso
diferenciar entre las dos entidades implicadas en el apuntamiento: la variable puntero
(quin hace el apuntamiento) y la variable apuntada (a quin se apunta).
128 Estructura de datos
Un tipo de dato puntero se especifica utilizando el smbolo de circunflejo (") seguido
por un identificador de tipo. Su formato es:
Ai dent if icador- t i po
Se puede declarar un puntero a una variable carcter, un puntero a un array de ente-
ros, un puntero a un registro o un puntero a cualquier otro tipo. En general, se pueden
declarar variables puntero que apunten a cualquier tipo de dato, incluso otros punteros.
La declaracin de una variable a un puntero se realiza con el formato siguiente:
var
Nombre-var i able : Aidentificador -tipo
var
Ptr: ATipoElement o
La variable Ptr apunta a un tipo de dato TipoElemento
EJEMPLO 4.1
var
P : Al n teger;
Los punteros se pueden representar mediante diagramas grficos:
P
Por ejemplo, la variable P contiene 0591 64 que es la direccin de memoria donde est
la variable entera apuntada 345.
059164
P est en la
direccin 034405
345
variable entera en la
direccin 059164 pA
Un puntero apunta hacia (a) otra variable cuando contiene la direccin de esa va-
riable.
Estructuras de datos dinmicas: punteros 129
p
variable entera a la que
apunta el puntero P
...
345
Es muy til crear un identificador de tipo para los tipos de datos puntero. Se puede crear
dicho identificador y utilizar ese identificador para crear variables punteros .
,'JO - _.
tyPe ....
. -. ,. .:
.' ' ''-''"': ..
. - ' --".,_ .
. ,.
..-.' .
nbmbr e :" tipo: Aidentificdor-t i po;
,
.---_ . ,
var .
," . -..
. noinbre-v?r-pt:r : nombf:e-'tipo; ' ",>", ;
EJEMPLO 4.2
Supongamos que se desean almacenar nmeros reales utilizando aplicacin de memo-
ria dinmica. Las variables A y B son variables punteros que apuntan a datos reales.
type
Pu n t ero Real = ARe a l;
var
A, B: Punter oRea l ;
1. type
Tipo_Pu n tero = Ai n teger ;
var
P: Tipo_Punt ero ;
2. var
P : Al ntege r;
3. type cad4 0 = s tr ing [ 40 1;
var ptr : Acad40 ;
ql , q2: Ar ea l;
4. type
Punt e r oRea l = ARea l ;
var
P: Pun teroReal ;
R: Real;
type
PunteroEnt = Ai nt eger ;
real
A
B
--- ."
real
declara tres variables puntero:
p t r apunta a valores cadena
ql, q2 apuntan a valores reales
puntero a reales
P es una variable puntero de tipo
PunteroReal
130 Estructura de datos
5. var
Pr imero :
Si g o Pun teroEn t ;
4.3. OPERACIONES CON VARIABLES PUNTERO:
LOS PROCEDIMIENTOS NEW Y DISPOSE
Los punteros se crean con las declaraciones citadas:
type
Puntero Rea l =
var
P : Pun t eroRea l ;
P es una variable puntero de tipo PunteroReal que apunta a posiciones que contie-
nen reales. La posicin de memoria designada por el valor de la variable puntero P se
representa por v'. La Figura 4.2 representa la relacin entre P y P".
Como P" designa una posicin de memoria, se puede utilizar como cualquier otra
variable Pascal. Se pueden asignar valores a P " y utilizar valores de P " en expresiones
tal como cualquier otra variable. Si P apunta a posiciones que contienen reales, P " es
una variable real. As, en la Figura 4.2 el valor de P " es 3.500.
Sin embargo, estas operaciones no se pueden realizar directamente tras la declaracin,
debido a que el objeto o direccin apuntada p A no tiene existencia. Antes de que un
programa utilice un puntero, se requiere primero espacio para el tipo de datos objeto de
la direccin del puntero. En otras palabras, un programa debe inicializar sus punteros
-su declaracin no basta ; para iniciar un puntero se debe utilizar el procedimiento
New.
4.3.1. Procedimiento New
La declaracin de una variable puntero P no crea una celda de memoria para apuntar a
ella. El procedimiento (sentencia) New se utiliza para crear tal celda de memoria P; es
decir el procedimiento New crea una nueva variable dinmica y establece que una varia-
ble puntero apunte a ella.
1000
3 * + 500
el valor de es 1000
toma el valor 3500
3500
Figura 4.2. Diferencia entre P y P".
Estructuras de datos dinmicas: punteros 131
Formato
New (P)
p variable puntero
La sentencia N ew ( P ) ; llama al procedimiento N ew que asigna almacenamiento para
un valor del tipo determinado y sita la direccin de esta celda de memoria en la variable
puntero P. Una vez que se asigna almacenamiento para un valor de tipo determinado al
que est apuntando P, se puede almacenar un valor en esa celda de memoria y manipu-
larlo. La posicin exacta de la memoria de esta celda particular es indiferente.
La nueva variable creada es la ya conocida con el smbolo P A. La llamada a N ew
exige que exista suficiente espacio de memoria libre en el montculo la pila de varia-
bles dinmicas (heap) para asignar a la nueva variable. En caso contrario se producir
un error en tiempo de ejecucin.
Se puede representar el valor de una variable puntero por una flecha dirigida a una
celda de memoria. El diagrama
p

?

muestra que la variable puntero P apunta a una celda de memoria cuyo contenido se
desconoce. Esta es la sentencia que existe inmediatamente despus de que se ejecuta
New (P) .
El smbolo P A se utiliza para referenciar a la celda de memoria apuntada por la va-
riable puntero P. El smbolo A (circunflejo) se denomina operador de indireccin o de
desreferencia.
La sentencia de asignacin
almacena el valor real 25.0 en la posicin (celda) de memoria apuntada por P.
p
25.0
Como P A se considera una variable, podr ser visualizado su valor
Wr i t e ( P A : 10 : 2 ) ; visualiza el valor 25.0
132 Estructura de datos
Atencin
P:= 25 .0;
Write (P : I0 : 2) ;
asignacin no vlida
sentencia no vlida
Ambas sentencias son no vlidas debido a que no se puede almacenar un valor de
tipo Real en una variable puntero P, ni se puede visualizar el valor (una direccin)
de una variable puntero.
Funcionamiento de New (P)
.. - . - -
,e ,--,_:','-_--, , ___ 'i",- -,., . . '<':,-. ,<-.': __ -- __ ;_: __ .J', . ;', .'-' -:: __, --, __ '_, < ' ,_'.' ,
l.
,:' ' ,,' < :':' ' '' 1<, ;\ ' f ' i':t "' , , ':' : ' ', ,: .:' ,,1 ' ,, ' , l . . . ' "
.' f . , memoria se crea una luira-
, , " "'bl ' :'='d" ... :."." .... ..':' .... 1)/'\""""':' -::''':' ,:' "" ",:"':< .. ,'::' ',' '_,",- ',' .. ... <. , ,,I""":f;!- ,.", ';' :, .,. , ... . <
. e . lnanuca J: ,. .... <,' ... ,',.ij;';>." ,. > ,, ,' ,' ," ." , , .. '" ,' , '
" .. ,.:".,- ',," , ;' !.'. . '"'..>i: ...?:.';::::',::. '-, __ ,, " ' ;, ,- , . " \ '<':"1 . .', ,' ,':
,,:: _" ,,' "
'ri'.!;.- ;'",:"if: ::' , .. :; " ' , j'-:, "f>
,
, . ".
.. "
i, "r-----....... -- :. " .. "" ... ,
. - ! ,
, ..
. ! ,
," '- ,
,
't' - . .'
...
, "

" .. " -_: - ---
P
,
, '
,. ,1 . -
."... ,<, -l;: \ .;h.' "'!'iiw.;. ..... , ",,",,,-, ' ''',,+__ . -f' ,,-,_."' _ -- , -_ . _------
<
EJEMPLO 4.3
A la posicin o celda de memoria a que apunta un puntero se puede acceder situando un
smbolo A despus del nombre de la variable puntero. Por ejemplo,
new (Ptr) ;
'Mckenna ';
La sentencia new (pt r) crea una celda de memoria vaca (o con basura) a la que apun-
ta Ptr. La segunda sentencia sita el valor I Mckenna I en esa celda de memoria. Un
diagrama grfico sera:
Ptr
Mc Kenna
Implementacin interna
Internamente, los punteros se implementan teniendo en cuenta las direcciones de memo-
ria a las que se apunta. Por ejemplo, supongamos que la direccin de p tres 1015 Y
que la celda de memoria que crea new (ptr) est en la direccin 1256. Por consigUien-
te, el efecto de
- __ o
__ _ _ o
Estructuras de datos dinmicas: punteros 133
new (ptr) ;
p t r
A
: = ' McKe nna ';
se puede dibujar a nivel de direcciones de memoria, como se muestra a la izquierda,
con el diagrama ms sencillo de la derecha.
Direcc i n 10 1 5 Direccin 1256
12 56 McKenna Mc Ke nna
Pt r Ptr
Atencin
Observe que en la declaracin de un puntero, el circunflejo est situado a la izquierda de
su tipo, mientras que en una sentencia en que se accede a la celda de memoria a que se
est apuntando, el circunflejo aparece a la derecha.
LO 4.4
Realizar el seguimiento del segmento de programa.
var
1. Pt r1 : Ac ha r;
2. Pt r2 : A int eger ;
begin
3. Ne w (Ptr 1) ;
4. Ptr l " : = ' B';
5. New (Ptr 2);
6. Pt r 2A := 86 ;
LO 4.5
Deducir la salida del siguiente programa.
program Pun ter o ;
type
Ptrint = Ai nt e ger;
var
l , J : Pt rint ;
N: int e g er ;
begin
Ne w ( l) ;
N ew (J) ;
N : = 5 ;
l
A . - N'
. - ,
Wri t e Ln
J
.- l' . - ,
J
A .- - 7 '
. - ,
Wri teLn
end.
( l A ) ;

134 Estructura de datos
EJEMPLO 4.6
Qu se imprime tras ejecutar el siguiente programa?
program Prueba Si mp l e ;
var p, q : Ainteger;
x, y : int ege r;
begin
new(P );
P
A._ 5 .
. - ,
X: ::::: p '" + 1;
Y
- pA .
. - ,
new (q) ;
qA: = y + 3;
WriteLn (x, " , y, " , pA, " , qA)
end.
Solucin
6 5 5 8
La distribucin grfica es:
x 6
y 5
P
q
4.3.2. Variables de puntero con registros
5
8
Las variables de puntero pueden contener la direccin de tipos de datos simples o datos
de tipo compuesto. En las estructuras dinmicas de datos es frecuente el uso de registros
como elementos. Se suelen conocer con el nombre de nodos, aunque en realidad el tr-
mino se extiende tanto a datos simples como compuestos. Por su importancia, y aunque
la manipulacin es idntica a la ya estudiada, consideraremos un ejemplo con variables
dinmicas tipo registro.
EJEMPLO 4.7
Cul es la salida de este programa?
program Test ;
type
Estudiante = record
Letr a : char;
Edad: int eger
end;
Pu n tEstu = A Estudi a nt e;
var
PI , P2 : PuntEs t u ;
begin
N ew (P 1 ) ;
Pl A. Edad
PI
A
.Letra
- l'
- ,
.- 'A"
- ,
WriteLn (PlA.Edad , Pl A. Letra) ;
New (P2) ;
P2
A
.Edad = 2
,
P2
A
. Letra : = 'B ';
Wr i teLn (P2
A
.Edad, P2
A
.Letra);
PI := P2 ;
P2
A
.Edad - 3 - ,
P2
A
. Letra := 'C' ;
Estructuras de datos dinmicas: punteros 135
Wr it eLn (PlA . Edad, PI
A
. Letra , P2
A
. Edad , P2
A
.Letra)
end.
Ejecucin
lA
28
3C3C
4.3.3. Iniciacin y asignacin de punteros
Antes de intentar referirse a valores de variables es preciso, como siempre, inicializar
las variables. Los pasos a dar se muestran en las siguientes sentencias:
var
P : Ainteger;



New (P) ;



. - 17 '
- ,
En un puntero (P) se deben considerar dos valores:
Puntero (P)
P"
---".
Su valor es la posicin (direccin) de una variable integer.
El valor de la variable integer propiamente dicho.
P (flecha que apunta a la posicin de una
variable de memoria)
P " (contenido de esa memoria)
El procedimiento new inicializa el puntero con la direccin de una variable integer.
La variable integer, P", a la que P apunta debe tambin ser inicializada (P" : = 1 7 ) .

136 Estructura de datos


Recuerde
Write (PA)
Wr i te (P)
Asignacin
sen t enci a vl i da
sentenci a no vl ida (error)
Las variables dinmicas pueden tener ms de un puntero que est apuntando a ellas.
Tambin los punteros pueden ser modificados de modo que apunten a variables dinmi-
cas diferentes en momentos diferentes.
Estos cambios se pueden realizar con el operador de asignacin (:=). Estudiemos las
asignaciones posibles.
(1) p : = q (2)
(1) Los punteros p y q apuntan a la misma posicin; por consiguiente, p A Y q A
designan la misma posicin y tienen el mismo valor.
(2) El valor de q A se asigna a p A; despus de la asignacin, p A Y q A tienen el
mismo valor, sin embargo, p A Y q A permanecen en distintas posiciones de

memona ..
\ . ~ ~ ~ - - .
~ ; . .'.""" ::', _-- ' :--i.".
No se
diferente . .
4.8
'. . . . ,

. :,;
.. -, -
" , , .' ",:. " " , ....... . ' .
, . " i : " ." " , ' " , - ,
Pl Y P2 son punteros de tipo entero. Qu se imprimir tras la ejecucin del siguiente
segmento de programa? y cmo ser la distribucin en memoria?
new ( p I ) ;
new ( p 2) ;
PIA := 86 ;
P2
A
:= 50 ;
P I:: P2 ;
No se puede acceder a este valor-----
Writ e Ln (PIA, " , P2A) ;
Solucin
50 50 PI
86
P2
5 0
Estructuras de datos dinmicas: punteros 137
4.3.4. Procedimiento oispose
El procedimiento dispose libera la posicin de memoria ocupada por una variable
dinmica.
Formato
dispose (p)
p variable puntero
Dispose destruye la variable referenciada por P y devuelve su zona de memoria a la
pila dinmica (heap). Despus de una llamada a dispose, el valor de P se vuelve indefi-
nido y cualquier intento de referenciar a P/\ producir un error.
En resumen, Dispose produce las siguientes acciones:
l. La posicin de memoria cuya direccin se almacena en P se libera de la memo-
ria montculo (heap). En otras palabras, P A deja de existir.
2. P se vuelve indefinido.
La representacin grfica es:
p
situacin inicial
?

situacin despus de di spose (p)
p
EJEMPLO 4.9
1. var
p,
Q: Ainteger;
begin
2. New ( p) ;
3.
p A
-
8 ;
-
4. Q - P;
-
5.
QA
- 5 ;
-
6. Dispos e ( P)
end

I



138 Estructura de datos
4.3.5. Constante ni 1
Pascal proporciona una constante predefinida, nil (nulo). La constante nil se utiliza para
dar un valor a una variable puntero que no apunta a ninguna posicin, nil puede ser
asignada a un puntero de cualquier tipo.
p: = nil
Como ni 1 no apunta a ninguna posicin de memoria, una referencia a p " es ilegal
si el valor de p es nil.
p : = ni 1;
p '" : = 5; es ilegal ya que se instruye a la computadora a almacenar 5 en la
posicin apuntada por p, pero debido a la primera sentencia (p: =nil),
p no apunta a ninguna direccin
EJEMPLO 4.10
El segmento de programa
var
p : Ac ha r;
begin
p := nil;
if p = nil
then
WriteLn ( ' e l puntero P n o apunta a nada')
else
Wr i t e Ln ( ' P se qu eda i ndef ini d o apunta ' ) ;
proporciona la salida
el p unt e r o P no apunta a nada
.',.- .. -.
4.3.6. Naturaleza dinmica de los punteros
,
,
,_o ,.- .
. . , .
.... ........... ij. JC

Las variables a las que se apuntan no estn declaradas. Unicamente las variables a las
que se apunta se declaran. As, una sentencia como:
New (P) ;
se puede ejecutar muchas veces dentro de un programa simple; cada vez que se ejecuta,
crea una nueva celda de memoria. En consecuencia no existe lmite declarado para saber
cuntas celdas de memoria se pueden crear utilizando unos pocos punteros.
Estructuras de datos dinmicas: punteros 139
Los arrays se dice que son estticos debido a que la cantidad mxima de espacio de
memoria que se puede utilizar debe ser declarado por anticipado. Los punteros son din-
micos ya que no hay tal lmite previo, el espacio de memoria se crea durante la ejecucin
del programa.
4.3.7. Comparacin de punteros
Los punteros pueden ser comparados slo en expresiones de igualdad. As, en el caso de
var
Pu nt eroA, Pun teroB: Ainteger;
las comparaciones:
if ( PunteroA = Punter oB)
then < sentenc i a >;
if ( Pu nteroA <> Punt eroB)
then < sent e n cia > ;
No se puede comparar la ordenacin de punteros con los operadores de relacin
<, >, <= y >=.
No existe ningn problema para comparar los objetos direccionados por los punte-
ros. La lnea siguiente es vlida.
if ( Pun teroA
A
<= Punt eroB
A
)
then < sentenc i a >
Si dos punteros PI y P2 son del mismo tipo, el efecto de
Pl : = P2 ;
redirige PIde modo que apunta a la celda de memoria apuntada por P 2. Despus de la
ejecucin de PI: = P2, ambos punteros apuntan a la misma celda.
Se dice que dos punteros son iguales si ambos apuntan precisamente al mismo ele-
mento de datos. En un diagrama ambos apuntan a la misma caja.
Pl
25
P2
,

1

j
1
, 1

,

Estructuras de datos dinmicas: punteros 141


La traza de memoria es
La salida ser
Concha
Concha
p
q
p
Carpe
q
Dien

4.3.8. Paso de punteros como parmetros


Concha
Dien
El paso de parmetros es, como conoce el lector, una tcnica poderossima para proce-
sar informacin. El paso de punteros se realiza como cualquier otro tipo de dato, con
la salvedad de que cuando se pasa un puntero como un parmetro, se est pasando el
puntero, no el objeto al que apunta. En el caso de una lista enlazada, el paso de la
cabeza o cabecera de la lista no pasa la lista en s, slo el puntero a su primer ele-
mento.
El caso ms sencillo es cuando se pasa el puntero como un parmetro varo Al igual
que en otros casos similares, todos los cambios realizados a los parmetros formales se
harn tambin al parmetro real. Normalmente se utiliza un parmetro var cuando se
espera que el procedimiento cambie el puntero.
Ms complejo es el caso en el que un puntero se pasa por valor. En este caso, la
computadora hace una copia legal del parmetro real de modo que cualquier cambio
hecho al parmetro formal no se reflejar de nuevo. Por ejemplo, supongamos que en el
procedimiento de escritura VerNumeros (imprime los nmeros almacenados en una
pila) en lugar de utilizar un puntero temporal para moverse a travs de la lista, se utiliza
el propio parmetro.

procedure VerNumeros (Cabeza: PtrLista);


begin
while Cabeza < > nil do
begin
WriteLn (CabezaA.Datos);
Cabeza:= CabezaA.Siguiente;
end;
end;

El procedimiento funciona, pero se destruye la lista cuando se cambia e abe z a?


La respuesta es no ya que el parmetro valor protege el parmetro real del cambio.
142 Estructura de datos
4.4. EL TIPO GENRICO PUNTERO (POINTER)
Turbo Pascal permite un tipo especial de definicin de puntero: genrico o no tipifi-
cado. Difiere del puntero estndar en que no tiene un tipo base, no est definido como
un puntero hacia algn tipo, sino simplemente como una variable de tipo pointer.
EJEMPLO 4.13
var
enlace: pointer;

enlace:= lis; {la variable lis figura en declaraciones precedentes}
La direccin contenida en la variable 1 i s est asignada a la variable en 1 a e e.
Los punteros genricos estn especialmente concebidos para la programacin de bajo
nivel, para la cual Turbo Pascal ofrece buenas posibilidades.
4.5. LA ASIGNACiN DE MEMORIA EN TURBO
BORLAND PASCAL
Turbo Pascal divide la memoria de su computadora en cuatro partes: el segmento de
cdigo, el segmento de datos, el segmento pila (stack) y el segmento montculo o alma-
cenamiento dinmico (heap). Tcnicamente la pila y el montculo no estn totalmente
separados, pero funcionan como entidades separadas.
El segmento de datos est claramente dedicado al almacenamiento de datos, pero en
los otros tres segmentos tambin pueden almacenarse datos. La Figura 4.3 muestra el
mapa de memoria simplificada de Turbo Pascal 7.0. Cada mdulo (que incluye el pro-
grama principal y cada unidad) tiene su propio segmento de cdigo.
El programa principal ocupa el primer segmento de unidades (en orden inverso de
como estn listadas en la clusula uses) y el ltimo segmento de cdigo est ocupado
por la biblioteca en tiempo de ejecucin.
El tamao de un segmento de cdigo no puede exceder de 64 K, pero el tamao total
del cdigo est limitado slo por la memoria disponible. El segmento de datos contiene
todas las constantes con tipo seguidas por todas las variables globales. El tamao del
mento de la pila no puede exceder de 64 K (el tamao por defecto es 16 K, que se
,
pueden modificar con la directiva $M).
El buffer o memoria intermedia de solapamiento (overlay) se utiliza por la unidad
estndar Overlay para almacenar cdigo recubierto. Si el programa no tiene solapamiento,
el tamao de la memoria intermedia del solapamiento es cero.
La Figura 4.4 (modificacin de la 4.3) muestra cmo queda la memoria cuando un
programa arranca, y en ella se observa que todas las variables locales se almacenan en la
pila (stack) y las variables globales (tambin llamadas estticas) se almacenan en el seg-
mento de datos. El cdigo y el segmento de datos estn localizados en la parte baja de
la memoria y la pila (stack) y el almacenamiento dinmico o montculo (heap) ocupan la
zona alta de la memoria.
Estructuras de datos dinmicas: punteros 143
FreePtr
HeapPtr ~
HeapOrg I ~
SSeg:Sptr ~
SSeg:OOOO ~
DSeg:OOOO ~
PrefixSeg ~
Cima de la memoria DOS
Lista libre (crece hacia abajo)
Montculo (crece hacia arriba)
....
Recubrimiento de Buffer
....
Pila (crece hacia abajo)
Pila libre
Variables globales
Constantes con tipos
Segmento de cdigo de la primera unidad

Segmento de cdigo de la unidad System
Segmento de cdigo de la ltima unidad
Segmento de cdigo del programa principal

Program Segment Prefix (PSP)
Memoria baja
Figura 4.3. Mapa de memoria de Turbo Pascal 7.0.
Ovr
Ovr
HeapEnd
HeapOrg
Contenid o de una
imagen de
archiv o .EXE
El diagrama de la Figura 4.4 muestra tambin que la pila crece hacia abajo en la
memoria y el montculo crece hacia arriba en la memoria. Aunque la pila y el montculo
comparten la misma zona de la memoria, ellas nunca deben solaparse (recubrirse).
La mayora de las variables que se declaran en Turbo Pascal son estticas, su tamao
se fija en tiempo de compilacin y no pueden variar. Por el contrario, el montCulo alma-
cena variables dinmicas.
4.5.1. El montculo (heap) y los punteros
El montculo o heap (pila de variables dinmicas o almacenamiento dinmico) alma-
cena variables dinmicas, esto es, las variables asignadas a travs de los procedimientos
144 Estructura de datos
Aqu se almacena el cdigo
objeto.
~
~ ~
Se almacenan variables
globales (estticas)
y constantes con tipos.
~ ~
Se almacenan variables de
subprograma, parmetros
pasados y otros valores
auxiliares.
~
Se almacenan variables
dinmicas creadas por New y
GetMen.
Espacio del montculo no
utilizado disponible para
almacenar variables dinmicas
adicionales.
Comienzo del
programa
principal
Cdigo unidad n

Cdigo unidad 2
Cdigo unidad 1
Comienzo de
datos
Fin de datos
Comienzo de la
pila
Comienzo del
montculo
Cima del montculo
~
El tamao de la zona
de cdigo es el total
del tamao del cdigo
de programa principal
ms el tamao del
cdigo de todas las
unidades utilizadas
por el programa. El
tamao total del
cdigo slo est
limitado por la
memoria disponible.
Tamao de la zona de
datos (suma de todas
las variables globales
del programa principal
y todas las unidades
utilizadas). El mximo
es 65.520 bytes.
El tamao de la zona
de la pila se establece
con las directivas del
compilador.
La pila crece hacia la
zona baja de la
memoria.
El montculo crece
hacia la zona alta de la
memoria.
El tamao del
montculo se
establece con las
opciones del
compilador. Si la
memoria disponible es
menor que el lmite
bajo del montculo, el
programa no se
cargar.
Figura 4.4. Mapa prctico de memoria de Turbo Pascal 7.0.

Estructuras de datos dinmicas: punteros 145


estndar New y GetMem. El montculo puede crecer o disminuir en el segmento corres-
pondiente, ya que utiliza tipos de datos dinmicos: los punteros, que pueden crear o
liberar variables dinmicas mientras el programa se est ejecutando. En resumen, las
variables puntero pueden utilizar y reutilizar la memoria montculo.
El tamao real del montculo depende de los valores mnimos y mximos que pue-
den fijarse con la directiva del compilador $M. El tamao mnimo es de O bytes, y el
mximo por defecto es de 640 Kb; esto significa que poi defecto el montculo ocupar
toda la memoria restante (640 Kb viene definida por la mxima memoria direccionable
por el DOS, aunque los procesadores 8086/88 tienen diecisis segmentos que por un
valor de 64 K de RAM resultara 1.048.560 bytes = l Megabyte).
El lmite inferior del montculo se almacena en la variable HeapOrg, y el lmite o
cuota superior (lmite inferior de la memoria libre) se almacena en la variable HeapPtr.
Cada vez que una variable dinmica se asigna en el montculo (va Newo GetMen), el
gestor de la pila mueve GetPtr hacia arriba el tamao de la variable.
El uso de las variables puntero en el montculo ofrece dos ventajas principales. Pri-
mero se ampla la cantidad total de espacio de datos disponibles en un programa; el
segmento de datos est limitado a 64 K, pero el montculo, como ya se ha citado, est
limitado slo por la cantidad de RAM en su computadora. La segunda ventaja es penni-
tir que su programa se ejecute con menos memoria. Por ejemplo, un programa puede
tener dos estructuras de datos muy grandes, pero slo una de ellas se utiliza en cada
momento. Si estas estructuras de datos se declaran globalmente, ellas residen en el seg-
mento de datos y ocupan memoria en todo momento. Sin embargo, si estas estructuras
de datos se definen como punteros, se pueden poner en el montculo y quitarse cuando
no se necesiten, reduciendo, por consiguiente, los requisitos de memoria.
4.5.2. Mtodos de asignacin y liberacin de memoria
Los subprogramas que gestionan el montculo o almacenamiento dinmico son:
Asignacin dinmica de memoria
New
Mark
Getmem
Dispose
Release
FreeMem
4.5.3. New y Dispose
Espacio ocupado en memoria
MaxAvail
MemAvail
Cuando Di spose libera o destruye una variable dinmica, puede dejar un agujero en el
montculo. Si hace uso frecuente de New y Dispose, puede llegar a producirse una
acumulacin de espacio de memoria inservible basura (garbage). Algunos sistemas
Pascal proporcionan rutinas especficas para comprimir esa informacin inservible (gar-
bage col/ection), Turbo Pascal no las soporta, pero s utiliza un sistema de gestin de la
memoria montculo muy sofisticada que minimiza la prdida de esos espacios inservi-
bles. Los procedimientos Mark y Re lease proporcionan un mtodo alternativo de
gestin del montculo que eliminan la necesidad de la operacin eliminar basura. Sin
embargo, hay un inconveniente: Dispose no es compatible con Mark y Release.
146 Estructura de datos
4.5.4. Mark y Release
Mark y Release son una alternativa a utilizar New y Dispose para. asignar memo-
ria dinmicamente.
El procedimiento Mark registra la direccin de la parte superior del montculo en
una variable puntero. El procedimiento Release devuelve el montculo a un estado
dado (reestructura la direccin).
Mark (va r pun t) Release (varpunt)
varpun t variable puntero de cualquier tipo puntero
Nota
4.5.5. GetMem y FreeMem
Un tercer mtodo de asignar memoria es GetMem y FreeMem. Se asemejan a New y
Dispose en que asignan o liberan memoria, pero GetMem y FreeMem pueden especi-
ficar cunta memoria se desea asignar con independencia del tipo de variable que est
utilizando. Se pueden asignar bloques de memoria en la pila de una unidad de datos
cuyo tamao no se conoce en tiempo de compilacin.
GetMem crea una nueva variable dinmica del tamao especificado y pone la direc-
cin del bloque en una variable puntero.
Formato
GetMem (va r pun t, tamao)
varpun t variable puntero de cualquier tipo puntero
tamao expresin de tipo word
FreeMem libera una variable dinmica de un tamao dado.
Formato
FreeMem (varpunt, tama o)
Las variables asignadas con GetMem se liberan con FreeMem.
EJEMPLO 4.14
GetMem (y, 100);
FreeMem (y, ~ O O ;
Nota
Estructuras de datos dinmicas: punteros 147
4.5.6. MemAvail y MaxAvail
El conocimiento de cunta memoria est realmente disponible para variables dinmicas
puede ser crtico. Turbo Pascal lleva un registro de cunta memoria queda en el montcu-
lo, de modo que si se solicita ms de la disponible, se generar un error en tiempo de
ejecucin. La solucin es no crear una variable dinmica que sea mayor que la memoria
disponible en el montculo. Turbo Pascal proporciona dos funciones para medir la me-
moria disponible: MemAvail y MaxAvail.
MaxAvail devuelve el tamao del bloque libre contiguo ms grande del montcu-
lo, correspondiente al tamao de la variable dinmica ms grande que se puede asignar a
la vez. (El valor devuelto es un entero largo.)
Formato
MaxAvail
MemAvail devuelve un valor (del tipo entero largo) que indica, en bytes, la cantidad
total de memoria disponible para variables dinmicas.
Formato
MemAvail
EJEMPLOS 4.15
begin
Writeln (MemAvail, 'bytes disponibles');
Writeln( 'el bloque libre ms grande es:', MaxAvail, 'bytes')
end
Programa
En el archivo Marathon van a almacenarse los datos personales de los participantes del
Marathon Jerez-97.
148 Estructura de datos
Anlisis. Este sencillo problema nos sirve para escribir un ejemplo de utilizacin de
variable puntero y variable apuntada o referenciada. El puntero va a referenciar a un
registro con los campos necesarios para representar los datos personales. Es evidente
que podramos utilizar una variable esttica de tipo registro, pero es un ejemplo.
Codificacin
program Marathon (input, output);
uses crt;
type
registro = record
nombre, apellido
direccin
ciudad
edad
marca
: string[25J;
: string[30J;
: string [20J;
: integer;
: record
n, m, sg: integer
end;
end;
Ptrreg = Aregistro;
var
R : Ptrreg; F: file of registro;
procedure Datos (var Pr: Ptrreg);
begin
new (Pr);
with PrAdo
begin
write ('Nombre Apellido:'); readln (nombre, apellido);
write( 'Direccion ciudad:') ;readln (direccion, ciudad);
write ('Edad:') ;readln (edad);
write( 'mejor Marca:') ;readln(marca.h,marca.m,marca.sg)
end
end;
begin
assign (F,' carrera. Dat ) ;
rewrite (F);

writeln( 'Escribe los datos de cada participante');


writeln( 'Para acabar proceso:Crtln Z');
while not eof do
begin
Datos (R) ;
write(F,R
A
)
end
end.
RESUMEN
Un puntero es una variable que se utiliza slo para almacenar la direccin de memoria de otra
variable. Un puntero apunta a otra variable cuando contiene una direccin de la variable.
Pascal tiene mtodos especiales para declaracin, iniciacin y manipulacin de punteros. La
razn principal para utilizar punteros es que ellos hacen posible las estructuras de datos dinmi-
cas, que les permiten crecer, decrecer e incluso desaparecer mientras se estn ejecutando.
152 Estructura de datos
PROBLEMAS
4.1. Escribir las declaraciones necesarias para definir un tipo de datos puntero a un registro de
estudiante con los campos Apellido-I, Apellido-2, Nombre, Fecha-nacimiento y notas. Los
tres primeros campos definirlos de tipo puntero a cadena de 25 caracteres. El campo Fecha
puntero a un registro con los campos da, mes y ao. Y el campo Notas puntero a un array
de 10 elementos.
4.2. Escribir un procedimiento que devuelva los datos correspondientes a un registro de estu-
diante definido en 4.1. En el procedimiento se ha de reservar memoria para cada uno de los
campos del registro.
4.3. Definir un vector de registro del tipo definido en 4.1. Escribir un procedimiento en el que
se d entrada a los registros de los estudiantes de una clase que tiene un mximo de 40
alumnos. Utilizar el procedimiento definido en 4.2.
4.4. Definir un archivo cuyos elementos van a ser los registros definidos en 4. 1, con la salvedad
de que en vez de los campos puntero, los campos sean del tipo apuntado. Escribir un
procedimiento que tome como entrada el vector generado en 4.7 Y escriba los registros en
el archivo.
4.5. Definir de nuevo el registro enunciado en 4.5 para escribir el procedimiento de entrada de
campos del registro con la particularidad de que se reserve memoria con el procedimiento
GetMem. El nmero de bytes a reservar se debe ajustar al tamao real del campo.
4.6. Una ecuacin de segundo grado depende de tres parmetros de tipo real: a, b, c. Escribir un
programa que tenga como datos de entrada los coeficientes de la ecuacin de segundo gra-
do y como salida las races de la ecuacin. Definir los parmetros a, b, c como punte-
ros a nmeros reales de tal forma que en el procedimiento de entrada se reserve memoria
para ellos.
,
CAPITULO

Istas en aza as:

Ista en aza a
CONTE
5.1. Especificacin formal del tipo abstracto de datos lista.
5.2. Implementacin del TAO lista con estructuras dinmicas.
5.3. Implementacin del TAO lista mediante variables dinmicas.
5.4. Iniciar una lista enlazada.
5.5. Bsqueda en listas enlazadas.
5.6. Operaciones de direccin: siguiente, anterior, ltimo.
5.7. Insercin de un elemento en una lista.
5.8. Borrado de un elemento de una lista.
5.9. Recorrido de una lista.
5.10. Lista ordenada.
RESUMEN.
EJERCICIOS.
PROBLEMAS.
Una lista enlazada (o lista) es una secuencia de nodos en el que cada
nodo est enlazado o conectado con el siguiente. La lista enlazada es
una estructura de datos dinmica cuyos nodos suelen ser normalmente
registros y que no tienen un tamao fijo.
En el captulo se desarrollan algoritmos para insertar, buscar y bo-
rrar elementos. De igual modo se muestra el tipo abstracto de datos
(TAD) que representa a las listas enlazadas.
5.1. ESPECIFICACiN FORMAL DEL TIPO ABSTRACTO
DE DATOS LISTA
Una forma de almacenar elementos relacionados es alinearlos, formando una lista lineal
que necesita un enlace por cada elemento, para referenciar al elemento sucesor.
153
154 Estructura de datos
p-
7 15 34 67 nil
Figura 5.1. lista enlazada de nmeros enteros.
En la Figura 5.1 se muestra una lista enlazada de enteros a la que se accede a travs
del puntero P. Una lista es una estructura que se utiliza para almacenar informacin del
mismo tipo, con la caracterstica de que puede contener un nmero indeterminado de
elementos, y que estos elementos mantienen un orden explcito. Este ordenamiento ex-
plcito se manifiesta en que cada elemento contiene en s mismo la direccin del siguien-
te elemento.
Una lista es una secuencia de O a n elementos. A la lista de cero elementos llamare-
mos lista vaca. Cada elemento de una lista se denomina nodo. En un nodo po-
demos considerar que hay dos campos, campo de informacin ( I nfo) y campo de enla-
ce (Enl ac e) o direccin del elemento siguiente.
Info Sgte (Enlace)
Figura 5.2. Nodo de una lista enlazada.
El campo de direccin, a partir del cual se accede a un nodo de la lista, se llama
puntero. A una lista enlazada se accede desde un puntero externo que contiene la direc-
cin (referencia) del primer nodo de la lista. El campo de direccin o enlace del ltimo
elemento de la lista no debe de apuntar a ningn elemento, no debe de tener ninguna
direccin, por lo que contiene un valor especial denominado puntero nulo (ni/).
La lista vaca, aquella que no tiene nodos, tiene el puntero externo de acceso a la
lista apuntando a nulo.
NIL
... --
NIL
p:=nil
Figura 5.3. lista enlazada sin informacin o inicializacin de lista (lista vaca).
Una lista es una estructura de datos dinmica. El nmero de nodos puede variar rpi-
damente en un proceso, aumentando los nodos por inserciones, o bien disminuyendo por
supresin (eliminacin) de nodos.
Las inserciones se pueden realizar por cualquier punto de la lista. As pueden reali-
zarse inserciones por el comienzo de la lista, por el final de la lista, a partir o antes de un
nodo determinado. Las eliminaciones tambin se pueden realizar en cualquier punto de
la lista, aunque generalmente se hacen dando el campo de informacin que se desea
eliminar.
Listas en/azadas: e/ TAO lista en/azada 155
Especificacin formal del TAD lista
Matemticamente, una lista es una secuencia de cero o ms elementos de un determina-
do tipo.
(al, a2, a3,

, an) donde n >= O,
si n = O la lista es vaca.
Los elementos de la lista tienen la propiedad de que sus elementos estn ordenados
de forma lineal, segn las posiciones que ocupan en la misma. Se dice que a
j
precede a
a j +1 para i = 1, 2, 3, 4, 5, ... , n -1 y que aj sucede a ajol para i = 2, 3,
4, 5, 6, ... , n.
Para formar el tipo de datos abstracto Lis t a a partir de la nocin matemtica de
lista, se debe definir un conjunto de operaciones con objetos de tipo Lista. Las opera-

ClOnes:
Listavacia(L)
Esvacia(L)
Inserprim(X,L)
Inserta(X,P,L)
Inserfin(X,L)
Localiza(X,L)
Suprime(X,L)
Suprimedir(P,L)
Anterior(P,L)
Siguiente(P,L)
Primero(p)
Ultimo (P)
Anula(L)
Visualiza(L)
Inicializa la lista.
Funcin que determina si la lista es vaca.
Inserta un nodo con la informacin X como primer nodo de la
lista L.
Inserta en la lista L un nodo con el campo X, delante del nodo
de direccin P.
Inserta un nodo con el campo X como ltimo nodo de la lis-
ta L.
Funcin que devuelve la posicin/direccin donde est el cam-
po de informacin X. Si no est devuelve nulo.
Elimina de la lista el nodo que contiene a X.
Elimina de la lista el nodo cuya direccin/posicin viene dada
por P.
Funcin que devuelve la posicin/direccin del nodo ante-
rior a P.
Funcin que devuelve la posicin/direccin del nodo siguien-
te a P.
Funcin que devuelve la posicin/direccin del primer nodo
de la lista L.
Funcin que devuelve la posicin/direccin del ltimo nodo
de la lista L.
Esta operacin vaca la lista L.
Esta operacin visualiza el campo de informacin de todos
los elementos de la lista L.
Estas operaciones son consideradas como bsicas en el manejo de listas. En realidad,
la decisin de qu operaciones son las bsicas depende de las caractersticas del proble-
ma que se va a resolver. Tambin depender del tipo de representacin elegido para las
listas, por lo que es posible que puedan aparecer otras operaciones posteriormente.
,
1

I
156 Estructura de datos
Independientemente de la implementacin de las operaciones, se escribe un ejemplo
de manejo de una lista. El objetivo es que dada una lista L, eliminar aquellos nodos
repetidos. El campo de informacin de los nodos puede ser cualquiera (Ti poinf o).
La funcin 1 gua 1 e s devuelve verdadero en el caso de que los dos parmetros de
Ti poi nfo sean iguales.
procedure Eliminadup( var L : Lista);
var
P, Q: Posicion; {P posicin actual en L,
Q posicin avanzada )
begin
P : = Pr ime r o( L) ;
while P<> nul o do
begin
Q:= Siguiente (P , L) ;
while Q <> nu l o do
if Iguales (I nf o(P) , Info(Q)) then
Suprimedir (Q ,L )
el se
Q:= Siguiente(Q,L);
P:= Siguiente( P,L )
end;
end;
Para representar las listas y las correspondientes implementaciones pueden seguirse
dos alternativas:
Utilizacin de la estructura esttica array para almacenar los nodos de la lista.
Utilizacin de estructuras dinmicas, mediante punteros y variables dinmicas.
5.2. IMPLEMENTACiN DEL TAO LISTA CON ESTRUCTURAS
,
ESTATICAS
En la implementacin de una lista mediante arrays, los elementos de sta se guardan en
posiciones contiguas del array. Con esta realizacin se facilita el recorrido de la lista y la
operacin de aadir elementos al final. Sin embargo, la operacin de insertar un elemen-
to en una posicin intermedia de la lista obliga a desplazar en una posicin a todos los
elementos que siguen al nuevo elemento a insertar con objeto de dejar un hueco.
En esta realizacin con estructuras estticas se define el tipo Lis t a como un regis-
tro con dos campos: el primero, es el array de elementos {tendr un mximo nmero de
elementos, pre-establecido}; el segundo, es un entero, que representa la posicin que
ocupa el ltimo elemento de la lista. Las posiciones que ocupan los nodos en la lista son
valores enteros; la posicin i-sima es el entero i.
Declaraciones:
const
Max= 1 00 ;

,
,
,
,

,
,
i
J
..
:
j
1


!
!
1

,
,
,
,
j
,
,

,
,

-;
,
i
type
Ti po in fo=
List a = record
Listas en/azadas: e/ TAO lista en/azada
{t i po d e l campo i n forma c i n d e c a da nodo}
Eleme ntos: array [l . . Max] of Tipo info ;
Ultimo: integer
end;
pos icion= O " Max;
157
El procedimiento Lis t a vac i a ( L) inicializa la lista, para lo cual simplemente se
pone a cero UI timo.
procedure Lis tavac ialvar L: Lista);
begin
L .Ultimo := O
end;
El procedimiento Inserprim (X, L), que inserta X como primer nodo, debe des-
plazar una posicin a la derecha todos los nodos, para as poder asignar X en la primera
. .,
poslclon.
procedure l nse rprimlX : Tipoinf o ;var L : List a ) ;
var
l: i nteger ;
begin
with L do
begin
for 1: = Ul t imo downto 2 do
Elemen tos [l+ l] := Eleme n tos[ l];
Element o s [1 ] : = X
ult imo : = ultimo + 1
end
end;
El procedimiento 1 n s e r t a ( X I P, L) desplaza los elementos de la lista a partir de
la posicin P e inserta X en dicha posicin.
procedure lnsertal X: Tipo in fo;P : Posicion; var L: Li s ta);
var
Q: Posicion;
begin
if L .Ul t imo = Ma x then
< error : l ista L llena >
else if (P> L.ult imo) o r IP< 1) then
. " .
< error: p oslclon n o eXl ste >
el se beg1n
end;
for Q:= L.Ulti mo downto P do
{desplaza los e lement os a l a derec ha}
L. Element os [ Q+ 1 ] : = L. Elementos [Ql ;
L . Ultimo := L.Ult imo+l ;
L . Element os [ P ] : = X
end
I
158 Estructura de datos
Para implementar la operacin Supr ime (X, L) , primero hay que encontrar la po-
sicin que ocupa x, a continuacin se elimina.
procedure Suprime(X: Tipoinfo;var L: Lista);
var
l: integer;
P: integer;
begin
P: = Localiza (X, L);
if P> O then
begin
L.Ultimo:= L.Ultimo-l;
for l:= P to L.Ultimo do
{desplaza a la izquierda}
end
end;
L. Elementos [l] : = L. Elementos [l+ 1] ;
Otra forma de escribir el procedimiento Supr ime es aprovechar el procedimiento
Suprimedir:
procedure Suprime(X: Tipoinfo;var L: Lista);
var
P: integer;
begin
P:= Localiza(X,L);
if P> O then
Suprimedir(P,L)
end;
La operacin Supr imedi r ( P , L) , que elimina de la lista el nodo cuya posicin
viene dada por P, tiene que hacer lo opuesto que la operacin Inserta: desplazar a la
izquierda los elementos que se encuentran a partir de la posicin P:
procedure Suprimedir(P: Posicion;var L: Lista);
var
Q: Posicion;
begin
if (P> L.Ultimo) or (P< 1) then
< error: posicin no existe>
else begin .
L.ultimo:= L.Ultimo-l;
for Q:= P to L.Ultimo do
{ desplaza a la izquierda }
L.Elementos [Q]:= L.Elementos [Q+l]
end
end;
La operacin de localizar, Local iza (X, L) devuelve la posicin de un elemento X:
function Localiza (X:Tipoinfo; L:Lista): Posicion;
var
,
,


Q: Pos i e i o n;
Le: boo l e a n;
begin
Q:= 1;
Le : = fal s e;
while (Q<= L. Ult imo) and not Le do
begin
Le := L.El e ment os [Ql= X
if not Le then Q:= Q+1
end;
if Le then
Loea liza:= Q
else
Loeal i z a := O
end;
Listas enlazadas: el TAO lista enlazada 159
5.3. IMPLEMENTACiN DEL TAO LISTA MEDIANTE VARIABLES
DINMICAS
Este mtodo de implementacin de listas enlazadas utiliza variables puntero que permi-
ten crear variables dinmicas, en las cuales se almacena el campo de informacin y el
campo de enlace al siguiente nodo de la lista. Con esta implementacin se ajusta la memo-
ria ocupada al tamao real de la lista, no como ocurre en la realizacin mediante estructuras
estticas en las que es necesario prever un mximo de elementos o nodos. Ahora, cada
vez que sea necesario crear un nuevo nodo se llama al procedimiento que capta la memoria
necesaria de la pila de memoria libre, y se enlaza con la lista. De igual forma cuando sea
necesario eliminar un nodo, la memoria ocupada por ste se devuelve a la pila de memo-
ria libre. El proceso es dinmico, la lista crece o decrece segn las necesidades.
Con esta realizacin se evitan los desplazamientos de elementos a la derecha o a la
izquierda en las operaciones de insercin o eliminacin, respectivamente. Por contra,
cada vez que se quiere acceder a un nodo hay que recorrer la lista, a travs de los enlaces
hasta alcanzar su direccin. Tambin hay que tener en cuenta que en esta realizacin de
listas, cada nodo ocupa la memoria adicional del campo de enlace.
Las variables enteras contienen o pueden contener valores enteros, y sucede igual
con variables reales. El tipo de variables puntero (o apuntadores) son aquellas cuyo con-
tenido va a ser la direccin de memoria de un dato. Las variables puntero, al igual que
las variables enteras o reales, son variables estticas, ya que se crean (se reserva memo-
ria para ellas) en tiempo de compilacin.
Pu ntero= ATipoapunt ado ;
Con esta declaracin de tipo estamos expresando que los valores que contenga una
variable de tipo Puntero van a ser direcciones de memoria del tipo Tipoapuntado. Grfi-
camente:
p

,
I
160 Estructura de datos
Con los punteros se pueden construir toda clase de estructuras enlazadas. Estas es-
tructuras son dinmicas; es decir, el nmero de elementos puede cambiar durante la
ejecucin del programa. Para lo cual hay procedimientos que permiten crear y destruir
elementos durante la ejecucin del programa, y as se ajustan a las necesidades de cada
instante, cosa que no ocurre con las estructuras estticas como los arrays.
Al trabajar con estructuras dinmicas hay que manejar dos clases diferentes de varia-
bles: variables puntero (direccionan un dato) y variables referenciadas (son apuntadas).
type
Ptrentero= Ain t eger ;
Ptrcadena= As t ring[251;
var
Pe: Ptrentero;
Pc: Pt r cadena;
Las variables puntero Pe y Pe van a contener la direccin en memoria de un dato
entero y de un dato cadena, respectivamente.
Lo habitual ser que el tipo del dato al que apunta una variable puntero sea un regis-
tro, ste tendr un campo de informacin y otro, u otros campo de enlace, por consi-
guiente del mismo tipo puntero. ,
type
Ptrnodo - APers o na;
Persona - record
Nombre: stri ng[ 25 1;
Direcc: string[501;
Edad : integer ;
Enlace: Ptrnodo
end;
Variables del tipo puntero Ptrnodo van a estar asociadas con variables referencia-
das del tipo Persona. '
var
P : Pt rnodo;
P Persona
En la declaracin anterior se crea la variable esttica P, cuyo valor, de momento, est
indefinido. Esta variable P apuntar a una variable referenciada, todava no creada, del
tipo Persona. La creacin de la variable referenciada se realiza mediante el procedi-
miento new
new(variable puntero); new(P};
Este procedimiento reserva memoria, crea una variable referenciada cuyo tipo (Per-
sona) est declarado dentro de las definiciones formales. Despus de la ejecucin del
procedimiento new la variable puntero tiene la direccin en memoria de la nueva varia-
ble creada.
,
,
,
,


,
1
Listas enlazadas: el TAO lista enlazada 161
As, P contendr la direccin de la variable creada del tipo Persona. Cmo se
nombran a las variables referenciadas? Tienen el mismo nombre que las variables punte-
ro poniendo a continuacin el carcter A (o una flecha).
new (P) ; pA es la variable referenciada del tipo Persona.
Con esta variable se pueden hacer exactamente las mismas operaciones que con una
variable registro del tipo Persona.
new ( P) ;
pA.Nombre:= 'Juan Marco';
readln (PA. Edad) ;
pA.Enlace:= nil;
Existe una operacin inversa a new que permite liberar la memoria referenciada por
una variable puntero: procedimiento dispose.
di spose ( P) i libera la memoria! devtJ,c::lvees, mc::11}oria a la pila de memoria
libre, asignada anfer1rtnenfe onnew. .. . .
Operaciones con variables puntero
Las variables puntero se pueden asignar y comparar con los operadores =, < >. Los pun-
teros pueden pasarse como parmetros a los subprogramas; una funcin puede ser de
tipo puntero, es decir, puede devolver un puntero.
type
Ptr= AElemento;
Elemento = record
Numero: integer;
Enlace: Ptr
end;
var
PI, P2: Ptr;

P2:= PI;
P2:= PIA.Enlace;
PIA.Enlace:= P2
A
.Enlace;
P2:= nil;
Se asigna el campo Enlace de la variable referenciada por P l.
Es posible hacer que una variable puntero no apunte a nada
as ignando n il .

Despus de la operacin de liberar memoria, di spose (P) . La variable puntero se


queda con un valor arbitrario, entonces conviene asignar ni 1,
dispose (PI) ;
PI:= nil;


I
,
I
I
I

!

162 Estructura de datos
Ahora ya se puede escribir la implementacin de las operaciones con listas simple-
mente enlazadas utilizando variables dinmicas. Las operaciones sobre una lista enlaza-
da permiten acceder a la misma mediante un puntero externo, que contiene la direccin
del primer nodo de la lista.
p--
Juan
Supngase los tipos
type
Ti po i n f o =
Pt rnod o = ANodo ;
No do = record
Inf o : Tipo i nfo ;
Sgte : Ptrnodo
end;
Mar Peter
5.4. INICIAR UNA LISTA ENLAZADA
... Urban nil
Las operaciones usuales de iniciacin de una lista enlazada son: crear una lista vaca y
comprobar si una lista est vaca.
Crear lista
Inicia una lista sin nodos, como lista vaca.
procedure Listavac i a( var L: Ptrnodo);
begin
L:= nil
end;
Esvacia
Esta operacin es una funcin que determina si la lista no tiene nodos.
function Esvac ia(L : Pt r nodo) : b o olean;
begin
Es va cia := L = nil
end;
5.5. BSQUEDA EN LISTAS ENLAZADAS
La operacin de bsqueda en una lista enlazada, requiere una operacin Localiza
que permite localizar la direccin de un nodo que contenga un campo de informacin
determinado; asimismo, se puede plantear una operacin Ex i s t e que sirve para deter-
- -_ .. ~ ~ ~

,
,











,

,

,
,
I
1
1
-o
,
,
~

,
,
,
~

l

~
I
I
Listas enlazadas: el TAO lista enlazada 163
minar si hay un nodo con cierta informacin. La funcin Loca 1 iza devuelve la direc-
cin de un nodo o ni l. Los cdigos fuente de ambas funciones son:
function Localiza(X:Tipo inf o ; L : Ptrnodo): Ptrnodo;
var
T : Ptrnodo;
begin
T : = L;
while (TA . Sgte<> nil) and (TA.lnfo<> X) do
T: = TA .Sgte;
if TA. ln fo< > X then
Loca l iza : = nil
elee
Local iza := T
end;
function Existe(X: Tipoinfo ; L: Ptrnodo): bool ean ;
begin
if not Es vacia(L) then
begin
while (LA .lnfo<> X) and (LA . Sg te<> nil) do
L: = LA . Sgte;
Existe : = LA. lnfo=X
end
elee
Msge( ' Error en llamada ' )
end;
5.6. QPERACIONES DE DIRECCiN: SIGUIENTE, ANTERIOR,
ULTIMO
Operaciones usuales en la construccin de algoritmos de manipulacin de listas enlaza-
das son aquellas que permiten la bsqueda y localizacin de un cierto nodo. Este es el
,
caso de las operaciones Anterior, Siguiente y Ultimo.
Anterior (P, L)/Siguiente (P, L)
Con esta operacin se obtiene la direccin del nodo anterior a P, o bien ni 1 si no existe
tal nodo. Para 10 que hay que recorrer la lista hasta encontrar P.
function Anterior(P: Ptrnodo ; L : Ptrnodo): Ptrnodo;
(El a nt e rior de lista vaca, del primer nodo y de d i reccin no
existente de l a l ista: nill
begin
if Esvac i a(L) or ( P= nil) or ( L=P) then
An terior:= n il
elee begin
while ( LA. Sgte< > P) and (LA. Sg te< > n i l ) do
L : = LA . Sgte ;
Anterior:= L
I
,
,


,
;
164 Estructura de datos
el se
An ter i or : = n i l
end
end;
La operacin siguiente devuelve la direccin del nodo siguiente a uno dado, o bien
n i 1 si es el ltimo nodo.
function Si gu i ente (P : Ptrnodo; L : Ptrnodo) : Ptrnodo ;
begin
if Esvac i a ( L) o r (P=n il) then
Sigu i e n te : =nil
else

end;
, .
Ultimo (L)
Para obtener la direccin del ltimo nodo se ha de recorrer toda la lista.
function Ultimo(L:Ptrnodo ) : Ptrnodo ;
{ El l timo de l i s ta vaca con s i der a mos nil }
begin
if Esvacia ( L ) then
Ult i mo := ni l
else
begin
while LA . Sgte<> n i l do
L:=
Ult imo:= L
end
end;
,
5.7. INSERCION DE UN ELEMENTO EN UNA LISTA
La operacin de insercin de un elemento con un campo de informacin X siempre su-
pone crear un nuevo nodo. Para ello se utiliza el procedimiento new. Adems habr que
hacer un movimiento de enlaces. La funcin Crear devuelve la direccin de un nuevo
nodo.
function Crear(X: Tipo i n f o ): Ptrnodo ;
var
N: Ptrnodo ;
begin
n ew (N) ;
X;
nil;
Crear: = N
end;
Inserprim(X,L)
Listas enlazadas: el TAO lista enlazada 165
Aade un nodo con la infolll1acin X como primer nodo de la lista
L-- N1 N2 N
A-- x
procedure In s e r p r im (X : Tipoin f o ; v ar L: Pt r no do);
var
A: Pt r n odo ;
beqin
A:= Crear (X) ;
AA. Sgte:= L;
L: = A
end;
Inserta(X,P,L)
nil
Aade a la lista L un nodo con el campo X, delante del nodo de direccin P.
p-
L-
A-....,
procedure I n sert a(X : Ti p o i n f o ; P: Ptrno d o ; var L : Pt r n odo ) ;
var
A: Ptrn odo ;
begin
A:= Crear ( X) ;
if Esvac ia(L)
L: = A
then
elBe if P= L then
begin
AA. Sgte := P ;
L : = A
end
nil
elBe begin {Ah ora es cuando se en l aza el nuevo no do e n t r e e l n odo
a n t er i or y e l n od o P}
end
end;
Anter i or( P ,L) A. Sg t e : = A;
AA. Sg t e := P
I
j

i
I
I
I
I

,
I


.
,
.
I
I
166 Estructura de datos

Otra forma de enlazar el nuevo nodo consiste en aadir el nuevo nodo a continuacin
de P e intercambiar el campo de informacin:
procedure Inserta(X: Ti po i nfo ; P: Ptrnodo ; var L: Ptrnodo) ;

elae
begin {El nuevo nodo es enl azado a cont inuac i n de P, d espus s e
intercambi a el campo Info }
AA . Sgte : = p A. Sgte ;
pA . Sg t e : = A;
AA . lnfo := PA. lnfo ;
pA .lnfo : = X
end;
Inserfin(X,L)
Aade un nodo con el campo X como ltimo nodo de la lista.
L- N1 N2 N
procedure Inserfin(X: Ti poinfo ; var L: Ptrnodo) ;
var
A: Ptrnodo;
begin
A:= Crear (X) ;
if Esvac i a( L) then
L := A
elae
Ult i mo(L)A. Sgte : = A
end;
x
5.8. SUPRESiN DE UN ELEMENTO DE UNA LISTA
nil
La operacin de supresin (borrado) supone enlazar el nodo anterior con el nodo si-

guierlte al que va a ser borrado y liberar la memoria ocupada por el nodo a borrar. Esta
opera in se realiza con una llamada al procedimiento dispose.
Co las operaciones de supresin de un nodo y Ul t i mo resulta fcil eliminar todos
los nodos de una lista, quedando sta como lista vaca.
L-
,

N1
Suprime(X,L)
--- - - -
p
N2 N3 N4 O " - N nil
Se elimina el nodo que contiene a X.

--------- - ------------ ------------. . _- ------

i
168 Estructura de datos
5.9. RECORRIDO DE UNA LISTA
Una operacin frecuente en cualquier algoritmo de manipulacin de listas es el re-
corrido de los nodos de la lista enlazada. El qu se haga con cada nodo depender
del problema que se est resolviendo, ahora son visitados para escribir el campo de in-
formacin.
procedure Vi s u a liza( L: Ptrnodo );
var
Q: Ptrnod o ;
beg1n
Q:= L;
wh11e Q< > n11 do
beg1n
wr iteln (QA. Inf o, , ') ;
Q: = QA. Sgte
end
end;
5.10. LISTA ORDENADA
En las listas tratadas anteriormente los elementos de las mismas estn ordenadas por la
posicin que ocupan dentro de la lista. Si el tipo de informacin que representa cada
elemento es un tipo ordinal, o tiene un subcampo ordinal , se puede mantener la lista
ordenada respecto a dicho campo.
Al representar la lista ordenada mediante un puntero externo L, ste apuntar al pri-
mer nodo en el orden creciente de los elementos.
Dada la lista (al, a2, a3 , ... ,an) estar ordenada si a, <= az <= a
3
<= ...
ano' <= an
La representacin enlazada:
L- ... -- ni!
5.10.1. Implementacin de una lista ordenada
La formacin de una lista ordenada se basa en dos operaciones: Inserord en, aade
el elemento X a la lista, manteniendo la ordenacin; Posinser, operacin que obtiene
la posicin a partir de la cual hay que aadir el elemento X en la lista para mantener la
ordenacin.
posinser(X,L)
Devuelve la direccin del nodo anterior a X segn la ordenacin de los elementos.
Ni 1, si es el anterior del primero .
,

,


Listas enlazadas: el TAO lista enlazada 169
function Pos i nser(X : Ti poi nf o ; L:Ptrno d o ) :Pt r n o d o ;
var
T : Pt rno do ;
begin
T : = nil;
if Not Esvacia (L) then
begin
while (X >= LA. Inf o ) and (L A.Sgte<> ni l) do
begin
T : = L ;
L : = LA . Sgte
end;
if X>= LA.Info then {Es e l lt i mo nodo}
T : = L;
end
Pos i ns e r:= T
end;
Inserorden(X,L)
Si la lista est vaca, el nodo se inserta como el primero de la lista. En caso contrario
se presentan dos casos:
a) El nodo ha de ser el primero de la lista.
b) El nodo ha de situarse entre dos nodos, o bien el ltimo. Al tener la direccin del
anterior, se reajustan los enlaces.
A
L-- 10 15 31 42
37
N
procedure Inserorden(X : Tipoinfo ; var L : Pt r nodo) ;
var
A, N: Pt r nodo ;
begin
N: = Cr ear ( X) ;
if Esvacia( L ) then
L : = N;
elee begin
A: = Posinser ( X, L) ;
if A = nil then {Se aade como primer n odo}
begin
NA.Sgt e : = L;
L : = N
end
elee begin
NA.Sgte:= AA.Sg te ;
AA. Sgte : = N
end
end
end;

91 nil
170 Estructura de datos
5.10.2. Bsqueda en lista ordenada
La operacin de bsqueda de un elemento en una lista ordenada es ms eficiente que en
una lista general. Para decidir que un elemento no est en la lista basta encontrar un
elemento mayor, no hace falta recorrer la lista hasta el final. La funcin Buscorden
realiza la bsqueda en una lista ordenada.
function Buscorden(X:Tipoinfo; L:Ptrnodo) :Ptrnodo;
var
T: Ptrnodo;
begin
T:= L;
while (TA.Sgte<> nil) and (TA.Info< X) do
T:= TA.Sgte;
if TA.Info= X then

Buscorden:= T
elee
Buscorden:= nil
end;
El resto de operaciones sobre listas son iguales ya estn o no ordenadas. Como en la
operacin de borrado de un elemento hay que buscar antes la posicin que ocupa, es ms
eficiente cambiar la llamada a Localiza por Buscorden.
PROBLEMA 5.1
Como ejemplo de listas ordenadas, se escribe un programa en el que se forma una lista
ordenada de N nmeros enteros aleatorios. Una vez formada, se eliminan los elementos
repetidos y se muestra la lista.
Anlisis
La unidad Lis t aOrdenada contiene las operaciones de manejo de listas. El progra-
ma Lis t a O r contiene un procedimiento El i m i n a r Du p que sirve para eliminar ele-
mentos duplicados y otro procedimiento Mo s t r a r que visualiza la lista. El algoritmo
de EliminarDup recorre la lista nodo a nodo, comparando el nodo actual con el si-
guiente; si son iguales se libera la memoria del nodo siguiente, se restablecen los punte-
ros y contina el proceso con el siguiente nodo. La lista estar formada por nmeros
enteros generados aleatoriamente de 1 a 99. El nmero de nodos, lo fijamos mediante la
constante Elementos = 55.
Interfaz de la unidad
unit ListaOrdenada;
interface
type
Tipoinfo = integer;
Ptrnodo = ANodo;

J
I


,
,
!
"
,


Listas en/azadas: e/ TAO lista en/azada
Nodo = record
Inf o :Tipoinfo;
Sgte : Ptrnodo
end;
function Posinser (X:Tipoinf o ; L:Ptrnodo) : Ptr nodo ;
procedure Inserorde n (X : Tipoinfo, var L:Ptrnodo) ;
function Busc orden (X : Tipoinf o ; L:Ptrnodo) : Pt rnodo ;
implementation
.. . {Cdigo correspondiente a los procedimientos / funciones escrit os
anteriorment e }
end .
Codificacin del programa
program ListaOr(input, output);
uses ListaOrdenada , Crt ;
const
Elementos - 55 ;
M = 99;
var
L,Q:Ptrno do ;
Y: i n t ege r;
procedure Eli mi nar Dup(L : Ptrnodo);
var
A, Q: Ptrnodo;
begin
A : - ' L ;
while A <> n i l do
if nil then
if then {Un repetido}
begin
Q := AA . Sgte ;
AA. Sgte : = QA .Sgte ;
d i spose(Q)
end
else A: =AA . Sg t e
else A:=AA . Sg te
end;
procedure Mo strar (L :Pt rno do);
var
Q:Pt rnodo ;
begin
Q: =L;
while Q <> ni l do
begin
wr ite (QA.lnfo, " ); Q: =QA.Sgte
end
end;
begin {Bloque ppal }
L: =Nil; randomize;

, ,
. ' ;' .
for Y:= l to El ementos do
Ins e ror den (Random (99)+1, L);
,
171

, ,
,
I
, ,
,
i
!
I
,

;
I
I
I
,
,
I

,
i
I
,
,
,
!
,
,
,
!
,
,
,
,
,
,
!
i
I

,


172 Estructura de datos
c l rscr ; {l a l ista es mostrada}
Mos tr ar(L) ;
{Los e l ementos duplicados son e limi nados d e la lista ordenada}
EliminarDup{L) ;
gotoxy(1 5, WhereY+l);
writel n ('Lista sin elemen tos duplicados') ;
Mostrar(L)
end.
PROBLEMA 5.2 (vector dinmico)
Se desea definir un vector de nmeros reales de manera dinmica (vector dinmico),
utilizando punteros para formar una lista enlazada que represente el vector. La estrategia
de creacin consiste en crear en una nica operacin (<<de golpe) un espacio de memo-
ria que reserve memoria suficiente para contener mx elementos.
En la operacin de asignacin se van aadiendo consecutivamente los nuevos ele-
mentos en la memoria reservada y si no hubiera espacio se ampla a otros mx elementos.
La operacin de supresin de un elemento requiere que un espacio equivalente al ocupa-
do por el elemento quede libre para posteriores asignaciones.
Solucin
El vector se representa mediante una lista enlazada con un puntero al primer nodo y otro
al ltimo nodo con nmero real aadido, La estrategia de asignacin es la indicada en el
enunciado del problema planteado,
La unidad Ve ctDi na contiene los tipos de datos y las operaciones necesarias para
cumplir los requisitos del problema.
unit VectDina;
interface
const
Mx=20;
type
Te l em=r ea l;
Pt r= AEl em;
Elem=record
Dat : Telem;
Sgte :Ptr
end;
Tvect or=record
A, Ult:Ptr;
N: i n t eger {nmero de elemen tos del vector}
end;
procedure Cr eac i on (var V:Tvector );
function Direccion (V :Tvector ; X: Te l em) : Ptr ;
function An t e ri or (V :Tvector ; W: Pt r ) :Pt r ;
procedure Asignar (var V: Tvector ; T: Te l e m) ;
procedure Bo rrar (var V: Tvector ; T : Telem) ;
procedure Mo st rar (V :Tvector) ;


176 Estructura de datos
La ventaja de una lista enlazada sobre un array es que la lista enlazada puede crecer y de-
crecer en tamao y que es fcil insertar o suprimir un valor (nodo) en el centro de una lista en-
lazada.
La lista enlazada es una estructura muy verstil. Los algoritmos para insercin y eliminacin
de datos constan de dos pasos:
Recorrer la lista desde el principio hasta que se alcanza la posicin apropiada .
Ejecutar cambios en los punteros para modificar la estructura de la lista.
El TAD lista enlazada es uno de los ms utilizados en gestin de proyectos software, debido a
que la estructura lista suele aparecer en la resolucin de numerosos problemas.
EJERCICIOS
Todos los ejercicios y problemas a los que se hace referencia deben de considerar la lista en-
lazada implementada mediante punteros. La direccin de acceso a la lista est en la variable
puntero L.
5.1. Escribir la funcin Cardinal que calcule el nmero de nodos de una lista enlazada.
5.2. Escribir un procedimiento que aada un nuevo elemento a la lista L a partir del elemento
. , .
-eSlmo.
5.3. Escribir un procedimiento que elimine de una lista L el nodo i-simo.
5.4. Escribir una funcin que devuelva la direccin del nodo i-simo de la lista L.
5.5. Escribir la funcin INVERSA que tiene como argumento de entrada la lista enlazada L,
devuelva la direccin de otra lista que tenga los nodos en orden inverso, es decir, ltimo
nodo pase a ser el primero, penltimo pase a ser el segundo, y as sucesivamente.
5.6. Escribir un procedimiento que tenga como argumento de entrada una lista L de nmeros
enteros, de la que se sabe que tiene nodos repetidos. El procedimiento crear otra lista
cuyos nodos contendrn las direcciones de los nodos repetidos en la lista L. Definir los
tipos de datos para representar ambas listas.
5.7. Una lista de cadenas de caracteres est ordenada alfabticamente. Escribir un procedimien-
to para suprimir aquel nodo que contenga la cadena S.
5.8. Se quiere implementar una lista enlazada mediante arrays de tal forma que cada elemento
del array contenga dos campos: campo de informacin y un segundo campo que llamare-
mos apuntador. El campo apuntador tiene la posicin que ocupa el siguiente nodo de la
lista, el ltimo nodo tiene el campo apuntador a cero.
Escribir los tipos de datos para esta representacin de la lista.
5.9. Dada la representacin de la lista propuesta en el anterior ejercicio, escribir el procedi-
miento de insertar un nodo como primer elemento de la lista.
5.10. Dada la representacin de la lista 5.8, escribir el procedimiento de insertar un nodo a partir
del que ocupa la posicin P.
5.11. Siguiendo con la representacin propuesta en 5.8, ahora escribir la funcin que localice un
nodo con el campo X.
5.12. Con la representacin de lista propuesta en 5.8, escribir el procedimiento de suprimir el
nodo con el campo de informacin X.

,


1


. :
,

,

,
,
I
1
l

Listas enlazadas: el TAO lista enlazada 177
PROBLEMAS
5.1. Dada una lista enlazada de nmeros enteros, escribir las rutinas necesarias para que dicha
lista est ordenada en orden creciente. La ordenacin se ha de hacer intercambiando los
punteros a los nodos.
5.2. Se dispone una lista enlazada ordenada con claves repetidas. Realizar un procedimiento de
insercin de una clave en la lista, de tal forma que si la clave ya se encuentra en la lista la
inserte al final de todas las que tienen la misma clave.
5.3. Dos cadenas de caracteres estn almacenadas en dos listas. Se accede a dichas listas me-
diante los punteros L 1, L2 . Escribir un subprograma que devuelva la direccin en la cade-
na L 2 a partir de la cual se encuentra la cadena Llo
5.4. Dada una cadena de caracteres almacenada en una lista L. Escribir un subprograma que
transforme la cadena L de tal fOllna que no haya caracteres repetidos.
5.5. Se quiere representar el tipo abstracto de datos conjunto de tal forma que los elementos
estn almacenados en una lista enlazada. Escribir una unidad para implementar el TAD
conjunto mediante listas. En la unidad deber de contener los tipos de datos necesarios y
las operaciones:
Conjunto vaco.
Aadir un elemento al conjunto.
Unin de conjuntos.
Interseccin de conjuntos.
Diferencia de conjuntos.
Nota: Los elementos del conjunto que sean de tipo cadena.
5.6. Escribir un programa en el que dados dos archivos de texto F 1, F 2 se formen dos conjun-
tos con las palabras respectivas de F 1 Y F 2 . Posteriollnente encontrar las palabras comu-
nes a ambos y mostrarlas por pantalla. Utilizar la unidad de conjuntos del problema 5.5
para resolver este supuesto.
5.7. Escribir un programa que forme lista ordenada de registros de empleados. La ordenacin
ha de ser respecto al campo entero Sueldo. Con esta lista ordenada realizar las siguientes

accIOnes:

Mostrar los registros cuyo sueldo S es tal que: P
1
::::; S ::::; P
2
.
Aumentar en un 7 por 100 el sueldo de los empleados que ganan menos de P pesetas.
Aumentar en un 3 por 100 el sueldo de los empleados que ganan ms de P pesetas.
Dar de baja a los empleados con ms de 35 aos de antigedad.
5.8. Se quiere listar en orden alfabtico las palabras de que consta un archivo de texto junto con
los nmeros de lnea en que aparecen. Para ello hay que utilizar una estructura multienlaza-
da en la que la lista directorio es la lista ordenada de palabras. De cada nodo con la palabra
emerge otra lista con los nmero de lnea en que aparece la palabra en el archivo.
Escribir la unidad Li s ta_de _Ent e r o s para encapsular el tipo lista de nmeros en-
teros.
Escribir la unidad Li s t a _ d e_Pa l abras para encapsular las operaciones que van a
manejar la lista de palabras propuesta.
Escribir un programa que haciendo uso de la(s) unidades anteriores resuelva el pro-
blema.
,

;'i



I
,


I
178 Estructura de datos
5.9. El polinomio P(x) = Go + G1X + G:zX2 + ... + a"x" deseamos representarlo en una lista enlaza-
da, de tal forma que cada nodo contenga el coeficiente y el grado de un monomio. Escribir
un programa que tenga como entrada los coeficientes y exponentes de cada trmino de un
polinomio, y forme una lista enlazada para representarlo; ha de quedar en orden decrecien-
te respecto al grado del polinomio. En el programa deben de encontrarse las operaciones:
Evaluacin del polinomio para un valor dado de x.
Obtencin del polinomio derivada de P(x).
Obtencin del polinomio producto de dos polinomios.
5.10. Un vector disperso es aquel que tiene muchos elementos que son cero. Escribir un progra-
ma para representar mediante listas un vector disperso. Y realizar las operaciones:
Suma de dos vectores dispersos.
Producto escalar de dos vectores dispersos.

.... -.. _ - -_. _- .... - - - - - - - - - - - - - - - - - - - - - - - ~ = ~ ~ = = = ~ - - - - - - - - - - - - -





....

,
CAPITULO

Istas emente en aza as
CONTENIDO
6.1. Especificacin de lista doblemente enlazada.
6.2. Realizacin de una lista doble mediante variables dinmicas.
6.3. Una aplicacin resuelta con listas doblemente enlazadas.
6.4. Especificacin de lista circular.
6.5. Realizacin de una lista circular mediante variables dinmicas.
6.6. Realizacin de listas circulares con doble enlace.
RESUMEN.
EJERCICIOS.
PROBLEMAS.
Las listas enlazadas se recorren en un solo sentido, normalmente en un
sentido establecido. En numerosas ocasiones es deseable avanzar en
cualquiera de los dos sentidos. Estas listas se denominan listas doble-
mente enlazadas. Otro tipo de listas que suelen ser tambin de gran
utilidad son listas circulares.
En el captulo se examinan las especificaciones de las listas doble-
mente enlazadas y listas circulares, as como los algoritmos que reali-
zan su implementacin.
6.1. ESPECIFICACiN DE LISTA DOBLEMENTE ENLAZADA
En las listas simplemente enlazadas hay un solo sentido en el recorrido de la lista. Puede
resultar til el poder avanzar en ambos sentidos, de tal forma que los trminos predece-
sor y sucesor no tengan significado puesto que la lista es completamente simtrica. En
cada nodo de una lista doblemente enlazada existen dos enlaces, uno al siguiente nodo y
otro al nodo anterior.
179



,
I

180 Estructura de datos


Un nodo de una lista doblemente enlazada puede ser considerada como un registro
con tres campos: un campo informacin y dos campos de enlace.
Lo
4 ni! H o L A ni!
.- ...
--1 __ '--
La implementacin de listas doblemente enlazadas se puede realizar con estructuras
estticas, o bien con estructuras dinmicas.
Las operaciones que pueden ser definidas en el TAD lista doblemente enlazada son
similares a las operaciones con listas simplemente enlazadas.
Listavacia ( Ld)
Esvac i a (Ld)
Ins erprim (X,Ld)
Inserta (X,P,Ld)
I nse rf in (X,Ld)
Loca li za (X , Ld )
Suprime (X,Ld)
Suprimedir ( P,Ld)
Prime ro (P)
ultimo (Ld)
Anul a (Ld)
visualiza ( Ld)
Inicializa la lista.
Funcin que determina si la lista es vaca.
Inserta un nodo con la infOJ macin X como primer nodo de
la lista Ld.
Inserta en la lista Ld un nodo con el campo X delante del
nodo de direccin P.
Inserta un nodo con el campo X como ltimo nodo de la lis-
ta Ld.
Funcin que devuelve la posicin/direccin donde est el cam-
po de informacin x. Si no est devuelve nulo.
Elimina de la lista el nodo que contiene a x.
Elimina de la lista el nodo cuya direccin/posicin viene dada
por P.
Funcin que devuelve la posicin/direccin del primer nodo
de la lista L.
Funcin que devuelve la posicin/direccin del ltimo nodo
de la lista Ld.
Esta operacin elimina/libera todos los nodos de la lista Ld.
Esta operacin visualiza el campo de informacin de todos
los elementos de Ld.
Puede observarse que no aparecen las operaciones Anterior ni Siguiente. Al
tener cada nodo dos enlaces, uno al siguiente y otro al anterior, y ser una lista simtrica,
se dispone directamente de las direcciones de los nodos contiguos a uno dado.
Las operaciones anteriores son las operaciones bsicas para manipulacin de listas.
Dependiendo del tipo de representacin elegida y del problema a resolver podrn existir
otras operaciones sobre listas .
,
6.2. PLEMENTACION DE UNA LISTA DOBLEMENTE
,
ENLAZADA MEDIANTE VARIABLES DINAMICAS
Se utiliza el tipo puntero a un dato. Este dato tendr un campo de informacin, relativo
a lo que queremos almacenar, y dos campos de enlace que por tanto tambin sern pun-

,
,
,
;.
-
,
,
;

;


,


'
i
J
,

1
.

Listas doblemente enlazadas 181
teros. Con esta implementacin, la lista doble se representa con una variable puntero Ld
a un nodo extremo que por conveniencia le consideramos el primer nodo de la lista.
type
Ti poi n for - ... ;
Ptrndble = ANododble
Nododbl e = record
I nfo : Tipoinf o ;
Sgt e , An ter: Pt rndbl e
end;
6.2.1. Creacin de nodos en la lista
Las operaciones utilizadas sern Cargar la lista (Li s taVac ia), Esvacia, Localiza,
Existe, Ultimo, Inserta e Insertajin.
Crear lista
Inicia una lista doble sin nodos, como lista vaca.
procedure Li s t aVac i a (var Ld : Ptrndble) ;
begin
Ld : =nil
end;
P ---,
,
Esvacia
La funcin EsVaci a devuelve verdadero si la lista est vaca y falso en caso contrario.
function Esvac ia (Ld: Pt r ndble) : boolea n ;
begin
Esvacia : = Ld = n i l
end
Localiza
Devuelve la direccin de un nodo o ni l.
function Loca li za (X : Ti poi n f o ; Ld : Ptrndble) : Ptrndb le ;
var
T: Pt rndbl e;
begin
T : = Ld ;
if not Esvaci a (Ld) then
end;
while (TA. Sgte < > n il) and (TA . lnfo < > X) do
T : = TA . Sgte ;
if TA. l n f o < > X then
Loca liza : =ni l
else
Locali za : = T

,
!

I
I
,
1
!

,

I
182 Estructura de datos
Una versin de Localiza es la operacin Existe. Con esta operacin se inspec-
ciona si en una lista doble existe un nodo del cual se conoce su direccin .
Existe (P, Ld)
function
begin
if not
begin
Existe (P: Pt rndb l e ; Ld:Ptrndbl e) : b oo lean;

Esvacia (Ld) and (P<> nil) then


while ( Ld<> Pi and ( Ld A. Sgte<> nil ) do
Ld := Ld A.Sgte ;
Exis te := Ld=P
end
elee
Msge ( 'Error e n l lamada ' )
end
Ultimo (Ld)
La operacin Ul timo obtiene la direccin del nodo que se encuentra en el otro extremo
del nodo que consideramos el primero, el apuntado por Ld.
function Ult i mo (Ld: Pt r ndble) : Ptrndble;
{El l t i mo de li sta vaca consideramo s n i l}
begin
if Esvacia ( Ld ) then
Ultimo := nil
elee begin
while LdA.Sgt e<> nil do
Ld := LdA. Sgte ;
Ultimo := Ld
end
end;
Cada vez que se realiza la insercin de un nodo con el campo de informacin x, hay
que reservar memoria para dicho nodo. La operacin crear realiza esta operacin.
function Crear (x : Tipo inf o) : Ptrndble;
var
N: Ptrndble;
begin
ne w (N);
NA.Info := X;
NA.Sgte := nil;
NA.Anter := nil;
Crear := N
end;
Inserta (X, P, Ld)
Aade a la lista Ld un nodo con el campo x, delante del nodo de direccin P.
,
.







,
184 Estructura de datos
: = N;
P
end
end;
nil
Insertafin (X, Ld)
p
Aade un nodo con el campo x como ltimo nodo de la lista.
u
nil
.. .
procedure Insertafin (X : Ti p oinfo ; var Ld : Ptrndbl e);
var
N, U: Ptrndbl e ;
begin
N : = Crear (X) ;
if Esvac i a (Ld) then
Ld : = N
else begin
U := Ultimo (Ld);
: = N;
:= U
end
end;
6.2.2. Eliminacin de nodos

I
L
ni I

La eliminacin de nodos de una lista doble la planteamos en dos operaciones muy simi-
lares. En la primera es pasado el campo de informacin del nodo que queremos borrar, y
se elimina el primer nodo que se encuentra con dicho campo de informacin. En la se-
gunda se tiene la direccin del nodo que quiere ser eliminado. Las acciones de supresin
se realizan en la segunda operacin.
~ ~ .... . ~ . ------- --_ .... -------_. ---- - --- --- -- --- ----
Listas doblemente enlazadas 185
r-----------,
n il
I
I
I
I
I
I
L ___________ .J
procedure Suprime (X: Tipoinfo; var Ld: Ptrndble);
var
P: Ptrndble;
begin
P := Localiza (X, Ld);
if P<> nil then
Suprimedir (P, Ld)
else
Msge ('No est')
end;
procedure Suprimedir (P: Ptrndble; var Ld: Ptrndble);
begin
if Existe (P, Ld) then
begin
if P = Ld then {Primer nodo}
begin
Ld := LdA.Sgte;
LdA.Anter := nil
end
else if P < > Ultimo (Ld) then
begin
pA.AnterA.Sgte := PA.Sgte;
pA.SgteA.Anter := pA.Anter
end
else {Es el ltimo nodo}
pA.AnterA.Sgte:= nil;
dispose (P)
end
end;
Anula (Ld)

ni I

,
Esta operacin libera la memoria ocupada por todos los nodos de la lista Ld. El estado
final de la lista Ld es vaca.
Una de las formas de realizar esta operacin es suprimir nodos desde aquel que arbi-
trariamente consideramos ltimo hasta el apuntado por Ld. Se fundamenta en las opera-
ciones de Ultimo y Suprimedir.
procedure Anula (var Ld: Ptrndble);
var
P: Ptrndble;
begin
while Ld < > nil do
begin
P := Ultimo(Ld);
,
I

186 Estructura de datos
Suprimedir(P,Ld) ; ,
end
end;
visualiza (Ld)
Esta operacin muestra el contenido de la lista en cualquier momento de manejo de la

mIsma.
procedure Visualiza (Ld: Ptrndble);
begin
while Ld<> nil do
begin
Escribir (LdA. Info) ;
Ld := LdA.Sgte
end
end;
6.3. UNA APLICACiN RESUELTA CON LISTAS
DOBLEMENTE ENLAZADAS
En un ambulatorio se desea asociar mdicos con asegurados. Para ello se trata de formar
una lista doblemente enlazada con todos los asegurados. Los datos de cada asegurado
son su nombre y nmero de afiliacin. A su vez, en otra lista doble se tendr a los mdi-
cos del ambulatorio. Los datos de cada mdico son nombre y nmero de telfono (f ono).
La lista de mdicos est ordenada alfabticamente; adems, cada nodo mdico tiene un
campo puntero, que referencia al nodo del primer asegurado asignado. Por consiguiente,
cada nodo de asegurado tiene, adems de los datos propios, un puntero al siguiente ase-
gurado que pertenece al mismo mdico; el ltimo de los asegurados a un mdico, contie-
ne nil en el campo que forma la lista de asegurados a un mdico.
La entrada de datos ser interactiva; primero se introducen los datos de los mdicos;
a continuacin, los datos de los asegurados. La asignacin de los asegurados a los mdi-
cos se har de manera aleatoria.
Anlisis
La representacin grfica de las dos listas a crear:
Mdico Referencia Asegurado Referencia
Amador 6 1 Luis M 5
Castro 9 2 Marta B
3 Mertoli 7
4 Tonino
5 Rufis A 3
6 Rios e 8
7 Fausto F nil
8 Slisa N 3
9 Doroteo
.

,
l
,
I
,
<

l
1
j




Listas doblemente enlazadas 187
De esta representacin podemos obtener que la lista de asegurados con el mdico
Amador comienza en el nodo <6>, Rios e, que le sigue <8>, Slisa N, al nodo <3>,
Mertoli , despus <7>, Fausto F, y aqu termina.
Para la representacin de datos, el nodo del mdico:
Anter Nomb re Te l fono Sgte
- -
-
--.
L_a s g : es el campo puntero al siguiente de la lista de asegurados.
El nodo del asegurado:
Anter Nomb re Idt Sgt e
- -
-
--.
Los tipos de datos y operaciones con lista doble de asegurados en la unidad Lis tAsg.
Unidad
unit Lis t Aseg ;
interface
type
ListAseg
Cadna30 =st ri ng[30] ;
Cadna1 1 =st ri ng [1 1 ] ;

NodoAs=record
Nombre :Cadna 30 ;
I dt : Cadna11;
S_ asg : Pt r As; {Referenci a a si guiente asegurado de un mismo md i co}
Anter , Sgte : PtrAs
end;
{Oper aciones}
Li stavacia (var Ld : PtrAs) ;
Esvacia ( Ld: Pt r As ) : boolean;
Localiza (x : Cadnall ; Ld:Pt r As) : PtrAs ;
procedure
function
function
function
function
Ex i ste (P : PtrAs ; Ld : PtrAs) : boolean;
Ult i mo (Ld : PtrAs) : PtrAs ;
procedure I nse rta (Nm: Cadna30; I d : Cadnall ; P :PtrAs ;var Ld : Pt rAs) ;
procedure Inse rtad (Nm: Cadna3 0 ; Id : Ca dnal1 ;P: PtrAs ;var Ld :PtrAs) ;
procedure Insertafi n (Nm:Cadna 30 ; Id : Cadna l 1 ;var Ld :PtrAs) ;
procedure Supr ime (I d: Cadnall ; var Ld : Pt r As) ;
procedure Supr emedir(P : PtrAs ; var Ld: Pt r As) ;
procedure Visuali z a (Ld : PtrAs);
implementation
uses crt;

188 Estructura de datos
procedure Listavacia (var Ld:PtrAs);
begin
Ld:=nil
end;
function Esvacia (Ld:PtrAs) :boolean;
begin
Esvacia:=Ld=nil
end;
function Localiza (X:Cadnall;Ld:PtrAs) :PtrAs;
{Bsqueda se hace por el cdigo de identificacin}
var
T:PtrAs;
begin
T:=Ld;
if not Esvacia (Ld) then
while (TA.Sgte<>nil) and (TA.ldt<>X) do
T:=TA.Sgte;
if TA.ldt<>X then
Localiza:=nil
elee
Localiza:=T
end;
function Existe (p:PtrAs; Ld:PtrAs) :boolean;
begin
if not Esvacia (Ld) and (P<>nil) then
begin
while (Ld<>P) and (LdA.Sgte<>nil) do
Ld:=LdA.Sgte;
Existe:=Ld=P
end
elee
writeln ('Error en llamada'); {<Msge (Error) >}
end;
function Ultimo (Ld:PtrAs) :PtrAs;
{El ltimo de lista vaca consideramos nil}
begin
if Esvacia (Ld) then
Ultimo:=nil
elee begin
while LdA.Sgte<> nil do
Ld:=LdA.Sgte;
Ultimo:=Ld
end
end;
functlon Crear (Nm:Cadna30;Id:Cadnall) :PtrAs;
var
N:PtrAs;
begin
new(N) ;
NA.Nombre:=Nm;NA.ldt:=Id;NA.S_asg:=nil;
NA.Sgte:=nil;NA.Anter:=nil;
Crear:=N
end;
Listas doblemente enlazadas 189
procedure I ns erta(Nm: Cadna30 ; Id : Cadnal l ; P :Pt r As ; var Ld :Pt r As );
{Aade a l a l i s ta Ld un nodo con e l campo X, de l a n te d e l n odo P }
var
A:PtrAs ;
begin
A:=Crea r (Nm, Id);
if Es vacia (Ld) then
Ld : =A
el se if p=Ld then {De l ante del pri mer n odo}
begin
AA . Sg te:=P;
pA. An t e r:=A;
Ld : =A
end
else if Ex ist e (P , Ld) then

begin {Aho ra e s cuando se enlaza e l n uevo nodo e n tre e l no d o


ante r i or y el nodo P}
pA . An t erA.Sgte:=A;
AA.Anter:=pA.Anter ;
AA. Sgte:=P;
p A.Anter:=A
end
end;

procedure I nsertad (Nm : Cadn a30 ;Id : Cadna ll;p: Pt rAs; var Ld :Pt rAs ) ;
{Aad ir nodo c on el campo X a cont i nua cin de l nodo P e n l a l is ta}
var
N: Pt r As ;
begin
if Es v a c i a ( Ld ) then
Ld : =Cr ear(Nm, I d )
else if P = Ultimo( Ld ) then
Insertafin(Nm,Id,Ld )
else if Existe(P,Ld) then
begin {Ahora es cuan do se enl aza el n uev o nodo, a con ti nuacin
d el n odo P}
N: =Cr ea r (Nm, I d ) ;
pA . Sg t eA . An ter : =N ;
NA. Sg t e :=pA. Sgte ;
pA. Sgte :=N;
NA. An ter:=P
end
end;
procedure Insertafin (Nm: Cadn a30 ;Id:Cadnall;var Ld :PtrAs );
var
N, U: PtrAs;
begin
N: =Crear(Nm, I d) ;
if Esvac i a ( Ld ) then
Ld:=N
else begin
U: =Ult imo (Ld) ;
UA. Sgt e :=N;
NA . Ant er :=U
end
end;



i

190 Estructura de datos
{Borrado de nodos}
procedure Supr ime(Id:Cadna l l ; var Ld: Pt r As) ;
var
P : PtrAs ;
begin
P : =Loca liza(Id , Ld) ;
if P<> nil then
Suprimedir ( P, Ld)
el se
wri teln ( ' Error en la l lamada .' )
end;
procedure Sup r imedir ( P :PtrAs; var Ld : PtrAs) ;
begin
if Ex i ste (P , Ld) then
begin
if p=Ld then (Primer nodo)
begin
Ld:=LdA.Sg te ;
LdA.Anter: =nil
end
else if P<>Ultimo(Ld) then
begin
pA . An t e r A. Sgte : =p A. Sgte;
p A. Sg t e A. Anter :=pA . Anter
end
el Be
p A. Ant erA . Sgte :=nil;
dispose(P)
end
end;
procedure Visuali za( Ld :Pt r As) ;
procedure Esc r ibir(A: NodoAs) ;
begin
write(A. Nombre} ; go t oxy(3l,whereY) ;
writeln(A. ldt)
end;
begin
while Ld<> nil do
begin
Esc ri b ir (Ld
A
) ;
Ld : =LdA.Sgte
end
end;
begin
end.
,


Los tipos de datos y operaciones bsicas para formar una lista doble ordenada las
representamos en la unidad Li s tMe d.
Unidad
unit Li stMe d;
interface
ListMed

,
,
Listas doblemente enlazadas 191
ueee ListAseg;
type
Cadna30=string[30] ;
Cadnall=string[ll] ;
PtrMd=ANodoMd;
NodoMd=record
Nombre:Cadna30;
Fono:Cadnall;{telfono}
L_asg:PtrAs;
Anter,Sgte:PtrMd
end;
function Posinser (X:Cadna30;L:PtrMd) :PtrMd;
procedure Inserorden (M:Cadna30;F:Cadnall;var L:PtrMd);
function Buscorden (X:Cadna30;L:PtrMd) :PtrMd;
procedure Mostrar (L:PtrMd);
implementation
function Posinser (X:Cadna30;L:PtrMd) :PtrMd;
begin
if(L<>nil) then
begin
while (X >= LA.Nombre) and (LA.Sgte<>nil) do
L:=LA.Sgte;
if X >= LA.Nombre then {Es el ltimo nodo}
Posinser:=L
elee
Posinser:=L
A
. Anter
end
elee {Lista vaca}
end;
procedure Inserorden(M:Cadna30;F:Cadnall;var L:PtrMd);
var
A, N:PtrMd;
begin
new(N); NA.Nombre:=M; NA. Fono:=F;NA.L_asg:=nil;
NA.Sgte:=nil; NA.Anter:=nil;
if L=nil then
L:=N
elee begin
A:=Posinser(M, L);
if A=nil then {Aadido como primer nodo}
begin
NA.Sgte:=L;LA.Anter:=N;
L:=N
end
elee begin {Aadido a partir de A}
NA.Sgte:=AA.Sgte; NA.Anter:=A;
if AA.Sgte<>nil then
AA.SgteA.Anter:=N;
AA.Sgte:=N
end
end
end;

,
,
192 Estructura de datos
function Buscord e n ( X: Cadna30 ; L :Pt r Mdl : Pt r Md ;
var
T:Pt rMd ;
begin
T: =L ;
while (TA.Sg te<>n i ll and (TA .Nombre < Xl do
T : =TA.Sgte;
if TA .Nombre =X then
Buscorden:=T
el se
Busco r d e n : =nil
end;
procedure Mos t ra r (L : PtrMd l ;
var
Q: Pt r Md ;
begin
Q: =L ;
while Q<>nil do
begin
writeln(QA.Nombr e ," , QA.Fo no); Q: =QA. Sgte
end
end;
end.
Programa Ambulatorio de creacin de listas
La primera accin para crear esta superestructura es dar entrada a los datos de los
mdicos y dar de alta los asegurados del ambulatorio. Por ltimo, asignar (se hace
aleatoriamente) cada asegurado a un mdico, y formar la lista virtual de asegurados de
un mdico.
Realmente hay dos nicas listas, mdicos y asegurados. A nivel lgico se forma una
lista por cada mdico para ello se utiliza el campo S_ asg con el que va enlazando los
asegurados del mismo mdico.
Los nombres de los mdicos y sus nmeros de fono se encuentran en el archivo de
texto Me d i e o s . t x t; al igual que los nombres de las personas adscritas al ambulatorio
que estn en el archivo As e gurad . t x t.
Una vez formada toda esta superestructura pueden plantearse otros problemas, como,
por ejemplo, dado un mdico listar sus asegurados; otra operacin, dado un asegurado
mostrar el doctor que le pertenece, y otras ms que podemos pensar de utilidad. En el
programa se realiza la operacin de listar todos los asegurados que tiene un mdico.
program Ambu l at o r io ;
uses ListAseg,ListMe d, Crt;
var
Lme d , Md : PtrMd ;
Las g : PtrMd ;
Fme d , Fasg : Te x t ;
Nb : Cadna3 0 ;
Ch : char ;
!

,
,
,

'.

procedure Medicos(var Lm:PtrMd);
var
Nm:Cadna30;F:Cadnall;
J:integer;
begin
Lm:=nil;
repeat
readln(Fmed,Nm) ;
readln(Fmed,F) ;
Inserdorden(Nm,F,Lm) ;
until eof(Fmed);
end;
procedure Asegurados(var Las:PtrAs);
var
Nm:Cadna30;Id:Cadnal1;
begin
Las:=nil;
repeat
readln(Fasg,Nm) ;
readln(Fasg,Id) ;
Insertafin(Nm,Id,Las)
until eof(Fasg)
end;
Listas doblemente enlazadas 193
{LOS siguientes procedimientos asignan aleatoriamente cada asegurado a un
mdi co. Para ello se cuenta el nmero de mdicos y con una funcin
random, se asocia un asegurado al mdico}
function Posicion(L:PtrMd;K:integer) :PtrMd;
begin
while K>l do
begin

K:=K- l
end;
Posicion:=L
end;
procedure Asocia(Asg:ptrAs;Lm:PtrMd);
var
C: integer ;
M:PtrMd;
function Cuantos(L:PtrMd) :integer;
var K:integer;
begin
K:=O;
while L<> nil do
begin
L:=LA.Sgte;
K:=K+l
end;
Cuantos := K
end


,
,

,

\

!
\
,
i
,
,
I
,

,
194 Estructura de datos
begin
randomize;
C:=Cuantos (Lm);if C=O then Asg:=nil; {Para no entrar en el bucle}
while Asg<>nil do
begin
M:=posicion(Lm, random(C)+l);
write(AsgA.Nombre) ;gotoxy(31,wherey);
write( 'tiene asignado al doctor');
writeln(MA.Nombre) ;
{Enlazamos en la lista de asegurados, como el primero de ella}
AsgA.S_asg:=MA.L_asg;
MA.L_asg:=Asg;
Asg:=AsgA.Sgte
end
end;
procedure VerAseg(M:PtrMd);
var A:PtrAs;
begin
{Recorre, visualizando por pantalla, los asegurados de un mdico}
A:=MA.L_asg;
while A<>nil do
begin
write(AA.Nombre) ;gotoxy(31,whereY) ;writeln(AA.Idt);
A:=AA.S_asg ;
end
end;
begin {programa Ambulatorio}
clrscr;
{Es creada la lista doble ordenada de mdicos}
assign (Fmed, 'Medicos. txt'); reset (Fmed) ;
Medicos (Lmed);
Mostrar(Lmed) ;
repeat until readkey

ln [#0 .. #255] ;clrscr;
{Es creada la lista doble de asegurados}
assign(Fasg, 'Asegurad.txt') ;reset(Fasg);
Asegurados (Lasg) ;
Visualiza(Lasg) ;
repeat until readkey in [#0 .. #255] ;clrscr;
{Se asocian}
Asocia (Lasg.Lmed);
repeat
gotoxy(lO,WhereY+2) ;
write( 'Nombre del mdico:') ;readln(Nb);
Md:=Buscorden(Nb,Lmed) ;
if Md<>nil then
VerAseg(Md)
elee
writeln( 'Mdico no est en el ambulatorio');
repeat write( 'Otro mdico:') ;readln(Ch)
until upcase (Ch) in [' S', 'N']
until Ch in ['N', 'n']
end. {Fin de programa Ambulatorio}
Listas doblemente enlazadas 195
6.4. PLE NTACIN DE UNA LISTA CIRCULAR
MEDIANTE VARIABLES DINMICAS
En las listas lineales siempre hay un ltimo nodo que tiene el campo de enlace a ni l .
Esto presenta el inconveniente de que dada la posicin de un nodo P no se puede alcan-
zar cualquier otro nodo que preceda al nodo P .
Haciendo un pequeo cambio en la estructura de una lista lineal, de tal manera que
no haya, al menos a nivel lgico, un ltimo nodo sino que los nodos formen una estruc-
tura circular, podremos acceder a todos los nodos a partir de uno dado.
Se podra decir que el cambio que hay que hacer es que el ltimo nodo en vez de
apuntar a n i 1 apunte al primer nodo. En realidad, en una estructura circular no hay
Le
4

primero ni ltimo.
Una lista circular, por su naturaleza no tiene primero ni ltimo nodo. Sin embargo,
resulta til establecer un primer y un ltimo nodo. Una convencin es la de considerar
que el puntero externo de la lista circular referencia al ltimo nodo, y que el nodo si-
guiente sea el primer nodo. Todos los recorridos de la lista circular se hacen tomando
como referencia el considerado ltimo.
Sobre una lista circular pueden especificarse una serie de operaciones, y as formar
el T AD lista circular. Estas operaciones coinciden con las definidas en los T AD lista y
lista doblemente enlazada
Listavaei a (Le)
Esvae i a (Le)
Primero ( Le)
Ultimo (Le)
Anter i o r ( P, Le)
Inicializa la lista.
Funcin que determina si la lista es vaCa.
Devuelve la direccin del primer nodo.
Devuelve la direccin del ltimo nodo.
Devuelve la direccin del nodo anterior a P.
Ins erprim ( X, Le ) Inserta un nodo con la informacin X como primer nodo de
la lista L e .
Inserta ( X, P , Le) Inserta en la lista Le un nodo con el campo X, delante del
nodo de direccin P.
I n ser f i n (X , Le) Inserta un nodo con el campo X como ltimo nodo de la lista L e.
Local i z a (X , Le) Funcin que devuelve la posicin/direccin donde est el cam-
po de informacin x. Si no est devuelve nulo.
Supr i me (X , Le) Elimina de la lista el nodo que contiene a X.
Supr i med i r ( P , Le ) Elimina de la lista el nodo cuya direccin/posicin viene dada
por P.
v isual iz a ( Le) Muestra el campo de informacin de cada nodo de una lista
circular.
.
,
,
196 Estructura de datos
,
6.5. IMPLEMENTACION DE UNA LISTA CIRCULAR MEDIANTE
,
VARIABLES DINAMICAS
En esta implementacin con punteros, hay un puntero externo Le que referencia al que
arbitrariamente se considera ltimo nodo de la lista. Esta realizacin de lista circular a
su vez es simplemente enlazada, por lo que el sentido de recorrido siempre es el mismo.
Puede hacerse con dos enlaces y as podra recorrerse en ambos sentidos.
type
Tipoinfo - ... ;
Ptrnlc = ANodolc
Nodolc = record
Info: Tipoinfo;
Sgte,
Anter: Ptrnlc
end;
Las operaciones de Listavaeia, Esvaeia no hace falta escribirlas, son exacta-
mentes iguales que en las listas dobles. El resto de las operaciones de la especificacin
se detallan a continuacin.
Primero (Le)
function Primero(Lc: Ptrnlc): Ptrnlc;
begin
if not Esvacia(Lc) then
Primero := LcA.Sgte
elee
Primero := nil {Consideracin arbitraria}
end;
Ultimo(Le)
function Ultimo(Lc: Ptrnlc) : Ptrnlc;
begin
Ultimo := Lc
end;
Anterior(P, Le)
function Anterior (P: Ptrnlc; Lc: Ptrnlc) : Ptrnlc;
{Consideramos que el anterior de lista vaca y de direccin no
existente de la lista: nil}
var
A: Ptrnlc;
begin
if Esvacia (Lc) or (P= nil) then
Anterior:= nil
elee begin
A:= Lc;
while (AA.Sgte < > P) and (AA.Sgte < > Lc) do
A :=AA.Sgte; "'- ------_._ .. . _---- --- --- ------ _._----- --
end;
if AA.Sgte= P then
An teri o r:= A
elBe
Anterior:= ni l
end
Loealiza(X, Le)
Listas doblemente enlazadas 197
Funcin que devuelve la posicin/direccin donde est el campo de informacin X. Si
no est devuelve nulo.
function Localiza ( X: Ti po i n f o ; Le : Ptrnl e ): Ptrnl e ;
var
T: Ptrnle;
begin
T:= Le ;
while (TA.Sgte < > Le) and (T A.lnfo < > X) do
T : = TA.Sgte;
if TA.lnfo < > X then
Loca liza := nil
elBe
Loca liza := T
end;
Al igual que ocurre con listas doblemente enlazadas, una versin de Localiza es
la operacin Ex i s te. Es planteada de tal forma que busca la existencia de un nodo,
dada su direccin en una lista circular.
Existe(P, Le)
function Existe ( P: Pt r n l e ; Le: Pt rnl e) : b oo l ean ;
var
T: Ptrnl e ;
begin
if not Es v a e ia(Le ) and ( P < > nil) then
begin
T:= Le ;
while (Le < > P ) and ( Le A. Sgte < > T) do
Le := LeA.Sgte;
Ex i s te := Le = P
end
elBe
Ms ge ( 'Error en ll a ma d a' )
end;

Inserta (X, P, Ld)
Aade a la lista Lc un nodo con el campo X, delante del nodo de direccin P. Para
las operaciones de insercin escribimos la operacin de crear un nodo para una lista
circular.
198 Estructura de datos
function Crear(X: Tipoinfo): Ptrnle;
var
N: Ptrnle;
begin
new (N) ;
NA.Info
NA.Sgte
Crear :=
end;
f-

-
-
-
-
N
A
X

,
N

,
Al aadir un nuevo nodo: Le

A
procedure Insera(X:Tipoinfo; P:Ptrnle; var Le:Ptrnle);
var
A: Ptrnle;
begin
A:= Crear(X);
if Esvaeia(Le) then
Le:= A
elae if Existe(P, Le) then
B
begin {Ahora es cuando se enlaza el nuevo nodo entre el nodo anterior y
el nodo P}
Anterior(P, Le)A.Sgte := A;
AA.Sgte := P;
end
end;
Inserprim(X, Le)
Aade un nodo con campo de informacin X como nodo que est a continuacin del
considerado el ltimo, Lc. En el caso de que la lista est vaca, crea la lista con dicho
nodo.
Procedure Inserprim(X:Tipoinfo; var Le: Ptrnle);
var
N: Ptrnle;
begin
N := Crear(X);
if Esvaeia(Le) then
Le := N
elae begin
NA.Sgte := LeA.Sgte;
LeA.Sgte := N
end
end;
Inserfin(X, Le)
Aade un nodo con el campo X como ltimo nodo de la lista L c. De estar vaca crea la
lista con dicho nodo. En cualquier caso, esta operacin siempre devuelve la direccin
del nuevo nodo: el ltimo.
200 Estructura de datos
I
6.6. IMPLEMENTACION DE LISTAS CIR RES
CON DOBLE ENLACE
Esta implementacin de listas circulares con nodos que tienen dos punteros, permiten
recorrer la lista circular en sentido del avance del reloj, o bien en sentido contrario. Los
tipos de datos para realizar una lista circular con doble enlace son:
type
Tipoin f o - string;
PtrDne - ANodoDe;
NodoDe = record
Inf o : Tipo inf o ;
Sgte , Anter : PtrDnc
end;
Las operaciones de insercin tienen que contemplar el doble enlace para forlllar la
lista circular. Lo mismo a la hora de suprimir un nodo de la lista. La operacin de reco-
rrer la lista se puede hacer en dos direcciones o bien con el puntero sgte o bien con el
puntero An ter. A continuacin se escribe el procedimiento que recorre la lista hacia
adelante:
procedure Re eorre_ A (Lde:PtrDnc) ;
var A:PtrDne;
begin
if not Esvacia ( Lde) then
begin
A:=Lde;
repeat
A := AA.Sgte;
Eseribir(AA.lnfo)
until A = Le;
end
end;
.. ..
rt
a)
Cabecera --,
b)
t
Figura 6.1. Lista circular doblemente enlazada con un nodo cabecera.
Listas doblemente enlazadas 201
Tambin se escribe el procedimiento para recorrer la lista desde el ltimo nodo al
primero. Recordemos que Ldc referencia al nodo que por convenio consideramos
ltimo; se utiliza el puntero Anter.
procedure Recorre_D(Ldc:PtrDnc);
var D:PtrDnc;
begin
if not Esvacia (Ldc) then
begin
D: =Ldc;
repeat
Escribir(DA.lnfo) ;
D:=DA.Anter
until D=Ldc
end
end;
PROBLEMA 6.1. Lista circular doblemente enlazada y ordenada
Se trata de escribir un procedimiento que tenga como entrada una lista circular con
doble enlace, siendo el campo info ordinal, y nos devuelva la lista ordenada.
En realidad se construye con dos procedimientos. El procedimiento ordenar reci-
be la lista, rompe la estructura circular, se convierte en una lista lineal y ordena la
lista; el procedimiento ordene ir compone la estructura circular. E/'nodo de la lista
tiene como campo in f o valores enteros, y los dos campos puntero para enlazar que
ahora se /laman izqdo y dcho.
type
ptro=Anodo;
nodo=record
izdo,
dcho:ptro;
info:integer
end;
var
cab:ptro;
procedure ordenar (var cab:ptro);
var
p,q,aux:ptro;
begin
p:=cab;
while p<>nil do
begin
q:=pA.dcho;
while q<>nil do
if p A.info <= qA.info then
q:=qA.dcho
elee
begin
{"saca" de la lista el nodo q}
qA.izdo A.dcho:=qA.dcho;


,

202 Estructura de datos
if q A.dcho<> nil then
A d hA' d A ' d
q . e o .l.Z O:=q .l.Z O;
{aade q c omo anterior a p}
aux:=qA.dc ho;
qA.deho:=!);
qA.izdo:=pA.izdo;
pA.izdo:=q;
if qA.izdo=nil then
cab:=q
el se
qA.izdo A.dcho:=q;
p:=q;
q:=aux
end;
p:=PA.dcho
end
end;
procedure ordeneir (var el:ptro);
var
aux:ptro;
begin
if el<>nil then
begin
aux:=cl A.izdo ;
auxA.dcho :=nil;
cl A.izdo:=nil;
ordenar (el);
aux:=el;
while auxA.dcho<> nil do
aux:=auxA.deho;
auxA.dcho:=el;
elA.izdo:=aux
end
end;
PROBLEMA 6.2. Cadenas de caracteres mediante listas circulares
Dos cadenas de caracteres estn almacenadas en dos listas circulares. Se accede a di-
chas listas mediante los punteros Le 1, Le 2. Escribir un subprograma que devuelva la
direccin en la cadena Le 2 a partir de la cual se encuentra la cadena Lelo
Solucin
En primer lugar, se escribe una unidad que defina los tipos de datos necesarios y la
funcin que resuelve el supuesto planteado. A esta unidad se la puede aadir otros pro-
cedimientos o funciones para crear listas circulares, visualizarlas ...
unit Lista_ci
interface
type
Tinfo = ehar;

Ptrlc = ANodolc;
Nodolc= record
Info : Tinfo;
Sgte : Ptrle
endl
function Direccion(Lc l, Le2:Ptrlc): Ptrle;
implementation
function Direeeion(Lel, Le2:Ptrlc): Ptrle;
var
A, A2, B: Ptrle; Sw:boolean;
bel1in
A := Lc2;
A2:= Le2;
B := Lel;
repeat
if AA.lnfo = BA.lnfo then
begin
A := AA.Sgte;Sw:=true;
B := BA.Sgte
end
elee
bel1in
A2 :=A2
A
.Sgte;A:=A2;
B := Lcl; Sw:=false
end
until (A = Lc 2 ) or (B=Lcl)and Sw;
if (B=Lel and Sw) then
Direeeion:= A2
elee
Direecion := nil
end;
end.
RESUMEN
Listas doblemente enlazadas 203
,
Las listas doblemente enlazadas son aquel tipo de lista que se puede recorrer avanzando en cual-
quiera de los sentidos.
Otro tipo de lista muy eficiente es la lista circular, que es, por naturaleza, la que no tiene
primero ni ltimo nodo.
Aunque una lista enlazada circularmente tiene ventajas sobre una lista lineal pero presenta
tambin algn inconveniente, como no poder recorrer la lista en sentido inverso. En estos casos la
lista idnea es una lista doblemente enlazada, en la que cada nodo de la lista contiene los punte-
ros, uno a su predecesor y otro a su sucesor.
Las listas doblemente enlazadas pueden ser o bien lineales o circulares y pueden o no conte-
ner un nodo de cabecera.
Los nodos de una lista doblemente enlazada constan de tres campos: un campo in/o, que
contiene la informacin almacenada en el nodo, y los campos izquierdo y derecho, que contienen
punteros a los nodos de cada lado.
"
,
,
,
,
, ,
,
,
,
I
,
I
j
I
1
,
,
i
"
l'
,
,


l
1
,
1
,
,
,
,
,
,
,
,
,
,

,
,




i
" ,
,
f
,
!
,
,

204 Estructura de datos


EJERCICIOS
6.1. Dibujar una lista doblemente enlazada, Ld, de nombres de personas con un nodo cabecera.
Escribir el procedimiento Lista_vaca que inicializa Ld como vaca.
6.2. Escribir la funcin Esvae ia que devuelve cierto si la lista Ld con nodo de encabezamien-
,
to es vaCla.
6.3. Dada la lista doble con nodo de encabezamiento Ld, escribir el procedimiento de insertar
un nodo antes del nodo de direccin P.
6.4. En la lista doble con nodo de encabezamiento borrar el nodo que tiene como campo de
informacin X.
6.S. Dada una lista doble sin nodo de encabezamiento cuya direccin de acceso Ld es el primer
nodo, la infoJlnacin de cada nodo es una cadena de caracteres; escribir un procedimiento
para visitar los nodos del primero (Ld) al ltimo, convirtiendo las cadenas a maysculas; a
continuacin visite los nodos del ltimo al primero (Ld) mostrando los nodos por pantalla.
6.6. Escribir un procedimiento que tenga como parmetro de entrada Le. Suponer que Le apun-
ta al primer nodo de una lista circular doblemente enlazada de caracteres. El procedi-
miento debe de escribir los caracteres de la lista Le en orden inverso, es decir, del ltimo al

pnmero.
c
La salida debe ser: R T J H
6.7. Hacer lo mismo que en el ejercicio 6.6 pero con una lista simplemente enlazada.
6.8. Dibujar una lista circular doblemente enlazada con nodo de cabecera. El nodo de cabecera
es tal que sus dos campos puntero referencian a los nodos extremos de la lista.
6.9. Dada la representacin de lista circular propuesta en 6.8, escribir las operaciones Lista_vaca
y la funcin Esvaca.
6.10. Con la representacin de lista circular de 6.8, escribir las operaciones de insertar como
ltimo nodo e insertar como primer nodo.
6.11. Con la representacin de lista circular de 6.8, escribir la funcin de localizar el nodo con el
campo de informacin X y la operacin de eliminar el nodo con campo de informacin X.
PROBLEMAS
6.1. Dada una lista doblemente enlazada de nmeros enteros, escribir las rutinas necesarias para
que dicha lista est ordenada en orden creciente. La ordenacin se ha de hacer intercam-
biando los punteros a los nodos.
6.2. Tenemos una lista doblemente enlazada ordenada con claves repetidas. Realizar un proce-
dimiento de inserccin de una clave en la lista, de tal forma que si la clave ya se encuentra
en la lista la inserte al final de todas las que tienen la misma clave.
6.3. En una lista simplemente enlazada L se encuentran nombres de personas ordenados alfab-
ticamente. A partir de dicha lista L crear una lista doblemente enlazada LL de tal forma que
el puntero de comienzo de la lista est apuntando a la posicin central. Damos por supuesto
que la posicin central es el nodo que ocupa la posicin n/2, siendo n el nmero de nodos
de la lista. Obviamente, los nodos que se encuentran a la derecha de la posicin central
estn ordenados ascendentemente y los que se encuentran a la izquierda ordenados de ma-
nera decrecientemente.

Listas doblemente enlazadas 205


6.4. Dada una cadena de caracteres almacenada en una lista circular Le, escribir un subprogra-
ma que transforme la cadena Le de tal forma que no haya caracteres repetidos.
6.5. En el archivo LIBROS se encuentran almacenados los datos relativos a la biblitoeca
municipal de Lupiana. Los campos de que consta cada registro son: Autor, Ttulo, N-
mero de ejemplares. Escribir un programa que realice como primera accin formar una
lista doblemente enlazada ordenada respecto al campo Autor, cuya direccin de acceso
sea el nodo que ocupe la posicin central. Con la lista se podrn realizar estas otras opera-

ClOnes:
Mostrar todos los libros de un Autor.
Prestar un ejemplar de un libro, designado por Autor y Ttulo.
Aadir un nuevo libro a la lista.
Dar de baja a todos los libros de un autor.
Al finalizar el proceso deber guardarse en el archivo los libros actuales.
6.6. Escribir un programa para realizar operaciones con vectores dispersos. Un vector disperso
es aquel cuyo nmero de elementos es grande, sin embargo muchos de esos elementos son
cero. La representacin se ha de hacer mediante una lista doblemente enlazada. Cada nodo
de la lista ha de tener un elemento del vector distinto de cero junto al ndice del elemento.
El programa debe de permitir estas operaciones:
Dado un vector disperso, representarlo en una lista doble.
Dados dos vectores mediante sendas listas L 1, L2, obtener el vector suma L 1 + L2.
Podr haber nuevas posiciones que sean cero.
Dados dos vectores L 1, L 2, obtener el vector diferencia (L 1- L 2 ) . Tener en cuenta
que puede haber nuevas posiciones que sean cero.
6.7. El polinomio P(x) = ao + a IX + a2x2 + ... + a,.x" deseamos representarlo en una lista circular
enlazada, de tal forma que cada nodo contenga el coeficiente y el grado de un monomio.
Escribir un programa que tenga como entrada los coeficientes y exponentes de cada trmi-
no de un polinomio, y forme una lista circular para representarlo. El puntero de acceso a la
lista circular ser el del nodo que contiene al tllnino de grado n, a partir de l se acceder
al tllnino de grado 0, y as sucesivamente. En el programa deben de encontrarse las opera-

ClOnes:
Evaluacin del polinomio para un valor dado de x.
Obtencin del polinomio derivada de P(x).
Obtencin del polinomio producto de dos polinomios.
6.8. Se desea sumar enteros muy largos utilizando listas circulares doblemente enlazadas. Es-
cribir una unidad donde se encuentren los tipos de datos y las operaciones para manejo de
listas circulares dobles. Escribir un programa que permita la entrada de enteros largos, rea-
lice la suma y los muestres por pantalla.
6.9. Escribir un programa para sumar enteros largos utilizando listas circulares con doble enla-
ce y un nodo de encabezamiento (segn se indica en los ejercicios 6,8,9, 10 Y 11). Previa-
mente escribir la unidad con tipos de datos y operaciones para manejo de listas circulares
con nodo de encabezamiento.

,
CAPITULO
pi a
CONTENIDO
7.1. Especificacin formal del tipo abstracto de datos Pila.
7.2. Implementacin del TAO pila con arrays.
7.3. Implementacin del TAO Pila mediante variables dinmicas.
7.4. Evaluacin de expresiones aritmticas mediante pilas.
RESUMEN.
EJERCICIOS.
PROBLEMAS.
Una pila es una estructura de datos en la que todas las inserciones y
eliminaciones de elementos se realizan por un extremo denominado
cima de la pila. Una analoga es una pila de platos o una pila de cajas.
La implementacin de una pila se puede realizar mediante arrays o
con punteros. El inconveniente de la implementacin de una pila con
un array es que su tamao mximo se debe especificar en tiempo de
compilacin. Para resolver este inconveniente, la implementacin de
una pila se ha de realizar con punteros (apuntadores).
El desarrollo de las pilas como tipos abstractos de datos es tam-
bin otro de los motivos centrales de este captulo. En el mismo se
ver cmo utilizar el TAD Pila para resolver problemas de diferentes
tipos.
,
7.1. ESPECIFICACION FORMAL DEL TIPO ABSTRACTO
DE DATOS PILA
Una pila es una lista ordenada de elementos en la que todas las inserciones y supresio-
nes se realizan por un mismo extremo de la lista. En una pila el ltimo elemento aadido
es el primero en salir de la pila. Por esa razn a las pilas, se las denomina tambin listas
207
.

1
,

i
I
! I
,
,
I
,

208 Estructura de datos


Lifo (Last input jirst output, ltimo en entrar, primero en salir). En la mente se tiene la
imagen intuitiva de una pila. As, si nos referimos a una pila de platos, sabemos que los
platos se toman por arriba, por la cabeza. En la vida cotidiana se encuentran infini-
dad de ejemplos; as a veces se dice que apilamos los libros de un curso ...
Pila






Las pilas crecen y decrecen dinmicamente, es una estructura de datos dinmica. En
cuanto a la representacin de una pila utilizando las estructuras de datos que tiene el
lenguaje, existen varias formas. Al ser una pila una coleccin ordenada de elementos, y
ser los arrays tambin una coleccin ordenada de elementos se tiene una forma de repre-
sentar las pilas. En definitiva, una primera representacin se realiza mediante la estruc-
, .
tura estatlca array.
Una segunda forma de representar una pila es con listas enlazadas. Las listas crecen
y decrecen dinmicamente, al igual que ocurre en una pila. Es una representacin din-
mica que utiliza punteros y variables dinmicas. Las operaciones bsicas que definen el
TAO pi 1 a son las siguientes:
Pilavacia(P)
Esvacia(P)
Cima(P)
Suprime(P)
Sacar(X,P)
Meter(X,P)
Crea una pila sin elementos.
Devuelve verdadero si la pila P no tiene elementos.
Devuelve el elemento que est en la cima de la pila.
Elimina el elemento que est en la cima de la pila.
Devuelve el elemento cabeza y lo suprime.
Aade el elemento X en la pila.
7.2. I PLEMENTACIN DEL TAO PILA CON ARRAYS
Un array constituye el depsito de los elementos de la pila. El rango del array debe ser lo
suficientemente amplio para poder contener el mximo previsto de elementos de la pila.
Un extremo del array se considera el fondo de la pila, que permanecer fijo. La parte

Pilas: el TAD pi la 209


superior de la pila, cima, estar cambiando dinmicamente durante la ejecucin del pro-
grama. Adems del array, una variable entera nos sirve para tener en todo momento el
ndice del array que contiene el elemento cima. Las declaraciones, procedimientos y
funciones para representar el TAD pila forman parte de la unidad pilas.
const
Maxelems = 100; {Depender de cada realizacin}
type
Indicepila = O .. Maxelems;
Tipoelemen = ... {Tipo de los elementos de la pila}
Tipopila = record
Elementos: array[l .. Maxelemsl of Tipoelemen;
Cab: Indicepila
end;
En funcin de esta representacin se codifican las operaciones bsicas definidas en
TAD pi/a: Pi/avacia, Esvacia, Cima, Suprimir, Sacar, Meter y Pi/aliena.
Pilavacia(P)
procedure Pilavacia(var P: Tipopila);
begin
P.Cab:= o
end;
Esvacia(P)
function Esvacia(P: Tipopila): boolean;
begin
Esvacia:= P.Cab=O
end;
Cima(P)
Esta funcin devuelve el elemento cabeza de la pila, sin modificar la pila.
function Cima(P: Tipopila): Tipoelemen;
begin
if not Esvacia(P) then
cima := P.Elementos[P.Cabl
end;
Suprime(p)
Esta operacin elimina el elemento cabeza, modificando la pila.
procedure Suprime(var P: Tipopila);
begin
if not Esvacia(P) then
P.Cab:= P.Cab- 1
end;
1
,


210 Estructura de datos
Sacar(X, P)
Esta operacin devuelve el elemento cabeza y lo suprime.
procedure Sacar(var X:Tipoe1emen; var P:Ti pop i1a) ;
begin
if not Esvacia(P ) then
with P do
begin
X:= Eleme n t os [ CabJ ;
Cab : = Cab- 1
end
end;
Meter(X, P)
Esta operacin aade el elemento X a la pila. Cuando se aade un elemento se dice
que ste es empujado dentro de la pila.
Al estar representando la pila mediante una estructura esttica puede ocurrir que no
haya posiciones libres en el array. Por esta circunstancia se ha de incorporar una opera-
cin P 11 ena que devuelve verdadero si se ha alcanzado el nmero mximo de elemen-
tos previstos.
function P1 1ena(P : Tipop i1a): boo1ean ;
begin
P11ena := P.Cab=Maxe1ems
end;
procedure Meter(X: Tipoe1emen; var P: Tipopi1a) ;
begin
if not P11ena(P) then
with P do
begin
Ca b:= Cab+ 1;
Elementos[CabJ: = X
end
end;
PROBLEMA 7.1. Utilizacin de una pila
Se desea invertir una cadena de caracteres y se trata de determinar si han sido inverti-
dos correctamente dichos caracteres. Para ello se lee la cadena de caracteres; a conti-
nuacin, en la siguiente lnea los caracteres de la cadena invertidos.
La estrategia a seguir es sencilla, los caracteres de la cadena se almacenan en una
pila. Segn se van leyendo los caracteres de la cadena invertida se comparan con el
carcter cima de la pila; de este modo se aprovecha la principal caracterstica de una

Pilas: el TADPila 211
pila: ltimo en entrar primero en salir. El ltimo carcter introducido debe ser igual que
el primer carcter de la cadena invertida.
function Esinversa: boolean;
var
Ch: char;
Pila: Tipopila;
Inv: boolean;
begin
Pilavacia(Pila) ;
writeln ( 'Caracteres de la cadena: ');
repeat
read (Ch) ;
Meter(Ch, Pila)
until eoln;
readln;
{Los caracteres ledos son comparados con la pila}
Inv:= true;
while not Esvacia(Pila) and Inv do
begin
read (Ch) ;
Inv:= Ch= Cima(Pila);
Suprimir(Pila)
end;
{Consideramos que si hay ms caracteres que en la pila, no ha
sido invertida correctamente}
Esinversa:= Inv and eoln;
readln
end;
Para sacar los elementos de la pila se puede seguir la alternativa de utilizar otra va-
riable carcter D y la operacin Sacar:
while not Esvacia(Pila) and Inv do
begin
read(Ch) ;
Sacar(D,Pila)
Inv:= Ch = D;
end;
7.3. IMPLEMENTACiN DEL TAO PILA
DINMICAS
DI ANTE VARIABLES
La implementacin dinmica de una pila se hace almacenando los elementos como nodos
de una lista enlazada, con la particularidad de que siempre que se quiera meter (empu-
jar) un elemento se har por el mismo extremo que se extraer.
Esta realizacin tiene la ventaja de que el tamao se ajusta exactamente a los ele-
mentos de la pila. Sin embargo, para cada elemento es necesaria ms memoria, ya que
hay que guardar el campo de enlace. En la realizacin con arrays hay que establecer un
mximo de posibles elementos, aunque el acceso es ms rpido, ya que se hace con una
variable subindicada.

i
,
I




,
I
,

212 Estructura de datos


Pila



Los tipos de datos y operaciones en la realizacin con listas son muy similares a los
ya expuestos en listas enlazadas Pilavacia, Esvacia, Cima, Suprime, Sacar y Meter.
type
Ti poelemen= ... {Tipo de los el emen tos de l a p i l a}
ptrp l a= ANo doPla;
Nodopla= record
Element o : Ti poeleme n;
Enl a ce : PtrPl a
end;
Pilavacia(crear pila)
Crea una pila sin elementos.
procedure Pil ava ci a( var Pila : Ptrp l a) ;
begin
Pi l a := n il
end;
Esvacia
Funcin que determina si la pila no tiene elementos.
function Esvacia(Pil a : Pt rp l a) : bool ean;
begin
Esvac i a : = pil a= n i l
end;
Cima(Pila)
Devuelve el elemento cabeza de la pila, sin modificar la pila.
I
,

,
I
,
I
,
I
I

I
function Cima(Pila: Ptrpl a): Tipoel e men;
begin
if not Esvac i a( Pila) then
Cima := pi laA .El e me nt o
end;
Suprime (Pila)
Pilas:elTADPila 213
Con esta operacin se elimina y libera el elemento cabeza, modificando la pila.
procedure Suprime( var Pil a : Pt rpl a) ;
var
Q: Ptrpla;
begin
if not Esvac i a( Pi la ) then
begin
Q: = Pil a ;
pila:= PilaA .Enlace ;
d ispose (Q)
end
end;
Sacar(X, pila)
"'"







Pila
Esta operacin engloba a las dos anteriores. Devuelve el elemento cabeza y lo su-

prime.
procedure Sacar( var X: Tipoe l emen; var Pila : Ptrpla) ;
var
Q: Pt rp la ;
214 Estructura de datos
begin
if not Esvacia(Pila) then
with pila
A
do
begin
Q:= Pila;
X:= Elemento;
pila:= Enlace;
dispose(Q)
end
end;
El procedimiento se puede escribir llamando a cima y Suprimir.
procedure Sacar(var X:Tipoelemen; var Pila: Ptrpla);
begin
X: = Cima ( pi 1 a) ;
Suprime(Pila)
end;
Meter(X, Pila)
Esta operacin aade el elemento X a la pila. En esta representacin con estructuras
dinmicas no tiene sentido la operacin pila llena, la pila crece o decrece segn lo nece-
sita.
-
--
-
--
-
--
--,
--
--



nil
procedure Meter(X: Tipoelemen; var Pila: Ptrpla);
var
Q: Ptrpla;
begin
new(Q) ;
QA.Elemento:= X;
QA.Enlace:= Pila;
pila:= Q
end;
Pila
,
l
,
..
Pilas: el TAO pi l a 215
7.4. EVALUACiN DE EXPRESIONES ARITMTICAS
MEDIANTE PILAS
Una de las aplicaciones ms tpicas del TAD pila es almacenar los caracteres de que
consta una expresin aritmtica con el fin de evaluar el valor numrico de dicha expre-
sin, Una expresin aritmtica est formada por operandos y operadores, As, la ex-
, ,
preslOn
R = X*Y - (A+B)
est escrita de la forma habitual: el operador en medio de los operando, Se conoce como
notacin infija, Conviene recordar que las operaciones tienen distintos niveles de prece-
dencia,
Parn t esis
Po t enc ia




Multipl / di v isi n :
Suma / Resta


() nivel mayor de prioridad
1\
* /
,
+ - , nivel menor de prioridad
Tambin suponemos que a igualdad de precedencia son evaluados de izquierda a
derecha,
7.4.1. Notaciones Prefija (Polaca) y Postfija (Polaca inversa)
La forma habitual de escribir operaciones aritmticas es situar el operador entre sus dos
operandos con la citada notacin infija. Esta forma de notacin obliga en muchas oca-
siones a utilizar parntesis para indicar el orden de evaluacin,
A*B / (A+C) A * B/A+C
Representan distintas expresiones al no poner parntesis. Igual ocurre con las expre-

Slones:
La notacin en la que el operador se coloca delante de los dos operandos, notacin
prefija, se conoce como notacin polaca (en honor del matemtico polaco que la estudi),
A* B / (A+C) ( i nfija) --7 A* B / +AC --7 *AB / +AC --7 I*AB+AC
A* B / A+C (infi j a) --7 * AB / A+C --7 I * ABA+C --7 + / *ABAC
(A- B) ~ C D ( infij a) --7 - A B ~ C D --7 ~ - A B C D --7 ~ - A B C D
(pol a c a )
(po l aca)
( p o lac a)
Podemos observar que no es necesario la utilizacin de parntesis al escribir la ex-
presin en notacin polaca. La propiedad fundamental de la notacin polaca es que el
orden en que se van a realizar las operaciones est determinado por las posiciones de los
operadores y los operandos en la expresin.
,
216 Estructura de datos
Otra forma de escribir las operaciones es mediante la notacin postfija o polaca in-
versa que coloca el operador a continuacin de sus dos operandos.
A*B/ (A+C) (infija) A*B/AC+ AB*/AC+ AB*AC+/ (polaca inversa)
A*B/A+C (infija) AB*/A+C AB*A/+C AB*A/C+ (polaca inversa)
(A-B) AC+D (infija) AB-AC+D AB-CA+D AB-CAD+ (polaca inversa)
7.4.2. Algoritmo para evaluacin de una expresin aritmtica
A la hora de evaluar una expresin aritmtica escrita, normalmente, en notacin infija la
computadora sigue dos pasos:
1.0 Transformar la expresin de infija a postfija.
2. Evaluar la expresin en postfija.
En el algoritmo para resolver cada paso es fundamental la utilizacin de pilas.
Se parte de una expresin en notacin infija que tiene operandos, operadores y pue-
de tener parntesis. Los operandos vienen representados por letras, los operadores
van a ser:
A (potenciacin), *, /, +, - .
La transformacin se realiza utilizando una pila en la que se almacenan los operado-
res y los parntesis izquierdos. La expresin se va leyendo carcter a carcter, los ope-
randos pasan directamente a formar parte de la expresin en postfija.
Los operadores se meten en la pila siempre que esta est vaca, o bien siempre que
tengan mayor prioridad que el operador cima de la pila (o bien igual si es la mxima
prioridad). Si la prioridad es menor o igual se saca el elemento cima de la pila y se
vuelve a hacer la comparacin con el nuevo elemento cima.
Los parntesis izquierdo siempre se meten en la pila con la mnima prioridad. Cuan-
do se lee un parntesis derecho, hay que sacar todos los operadores de la pila pasando a
formar parte de la expresin postfija, hasta llegar a un parntesis izquierdo, el cual se
elimina, ya que los parntesis no forman parte de la expresin postfija.
El algoritmo termina cuando no hay ms items de la expresin y la pila est vaca.
Sea por ejemplo la expresin infija A * (B + e - ( DIE A F) - G) - H, la expresin en postfi-
ja se va ir formando con la siguiente secuencia:
Expresin
A
AB
ABC
Estado de la Pila
Carcter A a la expresin; carcter * a la pila.
Carcter ( a la pila; carcter B a la expresin.
Carcter + a la pila; carcter C a la expresin.
En este momento el estado de la pila es
+
(
*
,
ABC+
ABC+D
ABC+DE
ABC+DEF
ABC+DEFAj
ABC+DEFAj-
ABC+DEFAj-G
ABC+DEFAj-G-*
ABC+DEFAj-G-*H
ABC+DEFAj-G-*H-
Pilas: el TADpila 217
El nuevo carcter ledo es -, que tiene igual prioridad que el ele-
mento cima de la pila +; en consecuencia, el estado de la pila es:
-
(
*
y la expresin es:
Carcter ( a la pila; carcter D a la expresin.
Carcter / a la pila; carcter E a la expresin.
Carcter /\ a la pila; carcter F a la expresin.
Carcter) (parntesis derecho) provoca vaciar la pila hasta un (.
La pila en este momento contiene
/\
/
(
-
(
*
El nuevo estado de la pila es
-
(
*
y la expresin
Carcter - a la pila y se extrae a su vez -;
Carcter G a la expresin; carcter ), son extrados
de la pila los operadores hasta un ( la pila queda
Carcter -, se saca de la pila * y se mete -
Carcter H se lleva a la expresin
Fin de entrada, se vaca la pila:
*
En la descripcin realizada se observa que el parntesis izquierdo tiene la mxima
prioridad fuera de la pila, es decir, en la notacin infija; sin embargo, cuando est dentro
de la pila la prioridad es mnima. De igual forma, para tratar el hecho de que varios
operadores de potenciacin son evaluados de derecha a izquierda, este operador tendr
mayor prioridad cuando todava no est metido en la pila que el mismo pero metido en la
pila. Las prioridades son determinadas segn esta tabla:
218 Estructura de datos

, Prlodaaa.aelltroplJa
,
!Operador

. Prioridad fuera pila

/\
3 4
*
I 2 2 ,
+,
-
1 1
( O 5
Obsrvese que no se trata el parntesis derecho ya que ste provoca sacar operadores
de la pila hasta el parntesis izquierdo. El algoritmo de paso de notacin infija a postfija:
l. Obtener caracteres de la expresin y repetir los pasos 2 al 4 para cada carcter.
2. Si es operando, pasarlo a la expresin postfija.
3. Si es operador:
3.1. Si pila est vaca, meterlo en la pila. Repetir a partir de 1.
3.2. Si la pila no est vaca:
Si la prioridad del operador ledo es mayor que la prioridad del operador
cima de la pila, meterlo en la pila y repetir a partir de 1.
Si la prioridad del operador es menor o igual que la prioridad del opera-
dor de la cima, sacar cima de la pila y pasarlo a la expresin postfija, vol-
ver a 3.
4. Si es parntesis derecho:
4.1. Sacar cima de pila y pasarlo a postfija.
4.2. Si nueva cima es parntesis izquierdo, suprimir elemento cima.
4.3. Si cima no es parntesis izquierdo, volver a 4.1.
4.4. Volver a partir de 1.
5. Si quedan elementos en la pila pasarlos a la expresin postfija.
6. Fin del algoritmo.
, , ,
7.5. APLlCACION PRACTICA DE LA EVALUACION
, ,
DE UNA EXPRESION ARITMETICA
Los tipos de datos, procedimientos y funciones utilizados para codificar el algoritmo
tratado en el apartado anterior se realiza en las unidades Pilaop y ExpPost.
7.5.1. Unidad Pilaop
La unidad pi 1 aop contiene los tipos bsicos para el manejo de las pilas, as como sus
operaciones asociadas.
unit pilaop;
interface
type
Plaopr = ANodopr;
Nodopr= record

,
.,
,
,


,
,
I
,
1

I
,
l
,
,
I ,
-1
1

1
1

1
!
I

,
,
'J
1
I
1
,
,
,
I
1
'o!
,
,
:

j
1 ,
.,
,
j
,
1

I
,

J
:
I
,
,
,
,
,
,

,
,
. ;
.,
,

Info: char;
Sgte: Plaopr
end;
function Pvacia(P: Plaopr ): boolean;
procedure Pcrear(var P: Plaopr);
procedure Pmeter(Ch: char; var P: Plaopr);
procedure Psacar(var Ch: char; var P: Plaopr);
Pilas:elTADPila 219
function Pcima(P:Plaopr) :char; {devuelve el elemento cima de la pila}
procedure Pborrar(var P: Plaopr);
implementation
function Pvacia(P: Plaopr): boolean;
begin
Pvacia:= P=nil
end;
procedure Pcrear(var P: Plaopr);
begin
P:=nil
end;
procedure Pmeter(Ch: char; var P: Plaopr);
var
A: Plaopr;
begin
new(A) ;
:= Ch;
:= p;
P := A
end;
procedure Psacar(var Ch: char; var P: Plaopr);
begin
Ch:= Pcima(P);
Pborrar(P)
end;
function Pcima(P:Plaopr) :char; {devuelve elemento cima de la pila}
begin
if not Pvacia(P) then
Pcima:=
end;
procedure Pborrar(var P: Plaopr );
var
A: Plaopr ;
begin
if not Pvacia(P) then
begin
A: =P;

dispose(A)
end;
end;
end.
222 Estructura de datos
end;
Psacar(It, P);
un ti lIt = ' ( , ;
end;
repeat
Psacar(It, P);
J:= J+l;
Ar [J] . e : = 1 t ;
Ar[J] .oprdor:= true;
until Pvacia(P);
end; {del procedure}
end.
7.5.3. Evaluacin de la expresin en postfija
En un vector ha sido almacenada la expresin aritmtica en notacin postfija. Los ope-
randos estn representados por variables de una sola letra. La primera accin que va a
ser realizada es dar valores numricos a los operandos.
Una vez que tenemos los valores de los operandos la expresin es evaluada. El algo-
ritmo de evaluacin utiliza una pila de operandos, en definitiva de nmeros reales. Al
describir el algoritmo P f es el vector que contiene la expresin. El nmero de elementos
de que consta la expresin es n.
l. Examinar P f desde el elemento 1 hasta el n. Repetir los pasos 2 y 3 para cada
elemento de P f .
2. Si el elemento es un operando meterlo en la pila.
3. Si el elemento es un operador, lo designamos con &, entonces:
Sacar los dos elementos superiores de la pila, los llamamos X e Y, respectivamente.
Evaluar y & X, el resultado es Z = y & X.
El resultado Z, meterlo en la pila.
Repetir a partir del paso 1.
4. El resultado de la evaluacin de la expresin est en el elemento cima de la pila.
5. Fin del algoritmo.
Codificacin de evaluacin de expresin en postfija
Las operaciones para manejar la pila de operandos estn encapsuladas en la unidad
Pilaopdos. Los nombres de las operaciones han sido cambiados para distinguirlos de la unidad
Pilaop. La parte de implementation es la misma, por ello nos limitaremos a escribir la interfaz.
unit Pilaopdos;
interface
type
Plaopdos = ANodopdos;
Nodopdos=record
Info: real;
Sgte: Plaopdos
end;
1
I
,

,
,
j
I
!
,
I
j
1
~
l
,
i
I

i
.,
j
,
,
.:
,
,

Pilas:elTADPila 223
function Povacia(P: Plaopdos ): boolean;
procedure Pocrear(var P: Plaopdos );
procedure Pometer(var P: Plaopdos ;eh: char);
procedure Posacar(var P: Plaopdos ;var eh: char);
function Pocima(P: Plaopdo s): char;
{devuelve el elemento cima d e la pila}
procedure Poborrar(var P: Plaopdos );
{Fin de la seccin de interface. La seccin implementation es igual que
en la unidad Pilaop}
Ahora ya se puede escribir el programa completo que realiza todo el proceso. El
programa Eval ua_Expresion utiliza las unidades Crt, ExpPos t y pi laOpdos;
contiene el procedimiento Leer_oprdos que lee el valor numrico de los operandos,
as como el procedimiento Eva 1 ua que implementa el algoritmos de evaluacin.
program Evalua_Expresion;
uses
ert, ExpPost, Pilaopdos;
var
v: Oprdos;
T: Tag;
1, J:integer;
Valor: real;
procedure Leer_oprdos(E:Tag;N:integer; var V: Oprdos);
{En este procedimiento se asignan valores numricos a los operandos}
var
K: integer;
eh: char;
begin
K:= O;
repeat
K:= K+l;
if not E[K] .Oprdor then {Es un operando, peticin de su valor
numrico}
begin
Ch:= E[K] .e;
write(Ch, '- ');
readln (V[Ch])
end
until K=N
end
procedure Evalua(Pf: Tag; N: integer;
Oper: Oprdos; Var Valor: real);
var
Pila: Plaopdos;
1: integer;
Numl, Num2: real;
Op: char;
begin
1 : = O;
Pocrear (Pila);
repeat
1:=1+1
224 Estructura de datos
if not Pf[1] .Oprdor then
Pometer(Oper[Pf [1] .C], Pila)
else if Pf[I] . Oprdor then
begin
Posacar(Num2, Pila);
Posacar(Numl, Pila);
case Pf [1].C of
,A, :Valor:= Exp(Numl*Ln(Num2)) {Potencia}
, * , : Valor: = Numl *Num2;
' / ' :Valor:= Numl / Num2;
'+' :Valor:= Numl+Num2;
'-' : Valor:= Numl-Num2
end;
Pometer(Valor, Pila)
end;
until 1= N
end;
begin
c lrscr;
writeln( 'Expresin aritmtica(termina #)');
Postfija(T, J);
writeln( 'Asignacin de valores numricos a los operandos');
writeln ;
Leer_oprdos (T, J, V);
Evalua(T, J, V, Va lor);
writeln;
write('Resultado de evaluacin de la expresin: " Valor);
end.
RESU N
Una pila es una estructura de datos tipo UFO (last-in-first-out, ltimo en entrar/primero en salir)
en la que los datos se insertan y eliminan por el mismo extremo, que se denomina cima de la pila.
El proceso de insercin se denomina meter o poner y el de eliminacin se denomina extraer,
quitar o sacar.
Aadir un elemento a una pila se llama operacin meter o poner (push) y eliminar un ele-
mento de una pila es la operacin extraer, quitar o sacar (pop).
El intento de poner un elemento en una pila llena produce un error conocido como desborda-
miento de la pila (s tack overf low). El intento de sacar un elemento de una pila vaca produ-
ce un error conocido como desbordamiento negativo de la pila (s tack underf low).
Una pila puede ser implementada mediante un array o mediante una lista enlazada. Una ven-
taja de una implementacin de una pila mediante una lista enlazada sobre un array es que, con la
lista enlazada no existe lmite previo en el nmero de elementos o entradas que se pueden aadir
a la pila.
Las llamadas a procedimientos recursivos se implementan utilizando una pila (de hecho, to- .
das las llamadas a procedimientos, sean o no recursivas, se implementan utilizando una pila).
El TAO Pi la, al igual que eITAO Lis ta y TAO Cola son, posiblemente, los tipos abstrac-
tos de datos ms utilizados en la gestin de proyectos software, dado que la estructura tipo pila es
muy frecuente en numerosos problemas de tratamiento de infolluacin, as como en problemas
matemticos, estadsticos o financieros. Por ejemplo, se puede utilizar una pila para determinar si
Pilas: el TAO pila 225
una secuencia de vuelos existe entre dos ciudades. La pila mantiene la secuencia de ciudades
visitadas y permite a un algoritmo de bsqueda volver hacia atrs. Para ello se sita la ciudad
origen en la parte inferior de la pila, y la ciudad destino en la parte superior, con lo que las suce-
sivas ciudades de trnsito se van colocando en la secuencia correcta.
EJERCICIOS
7.1. Se desea implementar el TAD pila de tal forma que los elementos de la pila sean almacena-
dos en una lista circular. El puntero externo a la lista apunta al elemento cabeza. Escribir
las operaciones de meter, cima, suprimir y esvacia.
7.2. Supongamos que estarnos trabajando en un lenguaje de programacin que no tiene el tipo
de dato puntero. Se plantea la resolucin de un problema utilizando dos pilas de nmeros
reales. Las dos pilas se quiere guardar en un nico array, de tal forma que crecen en sentido
contrario, una de ellas crece desde la posicin l del array y la otra desde la ltima posicin
del array. Escribir la estrategia a seguir para esta representacin, variables necesarias para
contener la posicin del elemento cabeza de ambas pilas.
7.3. Dada la representacin de dos pilas propuesta en 7.2, escribir el algoritmo de la operacin
Crea pi la (Pi lal, Pi la2) que inicializan ambas pilas corno pila vaca. De igual for-
ma escribir las funciones Esvac ial y Esvac ia2 que determinan si las respectivas pi lal
y pi la 2 estn vacas.
7.4. Completar las operaciones de las pilas propuestas en 7.2: Meterl, Meter2 y Supri-
mel, Suprime2. En las operaciones hay que tener en cuenta condiciones de error.
7.5. Utilizando una pila de caracteres, hacer un seguimiento para transformar la siguiente ex-
presin infija a su equivalente expresin en postfija.
E: (X-Y)/Z*W+(Y-Z)"V
7.6. Aplicando el algoritmo de evaluacin de una expresin, obtenga el resultado de las si-
guientes expresiones escritas en postfija .
XY+Z-YX+ZI\-
XYZ+*ZYX-+*
paraX=l, Y=3, Z=2
PROBLEMAS
7.1. Escribir un programa para determinar si frases (cadenas) son palndromos. Utilizar para
ello el TAD pila de caracteres realizado en una unidad. La entrada de datos son las frases y
la salida la propia frase junto a la etiqueta ES PALNDROMO, o bien NO ES PALN-
DRoMo .
. 7.2. Escribir un programa que convierta expresiones escritas en notacin infija (forma habitual)
a notacin postfija. Cada expresin se encuentra en una lnea, el programa ha de terminar
cuando la lnea conste de 3 asteriscos.
7.3. Escribir un programa que convierta expresiones escritas en notacin postfija a notacin
infija. Cada expresin se encuentra en una lnea, el programa ha de terminar cuando la lnea
conste de 3 asteriscos.
226 Estructura de datos
7.4. Escribir un programa que convierta expresiones escritas en notacin postfija a notacin
prefija. Cada expresin se encuentra en una lnea, el programa ha de terminar cuando la
lnea conste de 3 asteriscos.
7.5. Un mapa de carreteras podemos representarlo mediante la matriz simtrica MM de N x N
elementos enteros, donde los valores 1 a N representan los pueblos/ciudades que aparecen
en el mapa.
Los elementos de la matriz son tales que MM(i,j) = O si no hay conexin directa entre el
pueblo i y el pueblo j. MM(i,j) = d si hay conexin directa entre el pueblo i y el pueblo j, y
su distancia es d.
Con esta representacin del mapa queremos escribir un programa que simule el mapa des-
crito y que tenga como entrada dos pueblos (origen, destino) entre los que no hay conexin
directa; decida si hay un camino que pase por los pueblos del mapa y determine la distancia
de ese camino. Utilizar una pila para ir almacenando los pueblos que van formando el ca-
mino recorrido y poder volver atrs si se alcanza un pueblo desde el que no se puede prose-
guir la ruta, y probar con otra ruta.
7.6. Utilizando nicamente las operaciones bsicas sobre pilas: Met er, Cima, Supr ime y
Esvacia, construir las operaciones que realicen las siguientes acciones:
a) Asignar a X el segundo elemento desde la parte superior de la pila, dejando la pila sin
sus dos elementos de la parte superior.
b) Asignar a X el segundo elemento desde la parte superior de la pila, sin modificarla.
e) Dado un entero positivo n, asignar aX el n-simo elemento desde la parte superior de la
pila, dejando la pila sin sus n elementos de la parte superior.
d) Dado un entero positivo n, asignar aX el n-simo elemento desde la parte superior de la
pila, sin modificarla.
e) Asignar a X el elemento fondo de la pila, dejando la pila vaca.
j) Asignar a X el elemento fondo de la pila, sin modificarla.
7.7. Utilizando las operaciones del TAD pila, escribir una operacin de copia, tal que devuelva
la copia de una pila.
7.8. Escribir una funcin para determinar si una secuencia de caracteres de entrada es de la
fOllna:
X & Y
Donde X es una cadena de caracteres, e Y es la cadena inversa, siendo & el carcter sepa-
rador.
7.9. Escribir una funcin para determinar si una secuencia de caracteres de entrada es de la
forma:
A#B#C# ...
Donde cada una de las cadenas A, B, e ... son de la forma X & Y, que a su vez estarn
separadas por el carcter #.

1
1
1
,
,
,
,
I
I

;
,
,
,
CAPITULO



..,,0 as
CO as e rlO
e CO a
.' , '" ,': , ,', .. . .. , ' , .... . ' ' . . '
CONTENIDO
8.1. Especificacin formal del tipo abstracto de datos cola.
8.2. Implementacin del TAD cola con arrays lineales.
8.3. Implementacin del TAD cola con arrays circulares.
8.4. Implementacin del TAD cola con listas enlazadas.
8.5. Implementacin del TAD cola con listas circulares.
8.6. Bicolas.
8.7. Colas de prioridades.
8.8. Implementacin de colas de prioridades.
8.9. Un problema complejo resuelto con colas de prioridades.
8.10. Problema: Suma de enteros grandes.
RESUMEN.
EJERCICIOS.
PROBLEMAS.
El concepto de cola es uno de los que ms abundan en la vida cotidia-
na. Espectadores esperando en la taquilla de un cine o de un campo de
ftbol; clientes de un supermercado esperando la compra de un artcu-
lo comercial; etc. En una aplicacin informtica, una cola es una lista
en la que todas las inserciones a la lista se realizan por un extremo, y
todas las eliminaciones o supresiones de la lista se realizan por el otro
extremo.
Las colas se llaman tambin estructuras FIFO (jirst-in, first-ont;
primero en entrar, primero en salir). Las aplicaciones de las colas son
numerosas en el mundo de la computacin: colas de las tareas a reali-
zar por una impresora, acceso a almacenamiento de disco, o incluso,
en sistemas de tiempo compartido, el uso de la UCP (Unidad Central
de Proceso). En el captulo se examinan las operaciones bsicas de
manipulacin de los tipos de datos cola.
227

228 Estructura de datos


,
8.1. ESPECIFICACION FORMAL DEL TIPO ABSTRACTO
DE DATOS COLA
Una cola es una lista ordenada de elementos, en la cual las eliminaciones se realizan en
un solo extremo, llamado frente o principio de la cola, y los nuevos elementos son aa-
didos por el otro extremo, llamado fondo o jinal de la cola. La Figura 8.1 muestra una
estructura cola en una organizacin original (a) y sus modificaciones (b y e) despus de
eliminar y aadir un elemento de modo sucesivo.
En esta estructura de datos el primer elemento que entra es el primero en salir. Por
esta causa a las colas tambin se les llama listas FIFO (jirst input jirst output). Las
operaciones bsicas que definen la especificacin del TAD cola son:
Qcrear(Q)
Qvacia(Q)
Frente(Q)
Qborrar(Q)
Qanula(Q)
Quitar(X,Q)
Qponer(X,Q)
Crea la cola Q como cola vaca.
Nos devuelve cierto si la cola est vaca.
Devuelve el elemento frente de la cola.
Elimina el elemento frente de la cola.
Convierte la cola en vaca.
Elimina y devuelve el frente de la cola.
Aade un nuevo elemento a la cola.
a) Estructura original
AGHK
frente final
b) Estructura despus de eliminar un elemento
GHK
frente final
e) Estructura despus de aadir un elemento
GHKL
frente final
Figura 8.1. Una estructura de datos tipo cola.

Colas y colas de prioridades: el TAO cola 229
Al igual que las pilas, la implementacin de colas puede hacerse utilizando como
depsito de los elementos un array o bien una lista enlazada y dos punteros a los
extremos.
8.2. IMPLEMENTACiN DEL TAD COLA CON ARRAYS LINEALES
La forma ms sencilla de representacin de una cola es mediante arrays lineales. Se
utiliza como depsito de los elementos de la cola un array unidimensional cuyo tipo es
el mismo que el tipo de los elementos de la cola. Son necesarios dos ndices para refe-
renciar al elemento frente y al elemento final. El array y las dos variables ndice se agru-
pan en el tipo registro de nombre cola.
const
Max = 100;
type
Tipoelemen

I II definicin del tipo de elemento
posicion= O .. Max;
Cola= record
Datos: array[l .. Max] of Tipoelemen;
Frente,
Final: posicion
end;
var Q:Cola;
Un array es una estructura esttica y por tanto tiene dimensin finita; por el contra-
rio, una cola puede crecer y crecer sin lmite, y en consecuencia se puede presentar la
posibilidad de que se presente un desbordamiento. Por esa razn dentro de las operacio-
nes de este TAD se incorpora, normalmente, la operacin de verificacin de que la cola
est llena.
La operacin de aadir un nuevo elemento en la cola comienza a partir de la posicin
1 del array
1 234
AGHK
t t
frente final
Supongamos que la cola se encuentra en la situacin anterior: el frente est fijo y el
final de la cola es el que se mueve al aadir nuevos elementos. Si ahora se quita un
elemento (evidentemente por el frente) la cola queda as:
123 4
GHK
t t
frente final
Se ha dejado un hueco no uti-
lizable, por lo que se desapro-
vecha memoria.
230 Estructura de datos
Una alternativa a esta situacin es mantener fijo el frente de la cola al comienzo del
array; este hecho supone mover todos los elementos de la cola una posicin cada vez
que se quiera retirar un elemento de la cola.
Estos problemas quedan resueltos con los arrays circulares que se describen ms
adelante. Las operaciones ms importantes incluidas en la especificacin de una cola
con esta representacin son: Crear, Cola Vacia, ColaLlena, A adir y Quitar.
Crear (Qcrear(Q
La operacin Qcrear inicializa la cola como cola vaca.
procedure Qc r ear( var Q: Co l a) ;
begin
Q.Frente := 1;
Q.Fina l := O;
end;
Cola vaca (Qvacia(Q
La operacin Qva e i a devuelve verdadero si la cola no tiene elementos.
function Qva cia(Q : Co la) : boolean ;
begin
Qvacia : = Q.Fina1 < Q. Fren te
end;
Cola llena (Qllena(Q
La operacin Q 11 e na devuelve verdadero si en la cola no pueden aadirse ms elementos.
function Qllena( Q: Cola) : boo lean;
begin
Qll e na := Q.Fi nal = Max
end
Aadir (Qponer(X,Q
Aade el elemento X a la cola. Se modifica la cola por el extremo final.
procedure Qponer(X : Ti poe l e me n; var Q: Co l a) ;
begin
if not Ql l e na(Q) then
with Q do
begin
Final:= Final+1 ;
Dat os [Final]: = X
end
end;
Quitar (Quitar(X,Q
Elimina y devuelve el frente de la cola.
procedure Qu i tar( var x: Ti poe l emen ; var Q: Cola) ;
procedure Desplazar ;
var l: posi cion ;
Colas y colas de prioridades: el TAO cola 231
begin
for to Q. Fi nal - l do
Q . Da t o s [ 1 J : Q . Da t o s [ 1 + 1 J
end;
begin
X: = Q.Datos[Frent e l ;
Despl azar
end;
,
8.3. IMPLEMENTACION DEL TAD COLA CON ARRAYS
CIRCULARES
La implementacin de colas mediante un array lineal es poco eficiente. Cada operacin
de supresin de un elemento supone mover todos los elementos restantes de la cola.
Para evitar este gasto, imagnese un array como una estructura circular en la que al
ltimo elemento le sigue el primero. Esta representacin implica que aun estando ocupa- '
do el ltimo elemento del array, pueda aadirse uno nuevo detrs de l, ocupando la
primera posicin del array.
Para aadir un elemento a la cola, se mueve el ndice final una posicin en el sentido de
las manecillas del reloj, y se asigna el elemento. Para suprimir un elemento es suficiente
con mover el ndice frente una posicin en el sentido del avance de las manecillas del
reloj. De esta manera, la cola se mueve en un mismo sentido, tanto si se realizan inser-
ciones como supresiones de elementos.
Segn se puede observar en la representacin, la condicin de cola vaca [fren-
te = siguiente (final)] va a coincidir con una cola que ocupa el crculo completo, una
cola que llene todo el array.
Para resolver el problema, una primera tentativa sera considerar que el elemento
final referencie a una posicin adelantada a la que realmente ocupa el elemento, en el
sentido del avance del reloj.
n
1 2










4 ,
Final/"


--- - -,
::...
"
-
_o, 0_. _
I I

i
Cola
Figura 8.2. Arrays circulares.
I
232 Estructura de datos
Final--
p S



T
i
n
1
B
p
2....--Final
3
A
4
'Frente
Figura 8.3. Evolucin de arrays circulares.
Teniendo presente esta consideracin cuando la cola estuviera llena, el ndice si-
guiente a final ser igual al frente.
Consideremos ahora el caso en que queda un solo elemento en la cola. Si en estas
condiciones se suprime el elemento, la cola queda vaca, el puntero Frente avanza una
posicin en el sentido de las manecillas del reloj y va a referenciar a la misma posicin
que el siguiente al puntero Final. Es decir, est exactamente en la misma posicin rela-
tiva que ocupara si la cola estuviera llena.
Una solucin a este problema es sacrificar un elemento del array y dejar que Final
referencie a la posicin realmente ocupada por el ltimo elemento aadido. Si el array
tiene long posiciones, no se debe dejar que la cola crezca ms que long-lo
n
1
B p
2
u
W 3 Final
A
4
Frente
Figura 8.4. Insercin de nuevos
elementos en un array circular.
n
1
2
/Frente
W 3
Figura 8.5. Supresin de un
elemento en un array circular.

Colas y colas de prioridades: el TAO cola 233


Segn lo expuesto anteriormente, las declaraciones necesarias para especificar el tipo
cola son:
const
Long -
type

. .. ,
Tipoelemen -

r
posicion= O .. Long;
Cola= record
Elementos: array[l .. long] of Tipoelemen;
Frente,
Final: Posicion
end;
Las operaciones definidas en el TAD cola con esta representacin de array circular
son: Siguiente, Crear, Cola Vacia, CalaLlena, Frente, Borrar y Quitar.
Siguiente(J)
La funcin Si gu i en te ( J) obtiene la posicin siguiente a J en el sentido circular de
avance, segn las manecillas del reloj.
function Siguiente(J: integer): integer;
begin
Siguiente:= (J mod Long) +1
end;
Crear(Q)
La operacin de crear inicializa los ndices de la cola de tal manera que la condicin
de cola vaca aplicada sobre la cola creada sea cierta.
procedure Qcrear(var Q: Cola);
begin
Q.Frente:= 1;
Q.Final:= Long;
end;
Cola
,
VaCl.a
La operacin Qva c i a devuelve verdadero si la cola no tiene elementos.
function Qvacia(Q: Cola): boo1ean;
begin
Qvacia:= Siguiente(Q.Final)= Q.Frente
end;
Cola llena
La operacin Q 11 ena devuelve verdadero si en la cola no pueden aadirse ms ele-
mentos, es decir, si estn ocupadas Long-l posiciones del array.
234 Estructura de datos
function Qllena(Q : Co l a ) : bool ean ;
begin
Ql l e na := Sigu ien te (Sigu i e n te(Q .Fi n a l ) )= Q. Fr e nt e
end;
Frente (Frente(Q
function Frente (Q : Co l a ) : Ti poe l e men;
begin
if not Qvacia (Q) then
Fr ente := Q. El emen tos [Q. Frent e ]
end;
Borrar (Qborrar(Q
Esta operacin modifica la cola, elimina el elemento frente de la cola.
procedure Qborr ar( var Q: Co l a ) ;
begin
if not Qvacia (Q) then
Q. Frente:= Q. Fr e nt e+ l
end;
Quitar (Quitar(X, Q
Elimina y devuelve el frente de la cola. En realidad esta operacin es un compendio de
las operaciones Frente y Qborrar.
procedure Quitar( var x: Ti poelemen; var Q: Col a );
begin
X : = Frente(Q);
Qb o rrar(Q)
end;
n
~ F i n a l
e
2
3
-Frente
Q
4
o
p
5
6
Figura 8.6. Llenado del array circular.
,
,
,

I

1
i ,
,
j
,
)
I
i
I
j
I
1

1
l
I

,
,

j
i
1
!
1
1
i

,
,
,

;
,
,
,
,

;
!

I

,

I
,
Colas y colas de prioridades: el T AV cola 235
Qponer(X, Q)
Aade el elemento X a la cola. Se modifica la cola por el extremo final.
procedure Qponer(X : Ti poel eme n; var Q: Cola) ;
begin
if not Qllena (Q) then
with Q do
begin
Fina l:= S i guiente(Final);
Elementos [ Final] : = X
end
end;
,

8.4. IMPLEMENTACION DEL TAD COLA CON LISTAS


ENLAZADAS
Como ocurre con toda representacin esttica, una de las principales desventajas es que
hay que prever un mximo de elementos, de ese mximo no podemos pasamos. La rea-
lizacin de una cola mediante una lista enlazada permite ajustarse exactamente al nme-
ro de elementos de la cola.
Esta implementacin con listas enlazadas utiliza dos punteros para acceder a la lista.
El puntero Frente y el puntero Final.
Frente
Final
H K M
"'---1
T
n il
Figura 8.7. Cola implementada con lista enlazada.
El puntero Frente referencia al primer elemento que va a ser retirado. El puntero
Final referencia al ltimo nodo que fue aadido, en definitiva, al ltimo que ser retira-
do (1 i s t a F i f o). En esta representacin no tiene sentido la operacin que determina
si una cola est llena (Ql lena). Al ser una estructura dinmica crece y decrece segn
las necesidades. Las declaraciones para la representacin de cola mediante listas:
type
Tipoelemen - ... ;
Ptrn odoq= ANodoq ;
Nodoq= record
I nEo : Tipoe l eme n;
Sgte : Pt rnodoq
end;
Cola= record
Fr e n te ,
Final :Pt rnodoq
end;
236 Estructura de datos
Las operaciones definidas en la especificacin del tipo en esta estructura son: Crear,
Cola Vaca, Frente, Borrar, Quitar y Poner.
Crear (Qcrear(Q
La operacin Qcr ear inicializa la cola como Cola vaCa.
procedure Qcrear(var Q: Cola) ;
begin
Q. Frente := nil ;
Q.Fina l:= nil
end;
Cola
,
vac1a (Qvacia(Q) )
La operacin Qvacia devuelve verdadero si la cola no tiene elemento.
function Qva c i a(Q : Cola) : boolean;
begin
Qvacia := Q.Fr ente= n i l
end;
Frente (Frente (Q) )
Devuelve el elemento Frente de la cola.
function Fr e n te(Q : Co l a) : Tipoe l e me n;
begin
if not Qvacia(Q) then
Frente := Q. Frent e A. lnfo
end;
Borrar (Qborrar(Q
Esta operacin modifica la cola, elimina el elemento frente de la cola y es liberado.
procedure Qbo r rar( var Q: Cola) ;
var
A: Ptrnodoq ;
begin
if not Qvac i a(Q) then
with Q do
begin
A: = Fren te ;
Frente := FrenteA . Sgte ;
if Frente = nil Then
Final:= nil;
d i s pose(A)
end
end;
Quitar (Quitar(X,Q
Elimina y devuelve el frente de la cola.
procedure Quitar( var X: Tipoeleme n; var Q: Co l a);
begin
X : = Frent e (Q) ;
Qborrar(Q)
end;
,
,
,
,

Colas y colas de prioridades: el TAO cola 237


Poner (Qponer(X,Q
Aade el elemento X a la cola. Este elemento se aade como ltimo nodo, por lo que se
modifica la cola al cambiar Final.
function Crear (X:Tipoelemen): Ptrnodoq;
var T:Ptrnodoq;
begin
new(T); x; nil
Crear:= T
end;
procedure Qponer(X: Tipoelemen; var Q: Cola);
var
N: Ptrnodoq;
begin
N:= Crear(X); {Crea nodo con campo X, devuelve su direccin}
with Q do
begin
if Qvacia(Q) then
Frente:= N;
elee
N;
Final:= N
end
end;
8.5. I PLE NTACIN DEL TAD COLA CON LISTAS
CIRCULARES
Esta implementacin es una variante de la realizacin con listas enlazadas. Al realizar
una lista circular se estableci, por convenencia, que el puntero de acceso a la lista refe-
renciaba al ltimo nodo, y que el nodo siguiente se considera el primero. Segn este
convenio y teniendo en cuenta la definicin de cola, las inserciones de nuevos elementos
de la cola sern realizados por el nodo referenciado por Le, y la eliminacin por el nodo
siguiente. Las declaraciones de tipos para esta representacin:
type
Tipoelemen -
Cola=
Nodoq= record

. . . ,
rnfo: Tipoelemen;
Sgte: Cola
end;
Las operaciones son similares a las realizadas con listas enlazadas: Crear, Cola Va-
cia, Frente, Borrar, Quitar y Poner. El puntero necesario para realizar inserciones y
supresiones es el mismo: Q. Teniendo en cuenta que Q referencia al ltimo (Final)
y Q"'. Sgte al primero (Frente).
238 Estructura de datos
Le

Figura 8.8. Cola implementada con una lista circular con punteros.
Crear (Crear(Q
procedure Qcrear(var Q: Cola);
begin
Q:= nil;
end;
,
Cola vaC1a (Qvacia(Q
function Qvacia(Q: Cola): boolean;
begin
Qvacia:= Q= nil
end;
Frente(Q)
function Frente(Q: Cola): Tipoelemen;
begin
if not Qvacia(Q) then
Frente:= Q.SgteA.lnfo
end;
Qborrar(Q)
procedure Qborrar(var Q: Cola);
var
A: Cola;
begin
if not Qvacia(Q) then
begin
A:= QA.Sgte;
if QA.Sgte= Q then
Q:=nil;
else
QA.Sgte:=QA.SgteA.Sgte;
dispose(A)
end
end;

I
,
,
i
,
,


i
,
Colas y colas de prioridades: el TAO cola
Quitar(X, Q)
procedure Quita r (var x:Tipoelemen; var Q:Cola);
begin
X : = Frente (Q) ;
Qborrar(Q )
end;
Qponer(X, Q)
procedure Qponer(x: Tipoelemen; var Q: Co l a) ;
var
N: Col a;
begin
new(N) ;NA.Inf o : =X;NA.Sgte:=N;{Crea n o do con campo xl
if not Qvacia(Q) then
begin
NA. Sgte : = QA .Sgte ;
QA . Sgt e: = N
end
Q : = N;
end;
8.6. BleOlAS
239
Una variacin del tipo de datos cola es la estructura bicola. Una bicola es un conjunto
ordinal de elementos en el cual se pueden aadir o quitar elementos de cualquier extre-
mo de la misma. Es, en realidad, una cola bidireccional.
Los dos extremos de una bicola los llamaremos Izquierdo y Derecho, respec-
tivamente. Las operaciones bsicas que definen una bicola son:
CrearBq (Bq) :
Esvaci a (Bq) :
Inserlzq (x,
InserDch (x ,
Elimnlzq (x,
ElimnDch (x ,
Bq ) :
Bq) :
Bq) :
Bq) :
inicializa una bicola sin elementos.
devuelve verdadero si la bicola no tiene elementos.
aade un elemento por extremo izquierdo.
aade un elemento por extremo derecho.
devuelve el elemento Izquierdo y lo tetira de la bicola.
devuelve el elemento Derecho y lo retira de la bicola.
Para representar una bicola se puede elegir una representacin esttica, con arrays, o
bien una representacin dinmica, con punteros.
En la representacin dinmica, la mejor opcin es mantener la bicola con una lista
doblemente enlazada: los dos extremos de la lista se representan con las variables punte-
ro 1 zquierdo y Derecho, respectivamente.
En la representacin esttica se mantienen los elementos de la bicola con un array
circular y dos variables ndice del extremo izquierdo y derecho, respectivamente.
Al tipo de datos bicola se pueden imponer restricciones respecto al tipo de entrada o
al tipo de salida. Una bicola con restriccin de entrada es aquella que slo permite in-
serciones por uno de los dos extremos, pero pel mite la eliminacin por los dos extremos.
Una bicola con restriccin de salida es aquella que permite inserciones por los dos ex-
tremos, pero slo permite retirar elementos por un extremo.
240 Estructura de datos
Frente: 3
Final: 5
1 2
LUZ AGUA RIO
3 4 5
Al aadirse el elemento SOL por el frente
Frente: 2
SOL LUZ AGUA RIO
Final: 5
1 2 3 4 5
Puede eliminarse por el final
Frente: 2
Final: 4
1
SOL LUZ AGUA
2 3 4 5
6
6
6
Figura 8.9. Estructura tipo Bicola.
PROBLEMA 8.1
7 8
7 8
7 8
El estacionamiento de las avionetas de un aerdromo es en lnea, con una capacidad
hasta 12 avionetas. Las avionetas llegan por el extremo izquierdo y salen por el extremo
derecho. Cuando llega un piloto a recoger su avioneta, si sta no est justamente en el
extremo de salida (derecho), todas las avionetas a su derecha han de ser retiradas,
sacar la suya y las retiradas colocadas de nuevo en el mismo orden relativo en que
estaban. La salida de una avioneta supone que las dems se muevan hacia adelante, de
tal forma que los espacios libres del estacionamiento estn en la parte izquierda.
El programa para emular este estacionamiento tiene como entrada un carcter que
indica una accin sobre la avioneta, y la matrcula de la avioneta. La accin puede ser,
llegada (E) o salida (S) de avioneta. En la llegada puede ocurrir que el estacionamiento
est lleno, si es as la avioneta espera hasta que se quede una plaza libre, o hasta que se
d la orden de retirada (salida).
Anlisis
El estacionamiento va a estar representado por una bicola de salida restringida. Por
qu? La salida siempre se hace por el mismo extremo, sin embargo la entrada se puede
hacer por los dos extremos, y as contemplar la llegada de una avioneta nueva, y que
tenga que entrar una avioneta que ha sido movida para que salga una intermedia. La
lnea de espera para entrada de una avioneta (estacionamiento lleno) se representa por
una bicola a la que se aaden avionetas por un extremo, salen para entrar en el estacio-
Colas y colas de prioridades: el TAO cola 241
namiento por el otro extremo, aunque pueden retirarse en cualquier momento si as lo
decide el piloto; en este caso puede ocurrir que haya que retirar las avionetas que tiene
delante, o bien si es la ltima retirarla por ese extremo.
Las avionetas que se mueven para poder retirar del estacionamiento una intermedia
se disponen en una lista L i f o; as la ltima en entrar ser la primera en aadirse en el
extremo salida del estacionamiento y seguir en el mismo orden relativo.
La unidad 1 i f o (p i 1 a) se describe slo con in ter fa c e ya que su implentacin
se ha escrito anteriormente. En la unidad bicola se implementan las operaciones de una
bicola, la representacin con array circular, adems se incorpora la operacin que da las
plazas libres que hay en el estacionamiento. La restriccin de salida se refleja en que no
es vlida la operacin Rem_en t (retirada por el extremo de salida).
unit Lifo;
interface
type
Avioneta=string[15]; {En realidad sera un registro con ms campos
identificativos}
PtrPila =AItemp;
Itemp = record
Info: Avioneta;
Sgte: PtrPila
end;
procedure Pilavacia(var Pila: PtrPila);
function Pvacia (Pila: PtrPila): boolean;
procedure Pmeter(X: Avioneta; var Pila: PtrPila);
procedure Pcima(var X: Avioneta; Pila: PtrPila);
procedure Pborrar(var Pila: PtrPila);
procedure Psacar(var X: Avioneta; var Pila: PtrPila);
{Fin de la seccin de interfaz}
La unidad Bi colas utiliza la lista Li f o:
unit Bicolas;
interface
uses Lifo;
const
Long = 13;
type
Avioneta = string [15] ;
posicion= o .. Long;
Bicola= record
Elementos: array[l .. long] of Tipoelemen;
Salida,
Entrada: posicion
end;
procedure CrearBq (var Bq: BiCola);
function Esvacia(Bq: BiCola): boolean;
function EsLLena(Bq: BiCola): boolean;
procedure InsEntrada(A:Avioneta;var Bq:Bicola);
procedure InsSalida(A:Avioneta;var Bq:Bicola);
procedure EliEntrada(var A:Avioneta;var Bq:Bicola);
procedure EliSalida(var A:Avioneta;var Bq:Bicola);
I
!

i
,
i
I
!
.

,
Colas y colas de prioridades: el TAO cola 243
procedure Ins Entrada(A:Avioneta; var Bq:Bicola);
begin
if not EsLLena(Bq) then
with Bq do
begin
Entrada:= Siguiente(Entrada) ;
Elementos [Entrada) := A
end
end;
procedure InsSalida(A:Avioneta;var Bq:Bicola);
begin
if not EsLLena(Bq) then
with Bq do
begin
Sa lida:= Anterior(Salida);
Elementos [Salida) := A
end
end;
procedure EliEntrada(var A:Avioneta;var Bq:Bicola);
begin
if not Esvacia(Bq) then
begin
A:=BQ.Elementos[Bq.Entrada);
Bq.Entrada:= Anterior[Bq.Entrada)
end
end;
procedure EliSalida(var A:Avioneta;var Bq:Bicola);
begin
if not Esvacia(Bq) then
begin
A:=BQ.Elementos[Bq.Salida) ;
Bq.Entrada:= Siguiente[Bq.Salida)
end
end;
procedure Retirar(A:Avioneta;var Bq:Bicol a;var Ok:boolean);
{Esta operac in retira una avioneta. O bien por un extremo, o bien
intermedia}
var
D: integer;
Pl:Ptrpila;
begin
D:=Posicion(A,Bq) ;
Ok:=true;
if D<> O then
if D=Bq.Salida then
EliSalida (A, Bq)
e1ee begin
Pilavacia(Pl) ;
(Se sacan elementos intermedios, desde Salida hasta D)
repeat
Elisalida(A,Bq) ;
Pmeter(A,Pl) ;

,
244 Estructura de datos
until Bq.Sa l ida=D;
Elisalida ( A,Bq); (es retirado el elemento pedido)
(Son introducidos los el e mentos sacados)
repeat
Psacar(A,Pl ) ;
InsSalida(A,Bq )
until Pvac ia(Pl)
end
else
Ok:=fa l se ; {No est la avi o n et a}
end;
{fin de la unidad bi co l a }
end.
Por ltimo, el programa que emula el estacionamiento es Avionetas.
program Avionetas(input,output);
uses c rt,Lif o ,Bico la ;
var
u: Avi oneta;
Ch : char ;
Bq : Bicola;
Bqw: Bi co la; {Bi co la de espera de e n trada en estacionamiento}
Sw: boolean;
begin
clrscr ;
CrearBq (Bq) ; CrearBq ( Bqw);
write ( 'La entrada intera ctiva, son lneas con un char y ');
writeln( 'nmero matr icula:E( l legada) , S(Sal ida) ' ) ;
repeat
repeat
read(Ch) ; Ch :=upcase(Ch)
until Ch in[ 'E', ' S ' J ;
readl n (U) ;
if Ch = 'E' then
if not Esl lena (Bq) then
InsEnt rada (U,Bq)
el se
En s Entrada(U,Bqw); {se aade a b i co la d e espera}
el se {re t irada de avione tas}
Reti rar (U ,Bq,Sw)
Until n ot Sw
end.
8.7. COLAS DE PRIORIDADES
El trmino cola sugiere la forma en que esperan ciertas personas u objetos la utilizacin
de un determinado servicio. Por otro lado, el trmino prioridad sugiere que el servicio
no se proporciona nicamente aplicando el concepto de cola (el primero en llegar es el
primero en ser atendido) sino que cada persona tiene asociada una prioridad basada en
un criterio objetivo.
Un ejemplo tpico de organizacin formando colas de prioridades, es el sistema
de tiempo compartido necesario para mantener un conjunto de procesos que esperan

Colas y colas de prioridades: el T AD cola 245
servicio para trabajar. Los diseadores de estos sistemas asignan cierta prioridad a cada
proceso.
El orden en que los elementos son procesados y por tanto eliminados sigue estas
reglas:
l. Se elige la lista de elementos que tienen la mayor prioridad.
2. En la lista de mayor prioridad, los elementos se procesan segn el orden de
llegada; en definitiva, segn la organizacin de una cola: primero en llegar,
primero en ser procesado.
Las colas de prioridades pueden implementarse de dos formas: mediante una nica
lista o bien mediante una lista de colas.
8.8. IMPLE ENTACIN DE COLAS DE PRIORIDADES
Para realizar la representacin, se define en primer lugar el tipo de dato que representa
un proceso.
type
Ti po_i d entif = ... {Tipo de l i d e ntif icador d el p r oceso}
Ti po_ proceso= record
Idt: Tipo_i d e nt i f;
Priori dad : int eger
end;
8.8.1. Implementacin mediante una nica lista
Cada proceso forma un nodo de la lista enlazada. La lista se mantiene ordenada por el
campo prioridad.
La operacin de aadir un nuevo nodo hay que hacerla siguiendo este criterio:
La posicin de insercin es tal que la nueva lista ha de permanecer ordenada. A igual-
dad de prioridad se aade como ltimo en el grupo de nodos de igual prioridad. De
esta manera la lista queda organizada de tal forma que un nodo X precede a un
nodo y si:
l. Prioridad(X) > Prioridad(Y).
2. Ambos tienen la misma prioridad, pero X se aadi antes que Y.
Cp
41 P1 I ~ 1 P21 ~ I P31 r.lp21 I ~ l p 2 2 r. ... -.1 Pn I I
Figura 8.10. Cola de prioridad con una lista enlazada .

246 Estructura de datos


Los nmeros de prioridad tienen el significado habitual: a menor nmero mayor prio-
ridad. Esta realizacin presenta como principal ventaja que es inmediato determinar el
siguiente nodo a procesar: siempre ser el primero de la lista. Sin embargo, aadir un
nuevo elemento supone encontrar la posicin de insercin dentro de la lista, segn el
criterio expuesto anteriormente.
8.8.2. Implementacin mediante una lista de n colas
Se utiliza una cola separada para cada nivel de prioridad. Cada cola puede representarse
con un array circular, mediante una lista enlazada, o bien mediante una lista circular, en
cualquier caso con su Frente y Final. Para agrupar todas las colas, se utiliza un array de
registros. Cada registro representa un nivel de prioridad, y tiene el frente y el final de la
cola correspondiente. La razn para utilizar un array radica en que los niveles de priori-
dad son establecidos de antemano.
La definicin de los tipos de datos para esta realizacin:
const
Max_prior= ... ; {Mximo nmero de prioridades previsto}
type
Tipo_identif= ... {Tipo del identificador del proce so}
Tipo_proceso= record
Idt: Tipo_identif;
Prioridad: integer;
end;
Ptrnodoq=ANodoq;
Nodoq= record
info: Tipo_proceso ;
sgte : Ptrnodoq
end;
Cp
1
2
n
P1
P2





Pn
Q1
Q2
Qn
Ip11 P12 P1KI
Ip21 P2K I
IPn1 PnK I
Figura 8.11. Cola de prioridad con n colas .


Colas y colas de prioridades: el TAO cola 247
Cola = record
Numpr i dad : integer ;
fr e n t e ,
f ina l: Pt rno doq
end;
Tabl a_cp = array[ l .. Max_pri orl of Co la;
El tipo Ta bl a_c p es el que define la lista de colas y cada cola representa una prio-
ridad. Las acciones ms importantes al manejar una cola de prioridades son las de aadir
un nuevo elemento, con una determinada prioridad al sistema, y la accin de retirar un
elemento para su procesamiento. Estas acciones se expresan en forma algortmica en la
realizacin de n colas, como se muestra a continuacin.
Algoritmo para aadir nuevo elemento
Aade un elemento P que tiene un nmero de prioridad m.
l. Buscar el ndice en la tabla correspondiente a la prioridad m.
2. Si existe y es K, poner el elemento P como final de la cola de ndice K.
3. Si no existe, crear nueva cola y poner en ella el elemento P.
4. Salir.
Algoritmo para retirar un elemento
Retira el elemento de frente de la cola que tiene mxima prioridad.
1. Buscar el ndice de la cola de mayor prioridad no vaca. Cola k.
2. Retirar y procesar el elemento frente de la cola k.
3. Salir.
8.9. IMPLEMENTACiN DE UN PROBLEMA CON COLAS
DE PRIORIDADES
El objetivo del supuesto planteado es emular un sistema simple de procesamiento en
tiempo compartido. Para ello, van a generarse tareas aleatoriamente con un nmero de
prioridad de 1 a 8.
La simulacin se va a realizar hasta que hayan sido finalizadas un nmero detenni-
nado de tareas (Max_pr oc). Adems, cada vez que el sistema retira una tarea, sta se
procesa en su totalidad.
La cadencia es: por cada tarea procesada llegan al sistema dos nuevas tareas, as
hasta completar el proceso del mximo de tareas previstas.
La realizacin es con un sistema de n colas. En la unidad col a s estn encapsuladas
las operaciones de manejo de colas, los tipos de datos y los procedimientos para aadir
y eliminar una tarea cuyos algoritmos se han expuesto anteriormente.
begin
new(A) ;
AA.lnfo:=X;
AA.Sgte:=nil;
if Qvacia(Q) then
Q.Frente:= A
elBe
Q.FinalA.Sgte:=A;
Q.Final:= A
end;
procedure Qborrar(var Q: Colap);
var
A:Ptrnodoq;
begin
if (not Qvacia(Q) )then
begin
A:=Q.Frente;
Q.Frente:=Q.FrenteA.Sgte;
dispose(A)
end
end;
Colas y colas de prioridades: el TAO cola 249
procedure Quitar (var X: Tipo_proc; var Q:Colap);
begin
if (not Qvacia(Q)) then
X:= Q.FrenteA.lnfo;
Qborrar(Q)
end;
procedure CrearQP (var Tcp:Tablacolas;Max_prior:integer);
var
i:integer;
begin
for i:=l to Max_prior do
begin
Qcrear(Tcp[i]) ;
Tcp [i] . Prd: = o
end
end;
function Nurncola(P: integer; var Tcp:tablacolas): integer;
{Busca cola de prioridad P; Si no Existe devuelve la siguiente libre.
Todas ocupadas, devuelve O}
var
J: integer;
Sw: boolean;
begin
Sw:= false;
J:= O;
while (J < Max_prior) and not Sw do
begin
J:= J+l;
Sw:= (Tcp[J] .Prd= P) or (Tcp[J] .Prd= O)
end;
if Sw then
250 Estructura de datos
Numcola := J
elee
Numco l a := o
end;
function Qmaxp ri (var Tcp : tabl ac olas): int eger ;
{Bu sca cola de mx ima prioridad . si toda s las t a r eas e stn procesadas
devuelve Ol
var
J ,K: i n teger;
M: integer ;
begin
J: = O;
K: = O;
M: = Ma x_pr ior + 1 ; { valor de arranque }
while J< Max_prior do
if not Qvac ia(Tcp [ J ] ) and (Tcp [ J] . Prd< M) then
begin
K:= J;
M:= Tcp[J]. Pr d
end;
Qma x pr i:= K
end;
procedure pr esentar_ proc ( T : Co l aQp) ;
{Es t e p r oced imi ent o mue s t ra en pan talla la tarea que va a ser procesada }
begin
if LL = O then
clrscr ;
LL : = LL+1
write (T.Frent eA . lnfo .Tarea ) ;
Write ln( 'Priori dad :', T.FrenteA.Info.Prior) ;
if (LL mod 24) = O then
begin
de lay(1000) ;
c l rsc r
end
end;
procedure g e nerar_ proc( var Tcp : Tablacolas ; j : i nteger);
var
N : integer;
X: Tipo_proc;
function Tarea(K: integer) : St ring[20];
conet
Nt = 9 ;
Tareas = array [ l .. Max_ prior ] of string [ 20]
( 'RSET ' , ' COPIAR ', 'ENLAZAR ',
begin
'LEERDISCO ', ' COMP I LAR ',' HWAX ' ,
, EJECUTAT ' , ' ESTAT ' , ' TMTAX ' ) ;
if K i n [1 .. Max_ prior ] then
Tarea := Tareas [ K]
end;
-
-
begin
N:= random( Nt) + 1 ; {Tarea al azar}
X.Tarea : = Ta rea(N);
Colas y colas de prioridades: el TAO cola 251
N:= random(Max_ prio) + 1 ; {Prioridad al azar}
X. Prior:= N;
{Busca de Nmero de cola de prioridad}
N:= Nu mco la(X. Pr ior);
if N= O then
begin
writeln( ' Overf l ow en tabla de colas ' ) ;
halt( l )
end;
Tcp[N] . Prd : = X. Prior ;
Qponer(X, Tcp[N])
writ eln( ' SE GENERA TAREA N
Q
: ' , J)
end;
procedure procesar_ proc (var Tcp:Tablacol as ; var En co : boolean );
var
1 : i nteger;
begin
1 : = Qmaxpri(Tcp) ; {Col a de mayor pr i oridad}
Enc o : = 1<>0 ;
if 1 <> O then
begin
p resentar_proc( Tcp [ l ] ) ;
borrar (Tcp [ 1 ] )
end
end;
begin
LL : = O; {Para presentar tar eas procesadas }
end.
Codificacin del programa de gestin de colas de prioridades
program Co l asdeprior i dades ;
uses
u nit col a , c rt;
var
Tabl aq : Tabl aco l as;
1, J : int eger;
Hm: boolea n ;
C : char ;
begin
ran domi ze ;
CrearQp (Tablaq , max_ prior ) ;
{El b ucl e se real iza max_proc * 3 di v 2 iteraci one s para que
se generen Ma x_proc tareas . Por cada tarea p r ocesada , se
generan dos n u evas}
J : =O ;
for i:= 1 to (Ma x_proc*3 di v 2) do
if i mod 3 = O then
procesar_ proc (Tablaq , Hm)
252 Estructura de datos
else begin
J:= J + 1;
generar_pro c (Tablaq,j);
end;
repeat
pro ces ar_proc (Tablaq, Hm);
until not Hm
end.
PROBLEMA 8.2
En un archivo de texto F estn almacenados nmeros enteros arbitrariamente grandes.
La disposicin es tal, que hay un nmero entero por cada lnea de F. Escribir un progra-
ma que muestre por pantalla la suma de todos los nmeros enteros. Nota: Al resolver el
problema habr que tener en cuenta que al ser enteros grandes no pueden almacenarse
en variables numricas.
Anlisis
Partimos de que los nmeros estn dispuestos de tal forma que hay uno por lnea. El
objetivo es obtener la suma de todos estos nmeros y mostrarlo por pantalla.
Para leer los nmeros, los hacemos dgito a dgito (como caracteres).
Esta lectura capta los dgitos de mayor peso a menor peso; como la suma se realiza
en orden inverso, guardamos los dgitos en una pila de caracteres. As, el ltimo dgito
que entra (la unidad) es el primero en salir.
A partir de este hecho, podemos seguir dos estrategias:
Tener un array de enteros, de un mximo nmero de elemento establecido
(n = 250, por ejemplo). La suma se hace dgito a dgito, y guardando el resulta-
do en la misma posicin del array. Esto es, sacando de la pila y sumado el dgito
con el entero almacenado en la posicin n del array; en la siguiente iteracin se
saca de la pila y se suma con la posicin n - 1 del array, y as sucesivamente hasta
que la pila est vaca. En cada iteracin hay que guardar un posible acarreo.
La alternativa descrita tiene el inconveniente de que hay que establecer un
mximo de elementos del array, pudiendo ocurrir que nos quedemos cortos.
Otra estrategia consiste en sustituir el array de enteros por una lista enlazada.
Ahora se saca un dgito de la pila y se suma con el primer elemento metido en la
lista y con el acarreo. El dgito resultante se almacena en una nueva lista, a partir
del ltimo dgito insertado. En definitiva, es el tpico tratamiento de una lista fifo.
Con esta fOlma de proceder, cada vez que se accede a la lista para sumar dgito
hay que liberar el correspondiente nodo.
Esta alternativa nos peIlnite que no haya ningn tipo de restriccin en cuanto al n-
mero de dgitos. Como contrapartida, el proceso es ms lento, hay que realizar muchas
operaciones de creacin y liberacin de nodos.
Colas y colas de prioridades: el TAO cola 253
El programa que presentamos sigue la segunda alternativa. Para ello utilizamos dos
unidades, la unidad de manejo de pilas y la unidad de manejo de listas fifo. Presentamos
nicamente la seccin de interface de pila, la codificacin puede verse en las diversas
realizaciones de pilas escritas en el captulo anterior.
Codificacin de la unidad Pila
unit Pil a ;
interface
type
Tipoelem = c har ;
Ptr Pi l a =Altemp;
Itemp = record
I n f o : Ti poelem;
Sgte : Pt rPil a
end
procedure Pilavacia( var Pil a : PtrPila);
function Pvaci a(Pil a: PtrPi la) : boo lean ;
procedure Pme ter(X : Tipoelem; var Pi la : Pt r Pila) ;
procedure Pc ima( var X: Ti poe l e m; Pi l a : Ptr Pila) ;
procedure Pborrar( var Pi l a : PtrPil a) ;
procedure Ps a car( var X: Ti poelem; var Pila : PtrPila) ;
{Fin de la secci n de i nter faz}
Codificacin de la unidad Colas
unit Lf ifo ;
interface
type
Tipoi nf o - integer ;
Ptrnodoq =ANodoc;
Nodoc = record
In f o : Ti p o inf o ;
Sgte : Pt rnodoq
end;
Col a = record
Fr ent e ,
Fi na l: Pt r nodoq
end;
procedure Qc rear(var C: Cola);
function Qvacia (C : Co l a ): b oolean;
procedure Qpone r(X : Ti p oinf o ; var C:Col a) ;
procedure Qbo r rar( var C: Cola) ;
function Fren te(C : Co l a) : Tipoi n fo ;
procedure Qu itar (var X: Tipoi n fo ; var C: Co l a) ;
implementation
procedure Qcrear ;
begin
C. Frente := ni l ;
C.F inal : = nil
end;
)

254 Estructura de datos
function Qvacia;
begin

Qvacia := (C .Frente - nil)
end;
procedure Qponer;
var
A: pt rnod.,q;
begin
new (A) ;
AA.lnfo .- X . - ,
AA.Sgte := nil;
if Qvacia(C) then
C.Frente := A
else
C. Final A.Sg te := A;
C .Final:= A
end;
procedure Qborrar;
var
A:Ptrnodoq;
begin
if (not Qvacia(C) )then
begin
end
end
A := C.Frente;
C. Frente : = C.FrenteA.Sgte;
dispose(A)
function Frente;
begin
end
if (not Qvacia(C)) then
Frente := C.FrenteA.lnfo
procedure Quitar;
begin
X : = Frent e (C) ;
Qborra r(C)
end;
begin
end.
Codificacin completa del programa de gestin
program NurnerosGrandes(output, Dat os) ;
uses
Crt, Pila , Lfif o ;
var
Datos: text;
pla : Ptrpil a ;
Lfo : Cola;

256

Estructura de datos
if not Qvacia(Lfo) then
Qu i tar(52, Lfo);
52 : = 51 +52 +R;
R : = 52 div 10;
52 := 52 mod 10 ;
Qponer (5 2, Nq )
end;
while not Qvac i a( Lfo) do
begin
Quit a r(52 , Lfo) ;
52 := 52+R ;
R := 52 d i v 10 ;
52 := S2 mod 1 0 ;
Qponer(S2 , Nq)
end;
if R <> O
Lf o : = Nq
then Qponer (R , Nq ) ;
end;
procedure Escribir(Q: Cola) ;
var
N: integer;
begin
if not Qvacia (Q) then
end;
begin
Qu i t ar (N, Q) ;
Esc ri b ir (Q) ;
write(N)
end
begin
Abrir(Datos) ;
Qcrear( Lf o);
while not eo f (Dat os) do
begin
Leern umero(Datos , Pl a);
Suma r(Pl a, Lfo)
end;
if not Qvacia(Lf o) then
begin
-----------------------------..

wri teln( ' Res u l t ado d e l a suma d e nme r os grandes ' ) ;
Esc ri b i r(Lf o)
end
end.
RESUMEN
El proceso de insercin de datos se denomina acolar (enquering) y el proceso de eliminacin se
llama desacolar (dequering).
Una cola es una estructura de datos del tipo FIFO (jirst-in, first-out , primero en entrar, prime-
ro en salir); tiene dos extremos: una cola, donde se insertan los nuevos elementos, y una cabecera
o frontal , de la que se borran o eliminan los elementos.
Colas y colas de prioridades: el TAO cola 257
El tipo abstracto de datos cola se suele implementar mediante listas enlazadas por las mismas
razones que en el caso de las pilas: facilidad para gestionar el tamao variable o dinmico frente
al caso del tamao fijo.
Numerosos modelos de sistemas del mundo real, tanto fsicos como lgicos, son del tipo cola;
tal es el caso de la cola de trabajos de impresin en un servidor de impresoras, la cola de priorida-
des en viajes, programas de simulacin o sistemas operativos. Una cola es el sistema tpico que se
suele utilizar como buffer de datos, cuando se envan datos desde un componente rpido de una
computadora (memoria) a un componente lento (por ejemplo, una impresora).
Cuando se implementa una pila, slo se necesita mantener el control de una entrada de la
lista, mientras que en el caso de una cola, se requiere el control de los dos extremos de la lista.
Una cola de prioridad se puede implementar como un array de colas ordinarias o una lista
enlazada de colas ordinarias.
EJERCICIOS
8.1. Se ha estudiado en el captulo la realizacin de una cola mediante un array circular; una
variante a esta representacin es aquella en la que se tiene una variable que tiene la posi-
cin del elemento Frente y otra variable con la longitud de la cola (nmero de elementos),
LongCo 1 a, y el array considerado circular. Dibujar una cola vaca; aadir a la cola
6 elemento; extraer de la cola tres elementos; aadir elementos hasta que haya over f low.
En todas las representaciones escribir los valores de Frente y LongCola.
8.2. Con la realizacin de 8.1 escribir las operaciones de Cola: Qcrear, Qvacia, Qponer,
Frente y Qborrar.
8.3. Con la realizacin de una cola descrita en 8.1,2 consideremos una cola de caracteres. El
array consta de 7 posiciones. Los campos Frente, LongCola actuales y el contenido de
la cola:
Frente = 2 LongCola = 3 Cola: J, K, M
Escribir los campos Frente, LongCola y la Cola segn se vayan realizando las si-
guientes operaciones:
a) Se aaden los elementos F, J, G a la cola.
b) Se eliminan dos elementos de la cola.
e) Se aade el elemento A a la cola.
d) Se eliminan dos elementos de la cola.
e) Se aaden los elementos B, C, W a la cola.
f) Se aade el elemento R a la cola.
8.4. La realizacin de una cola mediante un array circular sacrifica un elemento del array; esto
se puede evitar aadiendo un nuevo campo a la representacin: Vac io de tipo lgico.
Escribir una unidad en la que se defina el tipo de datos y se implementen las operaciones de
manejo de colas.
8.5. Considere la siguiente cola de nombres, representada por un array circular con 6 posicio-
nes, los campos Frente, Final y Vacio:
Frente= 2, Final= 4, Vacio= Falso Cola: ,Mar,Sella,Licor,
Escribir el contenido de la cola y sus campos segn se realizan estas operaciones:
258 Estructura de datos
a) Aadir Folk y Reus a la cola,
b) Extraer de la cola.
e) Aadir Kilo.
d) Aadir Horche a la cola.
e) Extraer todos los elementos de la cola.
8.6. Una bicola con restriccin de entrada slo permite insercciones por uno de sus extremos,
permitiendo extraer elementos por cualquier extremo. Definir e implementar las operacio-
nes para este tipo de datos.
8.7. Una bicola con restriccin de salida slo permite extraer elementos por uno de sus extre-
mos, permitiendo insertar elementos por cualquier extremo. Definir e implementar las ope-
raciones para este tipo de datos.
8.8. Consideremos una bicola de caracteres representada en un array circular. El array consta de
9 posiciones. Los extremos actuales y el contenido de la bicola:
Izquierdo = 5 Derecho = 7 Bieola: A, e, E
Escribir los extremos y la bicola segn se vayan realizando las siguientes operaciones:
a) Se aaden los elementos F, J a la derecha de la bicola.
b) Se aaden los elementos R, W, V a la izquierda de la bicola.
e) Se aade el elemento M a la derecha de la bicola.
d) Se eliminan dos letras a la izquierda.
e) Se aaden los elementos K, L a la derecha de la bicola.
f) Se aade el elemento S a la izquierda de la bicola.
PROBLEMAS
8.1. Con un archivo de texto se quieren realizar estas acciones: formar una lista enlazada, de tal
forma que en cada nodo est la direccin de una cola que contiene todas las palabras del
archivo que empiezan por una misma letra. Una vez formada esta estructura, se desea vi-
sualizar las palabras del archivo, empezando por la cola que contiene aquellas palabras que
empiezan por la letra a, luego las de la letra b, y as sucesivamente.
8.2. Una empresa de reparto de propaganda contrata a sus trabajadores por das. Cada repartidor
puede trabajar varios das continuados o alternos. Los datos de los repartidores se almace-
nan en una lista simplemente enlazada. El programa a desarrollar contempla los siguientes
puntos:
Crear una estructura de cola para recoger en ella el nmero de la seguridad social de
cada repartidor y la entidad anunciada en la propaganda para un nico da de trabajo.
Actualizar la lista citada anteriormente (que ya existe con contenido) a partir de los
datos de la cola.
La informacin de la lista es la siguiente: nmero de seguridad social, nombre y total de
das trabajados. Adems, est ordenada por el nmero de la seguridad social. Si el trabaja-
dor no est incluido en la lista debe aadirse a la misma de tal manera que siga ordenada.
8.3. En un archivo de texto se quiere determinar todas las frases que son palndromo. Para ello
se sigue la siguiente estrategia: aadir cada carcter de la frase a una pila y a la vez a una
cola. La extraccin de caracteres simultnea de ambas y su comparacin determina si la
1 ,
,
Colas y colas de prioridades: el TAD cola 259
frase es o no palndromo. Escribir un programa para determinar todas las frases palndromo
del archivo de texto. Considerar que cada lnea de texto es una frase.
8.4. En un archivo de texto se encuentran los n;sultados de una competicin de tiro al plato, de
tal forma que en cada lnea se encuentra Apellido, Nombre, nmero de dorsal y nmero de
platos rotos. Se desea escribir un programa que lea el archivo de la competicin y determi-
ne los tres primeros. La salida ha de ser los tres ganadores y a continuacin los concursan-
tes en el orden en que aparecen en el archivo (utilizar la estructura cola).
8.5. El despegue de aeronaves en un aeropuerto se realiza siguiendo el orden establecido por
una cola de prioridades. Hay 5 prioridades establecidas segn el destino de la aeronave.
Destinos de menos de 500 km tienen la mxima prioridad, prioridad 1, entre 500 y 800 km
prioridad 2, entre 800 y 1.000 km prioridad 3, entre 1.000 y 1.350 km prioridad 4 y para
mayores distancias prioridad 5. Cuando una aeronave recibe cierta seal se coloca en la
cola que le corresponde y empieza a contar el tiempo de espera. Los despegues se realizan
cada 6 minutos segn el orden establecido en las distintas colas de prioridad. El piloto de
una aeronave puede pasar el aviso a control de que tiene un problema, y no puede despegar
por lo que pasa al final de la cola y se da la orden de despegue a la siguiente aeronave.
Puede darse la circunstancia de que una aeronave lleve ms de 20 minutos esperando, en
ese caso pasar a formar parte de la siguiente cola de prioridad y su tiempo de espera se
inicializa a cero.
Escribir un programa que simule este sistema de colas mediante una lista nica, cada vez
que despegue un avin saldr un mensaje con las caractersticas del vuelo y el tiempo total
de espera.
8.6. Resolver el problema 8.4 realizando el sistema de colas mediante un array de 5 colas.
PARTE
,
CAPITULO

ecurslvl a

a orltmos recursIvos
CONTENIDO
9.1. Recursividad.
9.2. Cundo no utilizar recursividad.
9.3. Algoritmos divide y vence.
9.4. Implementacin de procedimientos recursivos mediante pilas.
9.5. Algoritmos de vuelta atrs.
9.6. Problema de la seleccin ptima.
9.7. Problema de los matrimonios estables.
RESUMEN.
EJERCICIOS.
PROBLEMAS.
Un procedimiento o funcin recursiva es aquella que se llama a s mis-
ma. Esta caracterstica permite a un procedimiento recursivo repetirse
con valores diferentes de parmetros. La recursin es una alternativa a
la iteracin muy elegante en la resolucin de problemas, especialmen-
te si stos tienen naturaleza recursiva.
Normalmente, una solucin recursiva es menos eficiente en trmi-
nos de tiempo de computadora que una solucin iterativa debido al
tiempo adicional de llamada a procedimientos.
En muchos casos, la recursin permite especificar una solucin ms
simple y natural para resolver un problema que en otro caso sera difi-
cil. Por esta rzn la recursin (recursividad) es una herramienta muy
potente para la resolucin de problemas y la programacin.
9.1. RECURSIVIDAD
Un objeto recursivo es aquel que forma parte de s mismo. Esta idea puede servir de
ayuda para la definicin de conceptos matemticos. AS, la definicin del conjunto
263
264 Estructura de datos
de los nmeros naturales es aquel conjunto en el que se cumplen las siguientes ca-
, .
ractenstlcas:
O es un nmero natural.
El siguiente nmero de un nmero natural es otro nmero natural.
Mediante una definicin finita hemos representado un conjunto infinito.
El concepto de la recursividad es muy importante en programacin. La recursividad
es una herramienta muy eficaz para resolver diversos tipos de problemas; existen mu-
chos algoritmos que se describirn mejor en trminos recursivos.
Suponga que dispone de una rutina Q que contiene una sentencia de llamada a s
misma, o bien una sentencia de llamada a una segunda rutina que a su vez tiene una
sentencia de llamada a la rutina original Q. Entonces se dice que Q es una rutina re-

cursiva.
Un procedimiento o funcin recursivos han de cumplir dos propiedades generales
para no dar lugar a un bucle infinito con las sucesivas llamadas:
Cumplir una cierta condicin o criterio base del que dependa la llamada re-

cursiva.
Cada vez que el procedimiento o funcin se llamen a s mismos, directa o indirec-
tamente, debe estar ms cerca del incumplimiento de la condicin de que depen-
de la llamada.
EJEMPLO 9.1. Secuencia de nmeros de Fibonacci
Esta serie numrica es un ejemplo tpico de cumplimiento de las dos propiedades ge-
nerales de todo procedimiento recursivo. La serie de Fibonacci es:
O, 1, 1,2, 3, 5, 8, 13, 21, 34 ...
El trmino inicial es ao = 0, y los siguientes son: al = 1, a
2
= 2, a3 = 3, a
4
= 5, a
5
= 8 ...
observndose que cada trmino es la suma de los dos tlIninos precedentes excepto ao yal'
La serie puede ser definida recursivamente del modo siguiente:
Fibonacci(n) = n si n = O o n = 1
Fibonacci(n) = Fibonacci(n-2) + Fibonacci(n-l) para n >l
Esta definicin recursiva hace referencia a ella misma dos veces. Y la condicin para
que dejen de hacerse llamadas recursivas es que n sea O o 1. La llamada recursiva se
hace en trminos menores de n, n- 2, n-l, por lo que se va a los valores de los
que depende la condicin de terminacin.
9.2. CUNDO NO UTILIZAR RECURSIVIDAD
La solucin recursiva de ciertos problemas simplifica mucho la estructura de los progra-
mas. Como contrapartida, en la mayora de los lenguajes de programacin las llamadas
recursivas a procedimientos o funciones tienen un coste de tiempo mucho mayor que sus


j
I
1
1
,
1


!
1
<
,
I
,
,
Recursividad: algoritmos recursivos 265
homlogos iterativos. Se puede, por tanto, afirmar que la ejecucin de un programa
recursivo va a ser ms lenta y menos eficiente que el programa iterativo que soluciona
el mismo problema, aunque, a veces, la sencillez de la estructura recursiva justifica el
mayor tiempo de ejecucin.
Los procedimientos recursivos se pueden convertir en no recursivos mediante la in-
troduccin de una pila y as emular las llamadas recursivas. De esta forma se puede
eliminar la recursin de aquellas partes de los programas que se ejecutan ms frecuente-
mente.
PROBLEMA 9.1
Dada una lista enlazada imprimirla en orden inverso.
Se tiene una lista enlazada que se referencia por un puntero externo al primer nodo
de la lista. Se desea imprimir los nodos del ltimo al primero. Los tipos de datos que se
utilizan en la lista son:
type
Tipoinfo -

. . . ,
Puntero = ANodo;
Nodo = record
Info: TipoInfo;
Sgte: Puntero
end;
nil
La variable L referencia al primer nodo de la lista. El problema va a ser descompues-
to de forma recursiva, de tal forma que se vaya reduciendo la lista hasta llegar al ltimo
nodo. Es posible considerar la tarea a realizar dividida en los siguientes pasos:
Imprimir desde el segundo nodo hasta el ltimo en orden inverso.
Imprimir el primer nodo.
Ya se ha reducido la lista en un nodo. A su vez, la primera parte se puede efectuar en
dos pasos:
Imprimir desde el tercer nodo hasta el ltimo en orden inverso.
Imprimir el segundo nodo.
El primer paso est formulado recursivamente. El proceso llega a su fin cuando no
quedan elementos en la lista.
266 Estructura de datos
Codificacin
procedure I mpri melnverso( L: Puntero);
begin
if L <> nil then
begin
I mprimelnver so( LA. Sg t e ) ;
write(LA.lnfo)
end
end;
9.2.1. Eliminacin de la recursividad
Para eliminar la recursividad se utiliza una pila. En la pila el primer elemento que entra
es el ltimo en salir. Por consiguiente habr que recorrer la lista, nodo a nodo. Las direc-
ciones de los nodos (punteros) son almacenados en una pila hasta alcanzar el ltimo
nodo. Una vez alcanzado el ltimo nodo se escribe el campo de informacin y aqu es
donde se simula la recursividad. La vuelta atrs conseguida con la recursividad se consi-
gue sacando de la pila las direcciones de los nodos, escribiendo la informacin, as hasta
que quede vaca la pila.
Codificacin
uses Pi las;
procedure Imprime i nverso (L : Puntero ) ;
var
Pi la: ptrpila;
P : Puntero;
begin
Pcrear (Pila) ;
P : = L;
while P <> nil do
begin
Pmeter( P, Pila) ;
P := PA.Sg t e
end;
{En l a pi l a estn todas las direcciones de l os nodos }
while not Pvacia ( Pil a) do
begin
Psacar(P, Pi la);
Escribir(PA.lnf o)
end
end;
PROBLEMA 9.2
Multiplicacin de dos nmeros enteros por el mtodo de la montaa rusa.
Descripcin: El mtodo consiste en formar dos columnas, una por cada operando.
Las columnas se forman aplicando repetidamente los pasos siguientes:
Recursividad: algoritmos recursivos 267
Dividir por 2 el multiplicando. Anotar el cociente en la columna del multiplican-
do como nuevo multiplicando.
Duplicar el multiplicador y anotarlo en la columna del multiplicador.
Una vez hecho esto, se suman los valores de la columna del multiplicador que se
correspondan con valores impares de la columna de multiplicandos. La suma es el pro-
ducto.
Codificacin
El problema se resuelve con una funcin que tiene como entrada dos enteros X, Y, Y
devuelve el producto aplicando el mtodo de la montaa rusa.
function Pr oducto(X, Y: l o ngi n t): l o ng int;
begin
if X >= 1 than
end;
if (X mod 2) <> o then {Es impar }
Product o := Y + Produc t o( X div 2 , Y * 2)
elee
Producto : = Pr oduc t o(X div 2 , Y * 2)
alee
Producto . - O
. -
9.3. ALGORITMOS DIVIDE Y VENCERS
Una de las tcnicas ms importantes para el diseo de algoritmos recursivos es la tc-
nica llamada divide y vencers. Consiste esta tcnica en transformar un problema de
tamao n en problemas ms pequeos, de tamao menor que n. De modo que dando
solucin a los problemas unitarios se pueda construir fcilmente una solucin del pro-
blema completo.
El algoritmo de bsqueda binaria es un ejemplo tpico de esta tcnica algortmica.
La lista ordenada de elementos se divide en dos mitades de forma que el problema de
bsqueda de un elemento se reduce al problema de bsqueda en una mitad; as se pro-
sigue dividiendo el problema hasta encontrar el elemento, o bien decidir que no se
encuentra. Otro ejemplo claro de esta tcnica es el mtodo de ordenacin rpido
(quick sort).
Un algoritmo divide y vencers puede ser definido de manera recursiva, de tal
modo que se llama a s mismo aplicndose cada vez a un conjunto menor de elementos.
La condicin para dejar de hacer llamadas es, normalmente, la obtencin de un solo
elemento.
9.3.1. Torres de Hanoi
Este famoso juego/acertijo que a continuacin se describe, va a permitir aplicar la tcni-
ca de divide y vencers en la resolucin de un problema. El juego dispone de tres
I
I
,
,
I
,
,

268 Estructura de datos
postes, A, B, C; en el poste A se encuentran n discos de tamao decreciente. El objetivo
es mover uno a uno los discos desde el poste A al poste C utilizando el poste B como
auxiliar. Adems, nunca podr haber un disco de mayor radio encima de otro de menor
radio.
A B e
Vamos a plantear la solucin de tal forma que el problema se vaya dividiendo en
problemas ms pequeos, y a cada uno de ellos aplicarles la misma solucin. En lengua-
je natural lo podemos expresar as:
l. El problema de mover n discos de A a C consiste en:
mover los n-J discos superiores de A a B
mover el disco n de A a e
mover los n- J discos de B a e
Un problema de tamao n ha sido transformado en un problema de tamao n- J. A su
vez cada problema de tamao n-J se transforma en otro de tamao n-2 (empleando el
poste libre como auxiliar).
2. El problema de mover los n-J discos de A a B consiste en:
mover los n-2 discos superiores de A a e
mover el disco n-J de A a B
mover los n-2 discos de e a B
De este modo se va progresando, reduciendo cada vez un nivel la dificultad del pro-
blema hasta que el mismo slo consista en mover un solo disco. La tcnica consiste en ir
intercambiando la finalidad de los postes, origen destino y auxiliar. La condicin de
terminacin es que el nmero de discos sea 1. Cada accin de mover un disco realiza los
mismos pasos, por lo que puede ser expresada de manera recursiva.
El procedimiento recursivo TorresH resuelve el acertijo o juego.
procedure Torr es H (N: integer ; A, B, C: char);
procedure Movimiento(N: integer; A, C: cha r);
begin
writeln( 'Move r disco I ,N, I de I ,A, I a I/e)
end;
begin
if N=l then
Mov imi e nt o (N, A, e)
else begin
To rr es H (N - 1, A, e , B) ;
Mov imiento(N, A, e) ;
TorresH(N - 1, B, A, C)
end
end;
9.3.2. Traza de un segmento
Recursividad: algoritmos recursivos 269
Se desea dibujar un segmento que conecta dos puntos (x 1, Y 1) Y (x2, y2). Suponemos
que siempre xl, Y 1, x2, y2 son> = O. Planteamos la solucin de manera recursiva, utili-
zando la estrategia divide y vencers. El procedimiento consiste en dibujar el punto
medio del segmento; sobre las dos mitades que detennina ese punto medio volvemos a
aplicar el algoritmo de dibujar su punto medio. As hasta que, a base de dividir el seg-
mento, se proporcione un segmento de longitud prxima a cero.
El programa Dibuj ar en el que se define el tipo de dato coordenada (Coord), se
establecen los extremos del segmento y se dibuja.
program Dibujar;
uses c rt;
type
eoor d = record
X : r eal ;
y : rea l
end;
var
O, F : Coo rd;
procedure Dib_sgmto(O, F: eoord) ;
var
M: eoor d ;
begin
with M do
if (O.X+O .S) < F. X then
begin
X := ( O. X+ F. X) / 2 ;
y := (O. Y+F. Y) / 2 ;
Dib_ sgmt o(O, M) ;
if WhereX > 7 0 then
GotoXY( S , Wh e reY + 1 ) ;
wr i t e ( I ( I , X : 3 : 1, , , , I Y : 3 : 1, ' ) I ) ;
Dib_sgmt o (M, F ) ;
end
end;
begin
el rsc r; GotoXY ( 5,1 ) ;
O.X := 1 ; O.Y := 2 ;
F. X := 1 2 ; F. Y := 7 ;
Di b_ sgmt o (O, F)
end.
270 Estructura de datos
9.4. IMPLEMENTACiN DE PROCEDIMIENTOS RECURSIVOS
MEDIANTE PILAS
Un procedimiento, una funcin contiene tanto variables locales como argumen-
tos ficticios (parmetros). A travs de los argumentos se transmiten datos en las llama-
das a los subprogramas, o bien se devuelven valores al programa o subprograma in-
vocante.
Adems, el subprograma debe guardar la direccin de retomo al programa que reali-
za la llamada. En el momento en que termina la ejecucin de un subprograma el control
pasa a la direccin guardada.
Ahora el subprograma es recursivo, entonces adems de la direccin de retomo, los
valores actuales de las variables locales y argumentos deben de guardarse ya que se
usarn de nuevo cuando el subprograma se reactive. Supongamos que se ha llamado al
subprograma P, que tiene llamadas a s mismo, es decir, es recursivo. El funcionamiento
del programa recursivo P:
Se crea una pila para cada argumento.
Se crea una pila para cada variable local.
Se crea una pila para almacenar la direccin de retomo.
Cada vez que se hace una llamada recursiva a P, los valores actuales de los argumen-
tos y de las variables locales se meten en sus pilas para ser procesadas posteriormente.
Asimismo, cada vez que hay un retomo a P procedente de una llamada recursiva ante-
rior, se restauran los valores de variables locales y argumentos de las cimas de las pilas.
Para la obtencin de la direccin de retomo vamos a suponer que el procedimiento P
contiene una llamada recursiva en la sentencia N. Entonces guarda en otra pila la direc-
cin de retomo, que ser la sentencia siguiente, la N + 1. De tal forma que cuando el
nivel de ejecucin del procedimiento P actual termine, alcance la sentencia end final,
usar dicha pila de direcciones para volver al nuevo nivel de ejecucin. De esta forma
cuando la pila de direcciones se quede vaca volver al programa que llam al subpro-

grama recursIVO.
PROBLEMA 9.3
Hacemos una traza del estado de las pilas en la ejecucin de funcin producto, por el
mtodo de la montaa rusa, para los valores de 19 y 45.
1 no nO+Prod ...
2 360 ProductoO
4 180 ProductoO
9 90 90+Prod ..
19 45 45+Prod ..
Pila Pila Pila de
de X de Y direcc.
,

Recursividad: algoritmos recursivos 271
La estrategia a seguir para emular un procedimiento recursivo Pes:
l. Definir una pila para cada variable local y cada argumento, y una pila para alma-
cenar direcciones de retorno.
2. En la sentencia n donde se haga la llamada recursiva a P:
(1) Meter en las respectivas pilas los valores actuales de las variables locales y
argumentos; (2) Meter en la pila de direcciones la direccin de la siguiente
sentencia.
Inicializar los argumentos con el valor actual de ellos y empezar la ejecucin
desde el principio del procedimiento.
3. Vuelta de la ejecucin despus de la llamada recursiva:
Si la pila de direcciones est vaca, devolver control al programa invocador.
Sacar de las pilas los valores de la cima. Llevar la ejecucin a la sentencia
extrada de la pila de direcciones.
9.4.1. El problema de las Torres de Hanoi resuelto
sin recursividad
El problema de las Torres de Hanoi, cuya solucin recursiva se ha descrito, se puede
resolver de forma no recursiva siguiendo esta estrategia.
Algoritmo no recursivo Torres de Hanoi
Los argumentos conocidos son:
N Nme ro de di s co s .
A Vari ll a A
B Var il l a B
e va ri l la e
Para cada uno de ellos se define una pila:
Pil aN
Pi l aA
Pi l a B
p i lae
Adems la pila de direcciones: Pi 1 aD i r
Torre_ Hanoi(N, A, B, el
Crear pilas: Pi laN, Pil aA , Pi l a B, Pi l a e , Pi laDi r
Las etapas a considerar en la construccin del algoritmo To r res de Hano i son:
1. Condicin para acabar.
si N = 1 entonces
Escribir Pa l o A - > Pa l o e
Ir a 5
fin si
272 Estructura de datos
2. Llamada recursiva.
a) Guardar en pilas:
Meter (N, PilaN)
Meter ( A, PilaA)
Meter(B, PilaB)
Meter(C, PilaC)
Meter (e Pas o 3 >, PilaDir )
b) Actualizar los argumentos:
N N - 1
A A
Inter c ambiar B, C:
t B
B C
C t
e) Volver a paso 1.

3. Escribir varilla A Varilla C.


4. Segunda llamada recursiva:
a) Guardar en pilas:
Meter(N, PilaN)
Meter(A, PilaA)
Meter ( B, PilaB)
Meter(C, Pil aC )
Meter (e Pas o 5 > , PilaDir)
b) Actualizar los argumentos:
N N-l
C C
Intercambiar A, B:
t B
B A
A t
e) Volver a paso 1.
5. Este paso se corresponde con el retomo de las llamadas recursivas .

a) Si Pila vaca entonces fin de algoritmo: volver a la rutina llamadora.
b) Sacar de la pila:
Sa c ar(N, PilaN)
Sac ar ( A, PilaA)
Sacar(B, PilaB)
Sacar ( C, PilaC)
Sac ar(Dir, Piladir)
e) Ir al paso que est guardado en Di r.
Recursividad: algoritmos recursivos 273
Codificacin no recursiva del problema de las Torres de Hanoi
Para realizar la codificacin del algoritmo no recursivo de las Torres de Hanoi es ne-
cesario una pila de enteros (P ilaN) y tres pilas de elementos char (Pi l aA, p i la B,
p i 1 aC). Para simular direcciones de retomo se utili za otra pila de enteros en la que se
guarda 1 o 2, segn se simule la primera llamada o la segunda llamada recursiva. Los
tipos de datos y las operaciones estn en las unidades de pilas.
uses pi l acha r, Pi l a int ;
procedure Ha n o i t e r (N : i nteger ; A, B, C : c h a r ) ;
var
Pil a A, Pil a B, p ilaC : Pil a c ha r . Pt rPil a ;
Pi laN , P i l aD : P ilaint . PtrPi la ;
Paso : int eger;
T : c h a r ;
begin
Pi lachar .Pc rea r( P i laA) ;
Pilacha r . Pcr ear (P i l a B) ;
P ilachar . Pcrear (PilaC) ;
Pil a i n t . Pcrea r (Pi laN) ;
p il aint . Pc rear ( Pi l aD ) ;
Pi laint . Pme t e r( l,Pil aD ) ;
while not Pi l aint . Pvacia (PilaD)
i f (N = 1 ) then
do
begin
Mov e r di sco(N ,A , C) ;
P i la int . Ps a car (Pas o , pi l aD) ;
if not P i laint . Pva c i a(Pil aD)
begin
Pi lacha r . Psaca r(A, pilaA) ;
Pi lacha r . Psac a r (B, pilaB) ;
Pi lac h a r . Ps ac ar(C , PilaC) ;
Pil a i n t . Psaca r ( N,Pil aN)
end
end
else begin
Pi l aint. Psaca r(Pas o , Pil aD ) ;
Case Pas o of
1 : begin
Pilachar . Pme t er ( A,Pi laA) ;
Pi l a c h a r . Pmeter (B ,PilaB) ;
Pi l acha r . Pmeter IC , PilaC) ;
Pilai nt . Pmet e r(N, Pi l a N) ;
Pil a i nt . Pmete r (2, Pil aD ) ;
P i 1 a i n t . Pm e t er ( 1 , p i 1 a D) ;
N := N - l;
T := B; B : = C; C : = T
end;
2 : begin
Move r d iscO ( N,A, C) ;
then

{Pa so ac tual }
{No e s n e c esario almac ena r los argume n tos A, B, C, N p ue s no
se utilizan }
Pi l a i n t . Pmet er (1, Pi l aD) ;
,

I



274 Estructura de datos
N := N-1;
T := B; B := A; A : = T
end
end
end
end;
Esta solucin resulta un tanto farragosa debido a la utilizacin de 5 pilas. Una sim-
plificacin fcil que puede hacerse es utilizar una nica pila, en sta se guarda el estado
completo de los argumentos y la direccin de retomo. En la unidad p i 1 a S t a t est
declarado el tipo elemento, un registro con los campos necesarios para guardar A, B, e,
N y Di r , y adems las operaciones de manejo de pilas.
Los tipos de datos en la unidad Pi laSt a t:
type
Elemento = record
Pa , Pb , Pe : ehar ;
Nd , Oir: integ er
end;
Ptr Pi l a =AI temp;
I temp = record
I nf o : Eleme n t o ;
Sgte : PtrPil a
end;
El procedimiento Han o i ter 2 :
procedure Ha n oi ter2( N: intege r; A, B, e : eha r) ;
var
Pil a : PtrPil a ;
T : Elemento;
procedure Est a d o( var St : Elemento ; A,B , e : eha r; N,O : int ege r) ;
begin
with S t do
begin
Pa - A'
-
,
Pb - B;
-
Pe - e ;
-
Nd - N;
-
Oi r
. -
D . -
end
end;
begin
Pe r ear (Pil a ) ;
Es tad o(T , A, B, e , N, l J ;
Pmeter (T, Pi l a ) ;
while not Pvae i a (P i la) do
with T do
begin
Psaear ( T, Pi l a );
if (Nd = 1 ) then
Mo ver_ d i seo( Nd , Pa , Pe)
else
I
,


case Dir of
1: begin
Dir := 2;
Recursividad: algoritmos recursivos 275
Pmeter (T, Pila ); {Estado actual}
Estado(T,Pa,Pc,Pb,Nd-l,l) ;
Pmeter(T,Pila) ;
end
end;
end;
2: begin
Mover_disco (Nd, Pa, Pc);
Estado(T,Pb,Pa,Pc,Nd-l,l) ;
Pmeter(T,pila) ;
end
end
En el programa Torrehanoi se muestran diversas soluciones de las Torres de Hanoi
segn el nmero de discos. Se aplica tanto la solucin recursiva como a las dos solucio-
nes iterativas. La salida se dirige a la impresora.
program Torrehanoi;
uses Pil aint , Pilachar, Pilastat , crt, printer ;
const
Maxnumdiscos = 15;
var
N: integer;
A,B,C: char;
procedure mover_disco (N: int eger; A,C: Ch ar) ;
begin
writeln(Lst, 'Mover disco' ,N,' de ',A,' a ',C)
end;
procedure mover_torre (N : integer ;A,B,C: Char) ;
begin
if N = 1 then
mover_disco(N,A,C)
el se
begin
mover_torre(N-1,A,C,B) ;
mo ver_disco(N,A,C) ;
mover_t orre(N-1,B,A,C)
end;
end;
procedure Hanoit e rl(N: integer; A, B, C:char);
var
pilaA, Pi laB, pilaC: Pilachar.PtrPila;
PilaN, PilaD: Pilaint. PtrPila;
Paso: integer;
T: char;
begin
Pilachar.Pcrear(PilaA) ;
Pilachar,Pcrear(PilaB) ;
Pilachar.Pcrear(PilaC) ;
,


I
;
i
,

;
I
I

276 Estructura de datos


Pi l aint .Pcrear(PilaN} ;
Pi laint.Pcrear(PilaD} ;
Pilaint.Pmeter(l,PilaD} ;
while not Pilaint.Pvacia(pilaD} do
if (N = 1) then
begin
Mover_disco(N,A,C) ;
Pilaint.Psacar(Paso,PilaD) ;
if not Pilaint.Pvac i a(pilaD) then
begin
Pilachar.Psacar(A,Pi l aA) ;
Pilachar.Psacar(B,PilaB} ;
Pilachar.Psacar(C,PilaC} ;
Pilaint.Psacar(N,Pi laN}
end
end
else begin
Pilaint.Psacar(Paso,PilaD) ;
Case Paso of
1: begin
Pilachar.Pmeter(A,PilaA) ;
Pilachar.Pmeter(B,PilaB) ;
pilachar.Pmeter( e ,Pilae) ;
Pilaint.Pmeter(N,Pi l aN} ;
. ..... _._------------------
Pilaint. Pmeter (2, Pi l aD); {Paso ac t ual }
Pilaint.Pmeter(l,PilaD} ;
end
end;
N := N- 1;
T := B; B : = e ; e := T
end;
2 : begin
end
Mover_disco(N,A, e} ;
Pilaint . Pmeter(l,PilaD} ;
N := N- 1;
T := B; B := A; A : = T
end
procedure Hanoiter 2 (N: integer; A, B, e:char};
var
Pila: PtrPila;
T: Elemento ;
procedure Estado(var St: Elemento; A,B, e : char; N,D: integer);
begin
with St do
begin
Pa - A;
-
Pb - B;
-
Pc - e;
-
Nd - N;
-
Dir
. -
D . -
end
end;
begin
Pcrear(Pila) ;
I
I

,


Est ado (T,A,B, C,N,l) ;
Pmet e r (T, Pi l a) ;
while not Pvac i a(Pi la ) do
with T do
begin
Psacar (T , Pi l a) ;
if (Nd = 1) then
Mo ver_di sco (Nd , Pa, Pc)
else
Case Dir of
1: begin
Dir : = 2 ;
Recursividad: algoritmos recursivos 2n
Pmeter (T , Pila ) ; {Est ado actual}
Est ado( T,Pa,Pc, Pb ,Nd- l,l) ;
Pmeter(T, Pila) ;
end;
2 : begin
Move r_d i sco(Nd, Pa , Pc );
Estado( T, Pb , Pa , Pc , Nd-l , l) ;
Pmeter( T, Pila) ;
end
end
end
end;
begin
clrscr ;
A:= 'A';
B - ' B " . - ,
C - ' C " . - ,
wr i t e( 'Numero d e discos? : ' ) ;
repeat
readln ( N)
until N in (l .. Maxnumdi scos ];
cl r scr ;
wr i te l n(Lst , ' Soluc i n recursiva con ' ,N , ' d i scos ' ) ;
mover_t o rre (N, A,B ,C ) ;
wri teln(Ls t ) ;
writ e ln ( Ls t , ' So l uc i n it e ratival con ', N, ' di s cos' ) ;
Ha no it e rl(N,A,B, C) ;
wr i teln;
writeln(Ls t , ' So l uc in i terativa2 con ', N,' di scos ' ) ;
Ha no iter2(N, A, B, C)
end.
9.5. ALGORITMOS DE VUELTA ATRS (BACKTRACKING)
Esta tcnica algortmica recurre a realizar una bsqueda exhaustiva sistemtica de una
posible solucin al problema planteado. El procedimiento general es descomponer el
proceso de tanteo de una solucin en tareas parciales. Cada tarea parcial se expresa fre-
cuentemente en forma recursiva.
El proceso general de los algoritmos de vuelta atrs se contempla como un mtodo
de prueba o bsqueda, que gradualmente construye tareas bsicas y las inspecciona para


278 Estructura de datos
determinar si conducen a la solucin del problema. Si una tarea no conduce a la solu-
cin, prueba con otra tarea bsica. Es una prueba sistemtica hasta llegar a la solucin, o
bien determinar que no hay solucin por haberse agotado todas las opciones que probar.
Aplicamos esta tcnica algortmica al conocido problema de la vuelta del caballo que se
describe a continuacin.
En un tablero de ajedrez de N x N casillas. Un caballo sigue los movimientos de las
reglas del ajedrez. El caballo se sita en la casilla de coordenadas (x
o
, Yo)' El problema
consiste en encontrar, si existe, un circuito que permita al caballo pasar exactamente una
vez por cada una de las casillas del tablero.
La tarea bsica en que va a basarse el problema es la de que el caballo realice un
nuevo movimiento, o bien decidir que ya no quedan movimientos posibles. El algoritmo
que exponemos a continuacin trata de llevar a efecto un nuevo movimiento del caballo
con el objetivo de visitar una vez todas las casillas.
Algori t mo Caball o ;
inicio
Repetir
Seleccionar nuevo movimiento del caballo
si (Est e n tablero) y (No pas ya) entonces
Anota r movi mi e n to e n e l tablero
si (No compl etado t ablero) entonces
Nuevo ensayo : Caballo
{Vuelta de l l amad a recurs i va }
si (No se a l canz so lucin) entonces

Borrar
fin_si
fin si
fin si
hasta (Completado t ab l ero) o (No ms p os i b l es mov imientos)
fin
En los algoritmos de vuelta atrs siempre hay nuevas tentativas en busca de solucin,
nuevos ensayos. En el caso de que un ensayo no conduzca a alcanzar la solucin, se da
marcha atrs. Esto es, se borra la anotacin hecha al realizarse el ensayo y se vuelve a
hacer otro, en el caso de que sea posible (en el caso de un caballo, ste puede realizar
hasta ocho movimientos desde una posicin dada).
Para describir con ms precisin el algoritmo, definimos los tipos de datos para re-
presentar el tablero y los movimientos.
const
N= 8 ;
type
Tabl ero = array[l .. N, 1 .. N) of i n teger ;
var
T : Ta bl e r o ;
El tablero se representa mediante un array de enteros para guardar el nmero de
movimiento en el que pasa el caballo. Una posicin del tablero contendr:

Recursividad: algoritmos recursivos 279
o Por la casilla (X, y ) no pas el caballo.
T[ X, Y]
i Por la casilla (x , Y) pas el caballo en el movimiento i.
Para la accin de seleccionar un nuevo movimiento, hay que tener en cuenta que
dada una posicin el caballo puede realizar 8 posibles movimientos. En una matriz de
dos dimensiones se guardan los 8 desplazamientos relativos para conseguir un siguiente
salto. La figura nos muestra los desplazamientos:

3 .2
.4 1

5 .a
+
.6 .7
La condicin de que el nuevo movimiento est en el tablero y de que no hubiera
pasado anteriormente:
(X i n [1 .. N]) and (Y i n [1 .. N]) and (T[X,Y]= O)
La condicin no completado tablero se representa con el nmero de movimiento i
y el total de casillas:

< NxN
Para no penalizar en tiempo de ejecucin, las variables array son definidas globales.
CODIFICACiN DEL ALGORITMO VUELTA DEL CABALLO
CON UN MTODO RECURSIVO
const
N = 8 ;
type
Tabl ero = array [ l .. N, 1 .. N) of integer ;
Coord = array[1. . 2 , 1. .8 ) of i nteger ;
var
T: Tabl ero ;
H: Coord;
r , J : integer;
S : boolean;
Estructura de datos
procedure Caballo(I: integer; x, Y: integer; var s: boolean);
var
Nx, Ny: integer;
K: integer;
begin
S := false;
K := O; {Inicializa el conjunto posible de movimientos}
repeat
K := K+1;
Nx := X+ H[l,K];
Ny := Y+ H[2,K];
if (Nx in [1 .. N]) and (Ny
if T[Nx, Ny] = O then
begin

ln [ 1 .. N]) then
T [Nx, Ny] : = I; {Anota movimiento}
if I < N * N then
begin {Se produce un nuevo ensayo}
Caballo(I+1, Nx, Ny, S);
if not S then {No se alcanza la solucin}
T[Nx, Ny] := O {Borrado de la anotacin para probar con
otro movimiento}
end
else {Tablero completado}
S := true
end
until S or (K= 8)
end;
En las sentencias del bloque principal se inicializa las posiciones del tablero y los
desplazamientos relativos para obtener nuevas coordenadas.
begin
H[l,l] - 2 ; H[2,1]
-
H[1,2] - 1 .
H[2,2]
-
,
H[1,3] -
-1,
H[2,3]
-
,
H[1,4] - 2 ; H[2,4]
-
H[1,5] - - 2 ; H[2,5]
-
H[1,6] - -1 ; H[2,6]
-
H[1,7] - 1 ; H[2,7]
-
H[1,8] - 2 ; H[2,8]
-
for I - 1 to N do
-
for J - 1 to N do
-
T[I,J]
. -
O ; . -
{El caballo parte
T[l,l] - 1 ;
-
Caballo(2,1,1,S) ;
if S then
for I := 1 to N do
begin
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
de
for J := 1 to N do
wr i t e (T [ I , J] : 4 ) ;
writeln
end
el se
1 ;
2 ;
2 .
,
1 .
,
-1;
-2;
-2;
-1;
la casilla
writeln('NO SE ALCANZA SOLUCION')
end.

(l,l)}
I


I
i
I

,
,

Recursividad: algoritmos recursivos 281
La caracterstica principal de los algoritmos de vuelta atrs es intentar realizar
pasos que se acercan cada vez ms a la solucin completa. Cada paso es anotado, bo-
rrndose tal anotacin si se determina que no conduce a la solucin, esta accin consti-
tuye una vuelta atrs. Cuando se produce una vuelta atrs se ensaya con otro paso
(otro movimiento). En definitiva, se prueba sistemticamente con todas las opciones
posibles hasta encontrar una solucin, o bien agotar todas las posibilidades sin llegar a
la solucin.
El esquema general de este mtodo:
procedimiento EnsayarSolucion
Inicio
Inicializar cuenta de opciones de seleccin
repetir
Seleccionar nuevo paso hacia l a soluci n
si vl ido entonces
Anotar el paso
si no completada solucin entonces
EnsayarSoluc in a partir del nuevo paso
si no alcanza solucin completa entonces
borrar
fin_si
fin_si
fin
. ,

Hasta (Completada solucin) o (No ms opciones )
fin
Este esquema puede tener variaciones. En cualquier caso siempre habr que adaptar-
lo a la casustica del problema a
9.5.1. Solucin del problema Salto del caballo con esquema
iterativo
Ampliamos el problema anterior para encontrar todas las rutas que debe seguir el caballo
para completar el tablero pero utilizando pilas y as transformar el esquema recursivo en
iterativo. En la unidad PilasC tenemos todas las operaciones de manejo de pilas. En la
pila se almacena el nmero de movimiento, nmero de salto y posicin. A continuacin
escribimos el cdigo de la unidad PilasC.
unit PilaC;
interface
const
N = 8;
type
I ndice = 1. .N;
Tipoelem = record
Nummov: integer;
Salto: integer;
X: Indice;
Y: I ndi ce
end;
282 Estructura de datos
PtrPila =Altemp;
Itemp = record
Info: Tipoelem;
Sgte: PtrPila
end;
procedure Pcrear(var Pila: PtrPila);
function Pvacia(Pila: PtrPila): boolean;
procedure Pmeter(var Pila: PtrPila; X: Tipoelem);
procedure Pcima(Pila: PtrPila; var X: Tipoelem);
procedure Pborrar(var Pila: PtrPila);
procedure Psacar(var Pila: PtrPila; var X: Tipoelem);
implementation
procedure Pcrear(var Pila: PtrPila);
begin
pila := nil
end;
function Pvacia(Pila: PtrPila): boolean;
begin
Pvacia := (Pila = nil)
end;
procedure Pmeter(var Pila: PtrPila; X: Tipoelem);
var
A: PtrPila;
begin
new (A) ;
AA.lnfo := X;
AA.Sgte := Pila;
pila := A
end;
procedure Pcima(Pila: PtrPila; var X: Tipoelem);
begin
if not Pvacia(Pila) then
X := PilaA.lnfo
end;
procedure Pborrar(var Pila: PtrPila);
var
A: PtrPila;
begin
if not Pvacia(Pila) then
begin
A := Pila;
pila := PilaA.Sgte;
dispose(A)
end
end;
procedure Psacar(var Pila: PtrPila; var X: Tipoelem);
var
A: PtrPila;
begin
if not Pvacia(Pila) then

---------------------------------_ ... ... .


Recursividad: algoritmos recursivos 283
begin
A : = Pi l a ;
X : = PilaA.Info ;
Pila := PilaA. Sgte;
d i spose( A)
end
end;
begin
end.
Esta unidad la utilizamos para escribir el programa que iterativamente encuentra to-
das las rutas que puede seguir el caballo para recubrir el tablero.
program Caba it ef;
uses
c rt, Pi l aC ;
type
I ncr e mentos - array [1 .. 8 ] of integer;
Tabla = array [indice, i nd i ce] of integer ;
var
Cp : Ptrp ila;
R: Tipoelem;
Xn, Xp , Yn , Yp : integer;
Fila, Co l umna: I ndice;
{c oo rden adas cas il las}
Rl : set of Indice ;
Inc X,
I n c Y: I nc remen t o s ; {Despla zamien tos relativos }
Ta b lero : Tabla;
So luciones, Salto, NumMov : i n t eger ;
Recorrido , Colocado : b o o l e a n;
procedure Anotar (var Nw: Tipoelem; Nm, S: integer;
U, V : Ind i ce) ;
begin
with Nw do
begin
Nummo v := Nm;
Sa l to := S ;
X : = U ;
Y : = V
end
end;
procedure Escribepil a (Cp : PtrPila);
begin
if Cp <> nil then
begin
Es cr i bepila (Cp A. sg te) ;
with Cp A do

write ( i n Eo.nummov : 4 , in f o . sa l to : 2, i n fo . x:2, '-', i n Eo . y) ;


end
end;
procedure Iniciartabler o (var Tabl ero : Tabla);
var
Fila, Columna : Indi c e;

284 Estructura de datos
begin
for Fila := 1 to N do
end;
for Columna := 1 to N do
Tablero[Fila, Columna] .- O
. -
procedure Incre(var Incx, Incy: Incrementos);
begin {Desplazamientos relativos para desde una posicin dada dar
IncX[1]
IncX[2]
IncX[3]
un salto de caballo}
:= 2; IncY[1] := 1;
:= 1; IncY[2] := 2;
:= -1; IncY[3] := 2;
IncX[4] - -2; IncY[4] - 1 ;
- -
IncX[5] - -2; IncY[5] - -1;
- -
IncX[6] - -1; IncY[6] - -2;
- -
IncX[7] - 1 ; IncY[7] - -2;
- -
IncX[8] - 2 ; IncY[8] - -1;
- -
end;
procedure Escribetablero(var Tablero :Tabla);
var
Fila, Columna: Indice;
begin
for Columna := N downto 1 do
begin
end;
for Fila := 1 to N do
write (Tablero [Fila, Columna]: 5) ;
writeln
end;
begin
clrscr;
Rl := [l..N];
Incre(Incx, Incy);
Iniciartablero(Tablero) ;
Write ('Introduzca casilla inicial:');
Nummov : = 1;
with R do
begin
readln (X, Y) ;
Nummov : = 1;
Tablero[X,Y] := Nummov;
Salto := 8
end;
Pcrear (Cp) ;
Pmeter(Cp, R);
Recorrido := false;
Soluciones := O;
while not Pvacia(Cp)do
begin
if Recorrido then
begin
Pcima (Cp, R);
with R do
Tablero[X,Y] := O;
Salto := R.Salto;
Pborrar (Cp) ;
,
,
,
,
,
e,

,
I

,


,
I
,

1

I
l
,
,

J

;
,
j


,
1
Recursividad: algoritmos recursivos
"Vue lta atrs " tl asta l legar a u n a des de la q lle rl o
se ago ta r o n todos los saltos y asi pode r encont r ar otra
1
. "
s o .UC lon
while ( Salto = 81 and not Pvaci a(Cpl do
begin
Pcima ( Cp , RI;
with R do
Tab ler o [X , Y]
Pbo, rar (Cpl ;
. - () ,
. - ,
NUTIIInOV N\;nmov 1 ;
if not Pvacia(Cpl then
begin
end
Pcima(Cp, RI ;
SalLo : = R. . Salto
end
then
285
if not pvacia(Cp l
begin
Tabl ero [R , X, R, Vj := O; {Des ha ce a n te rior para b squ e d a
d e otra SC)l tl(::i!" \ . .
Numme)v : = R . N\lIT\mOV 1;
Pborrar (Cpl ;
Recorrido : = false
end
end
else Salt o
. .
. . o ;
if not pvaci a(Cp ) then
begin
Co locado
Pc imalCp,
repeat
: = f a l se ;
RI ; (Para
Salto : = Salto-1 ;
dar
Xn R . X + In c x lSalto );
'In := R . Y + Incy[Salto] ;
if ( Xn in R: ) and ('In in Rl )
Colocado : = Tab'ero ' Xn , Vn
1
until or (Salto = 8) ;
then
- O - ,
if Co l oc a do then {Anota movimiento}
begin
Nummov
1 .
.. ,
Tabler o ( Xn , Yr; ] : --
Ll:...no tar( R , Sa lto , Xn, Yn ) ;
Pme ter I Cp, R) ;
if Nummov = N * N then ( ru:a compl etada!
begin
end
end
Re corrido
- = t- r"p -
l . '"" '_1
SOlll Cio!leS : = Sol;Jc: iones + 1 ;
wri teln ( ' SOLUCION ': 4 ,1, Sol uciones) ;
(;'<'lbJ ero ) ;
else (No a partir de N,l mmC)V \
while not Colocado and not ? vaci a ( Cp ) do
286 Estructura de datos
begin {March a at rs : e s sacado el movimient o anter i or
para nueva "pru eba " con otro sal to}
Pcima(Cp , R) ;
with R do
Tabl ero [ X, Y] : = O;
Sa l to : = R. Salto ; {Es el l t i mo Sa lto)
Pborrar (Cp) ;
if not Pva ci a(Cp ) then
begin
Pcima(Cp , R);
with R do
begin
Xp : = X;
Yp : = Y
end;
while (S a lto < 8) and not Colocado do
begin
Salto : = Salto + 1;
Xn := xp + Incx[Salto] ;
Yn : = Yp + I ncy [ Salt o];
if (Xn in Rl) and (Yn in Rl ) then
if Tabl e r o [ Xn , Yn ] = O then
begin
Co locado := true ;
Nummov := R. Nummov + 1;
Tabl er o[ Xn, Yn ] : =Nummo v;
Ano t ar( R, Nummov, Sa l t o , Xn , Yn);
Pme t er( Cp , R) ;
end
end
end ( f i n d e if not Pvac i a )
end { fin d e while not col ocado )
end { f in de if not Pva ci a }
end; (fi n del mient r as)
Wr iteln ( ' Soluciones encontradas - " Soluc i ones) ;
end.
A continuacin son expuestos problemas tpicos que son resueltos siguiendo la es-
trategia de los algoritmos de vuelta atrs.
9.5.2. Problema de las ocho reinas
El juego de colocar ocho reinas en un tablero de ajedrez sin que se ataquen entre s es un
ejemplo del uso de los mtodos de bsqueda sistemtica y de los algoritmos de vuelta
,
atraso
El problema se plantea de la forma siguiente: dado un tablero de ajedrez (8 x 8 casi-
llas), hay que situar ocho reinas de forma que ninguna reina pueda atacar (<<comer) a
cualquiera de las otras. En primer lugar recordamos la regla del ajedrez respecto de los
,
movimientos de la reina. Esta puede moverse a lo largo de la columna, fila y diagonales
donde se encuentra. Una primera conclusin es que cada columna puede contener una y
slo una reina, por lo que la colocacin de la reina i queda restringida a las casillas de la
,


"
:
!
,


,

Recursividad: algoritmos recursivos 287


columna i. Por esta coincidencia el parmetro i nos sirve de ndice de columna dentro de
la cual podremos colocarla en los ocho posibles valores de fila.
En cuanto a los tipos de datos para representar las reinas en el tablero, como lo que
nos interesa es detelIuinar en qu fila se sita la reina que est en la columna i , defini-
mos un vector entero. El contenido de una posicin del vector ser 0, o bien el ndice de
fila donde se sita la reina.
const
N= 8 ; { Nmer o d e r ei na s }
type
Fila = array[l . . N] of i nteger;
En orden a buscar la solucin completa, la tarea bsica que exhaustivamente se prue-
ba es colocar la reina i en las 8 posibles filas. La comprobacin de que dicho ensayo es
vlido tiene que hacerse investigando que en dicha fila y en las dos diagonales no haya
otra reina colocada anteriormente. En cada paso se ampla el nmero de reinas coloca-
das, hasta llegar a la solucin completa, o bien determinar que en un paso no sea posible
colocar la reina. Entonces, en el retroceso se coloca la reina anterior en otra fila vlida
para realizar un nuevo tanteo.
CODIFICACiN
const
N= 8; {Nmero de reinas}
type
Fi las = array[ l .. N] of int e ger;
var
Re i nas: Filas;
Soluc i on: boo l ean ;
1: int eger ;
procedure Co l ocar_ Reinas (r : i n teg er ; va r S : bo olean ) ;
var
K: i nteger ;
function Va li do(J : integer) : bool e an ;
{Inspec ci ona s i la r e i na d e la co l umna J e s atacada por a l guna
colocada anteriormen te}
var
R: int eger ;
V: boo l ean ;
begin
V : = true ;
for R : = 1 to J-l do
begin
V : = V and (Reinas[R] <> Reina s[J]) ;
{No es t . e n la mi s ma f il a }
{No est en alguna de las dos diagona l es : }
V : = V and ((Re i nas [J ] + J) <> (Reinas [R] + R)) ;
V := V and ((Rei nas[J] - J) < > ( Re i na s [R ] - R))
end;
Val i do := V

relna
288 Estructura de datos
end;
begin
K : = (J ; {Inici.a lizar pos ibl es mo vimient o s}
repeat

S : .:..: t illse ;

Reinus [I] : = K ; {T enta tiva d e co l ocar re l na


q uelia a n otado
if Val ido(I ) then
if T < 8 then 18 Pllede su!;ti tuir se por NI
begin {No comp let ado e l p roblema}
Co locaI' _ Re ina s(I + 1, S I ;
end
if not S then ( Vuelta atrs)
Reinas[I] : = (J
else (Las 8 reinas c ol oc a das )
S : = true
until S or (K = 8)
end;
1 en ti l a K, a l u v e z
Observar que en la vuelta atrs se puede omitir borrar la anotacin ya que en la
siguiente iteracin se prueba con otra fila, asignando un nuevo valor a la misma posicin
del vector Reinas. En el bloque principal es escrita la solucin.
begin
Colocar Reinas(l, So lucion) ;
if s ol u ci on then
fa r 1 : - 1 t o 8 do
write(Reinus[l] : 5 )
end.
9.5.3. Solucin no recursiva al problema de las ocho reinas
Al igual que la solucin iterativa del salto del caballo, presentamos la solucin iterativa
de las 8 reinas con una pila para emular las llamadas recursivas. Ahora lo relevante en
cada movimiento es el nmero de fila y de columna, ello es lo que guardamos en la pila.
A continuacin escribimos el interface de la unidad p i 1 aR.
unit Pi la R;
interface
c onst
N = 8 ;
type
Rang o 7 l .. N;
Ptr Pila = ANodo ;
Nodo = record
NI' , Co l: word ;
sg te : Pt r Pila
end

procedure PcI' e ar (var Pila : PtrPi l a) ;
function Pva cia ( Pila : Plr Pil a) : bool ea n ;
.
L
Recursividad: algoritmos recursivos 289
procedure Pmeter(var Pila: PtrPila; Nr, Cql: word);
procedure Pcima(pila: PtrPila; var Nr, Col: word);
procedure Pborrar(var Pila: PtrPila);
procedure Psacar(var Pila: PtrPila; var Nr, Col: word);
{Fin de la seccin de interface}
La codificacin del programa que encuentra una solucin al problema.
program ReinaA_It;
{Sita N reinas sin atacarse en tablero N*N. Da una sola solucin}
uses Crt, PilaR;
type
Tipocol = array [Rango) of boolean;
DiagonalDchalzda = array [2 .. 2 * N) of boolean;
( Fila(nmero de reina) + Columna = cte.}
DiagonallzdaDcha = array [1 - N .. N - 1) of boolean;
{F ila o nmero de reina - columna = cte.}
var
Col , Nf, Nr, i: integer;
Colibre: Tipocol; {NO hay reina en fila j-sima}
Ddch: DiagonalDchalzda; {no hay reina en Diagonal Dcha -Izda }
Dizq: DiagonallzdaDcha; {no hay reina en Diagonal Izda-Dcha}
Cp: Ptrpila;
Colocado : boolean;
procedure Listarpila(Cp: Ptrpila);
begin
while CpA.sgte <> nil do
begin
write(CpA.Nr, '= ' ,Cp A.Col,' ') ;
Cp := CpA.Sgte
end;
writeln
end;
procedure Liberar(var Col : Tipocol; var Ddch: DiagonalDchaIzda;
var Dizq: DiagonalIzdaDcha; Nr, CO: word);
begin
Col[Co) := true;
Ddch [Nr + Co l : = true;
Dizq [Nr - Col : = true
end'

procedure Ocupar( var Col: Tipocol; var Ddch: DiagonalDchalzda;
var Dizq: DiagonalIzdaDcha; Nr, Co: word);
begin
Co l[Co)
Ddch[Nr
Dizq[Nr
end;
begin
ClrScr;
:= false;
+ Co) : = fal se;
- Col : = false
write( 'Introduzca dimensin del tablero: ');
repeat
290 Estructura de datos
r eadl n ( Nf )
until Nf <= N;
for i : =1 to Nf do Col ibr e[ i] := t rue ;
for i : =2 to 2 *Nf do Dd c h[i] : = true ;
for i : = 1 - Nf to Nf - 1 do Dizq [ i l : = t rue ;
Pcrea r(Cp) ; Nr := O; Co l : = O;
Pme t er (Cp, Nr , Col ) ;
while (Nr < Nf) and not Pvac i a(Cp) do
begin
Nr : = Nr + 1 ; Colocado : = fals e ;
while not Co locado and (Col < Nf ) do
begin
Co l := Col + 1 ;
if Co libre[Col] then
if Ddch[Nr + Col] then
if Dizq[ Nr - Co l] then
begin
Ocupa r (Co l ibr e , Ddc h, Di zq , Nr , Col) ;
Colocado : = t rue;
Pme t e r (Cp , Nr , Co l );
CA l : = O
end
end;
if not Col ocad o then
begin
if Cp A. Nr <> O then
begin
Libe rar(Colibre , Ddch, Diz q, Cp ' .Nr, CpA . Col);
Nr : = CpA .Nr - 1 ;
Col := CpA . Col ;
end;
Pbo rrar (Cp)
end
end;
if pvaci a( Cp) then
wr it e l n ('NO ENCUENTRO SOLUCION')
else
Li s t a rpila( Cp)
end.
9.5.4. Problema de la mochila
Un esforzado correo desea llevar en su mochila exactamente v kilogramos, se tiene para
elegir un conjunto de objetos de pesos conocidos. Se desea cargar la mochila con un
peso que sea igual al objetivo.
El planteamiento del problema de la mochila: dado un conjunto de pesos pI, p2,
p3, .. pn (enteros positivos), estudiar si existe una seleccin de pesos que totalice exac-
tamente un valor dado como objetivo v. Por ejemplo, si V = 12 Y los pesos son 4, 3, 6, 2,
1, se pueden elegir el primero, el tercero y el cuarto, ya que 4 + 6 + 2 - 12 . La
representacin de los pesos se hace con un vector de nmeros enteros.
const
N = ... { m ximo de pesos previ s t o }
type
Vector = array [ l . . N] of int ege r;
var
Pesos: Ve ctor;
Recursividad: algoritmos recursivos 291
El algoritmo para solucionar el problema tiene como tarea bsica aadir un peso
nuevo, probar si con ese peso se alcanza la solucin, o se avanza hacia la solucin. Es
una bsqueda sistemtica de la solucin hacia adelante. Si llegamos a una situacin de
impasse, en la que no se consigue el objetivo por que siempre es superado, entonces
se retrocede para eliminar el peso aadido y probar con otro peso para inspeccionar si a
partir de l se consigue el objetivo. Esto es, realizar otra bsqueda sistemtica.
La bolsa donde se meten los pesos viene representada por un tipo conjunto. Al aa-
dir un peso, la anotacin se realiza acumulando el peso y metiendo en la bolsa, el con-
junto, el ndice del peso. Para borrar la anotacin se opera a la inversa.
CODIFICACiN
const
N =
type

. . . , {mximo de pesos previsto}
Vec t or - array[l . . N] of i nteger ;
var
Pesos : Vec tor;
Bo l sa : set of 1 .. N;
So l uc i o no boolean;
V: integer ; {Obje tivo}
{V : Es el objet i vo
{Candidato : I ndi ce de l peso
{Cuenta : Suma parc i a l de
}
a aadir }
pesos }
procedure Moc hi la(V: i n teger ; Can didato : i n teger;
Cu e n ta: i n teger ; var S : boo l ean );
begin
if Cuenta = V then
S := t rue
el se if (Cuenta < V) and (Candidato <= N) then
begin
{Es a n o tado el objeto Candidat o y sigue l a b squeda}
Bo l sa : = Bolsa + [Ca n d i dato] ;
Mochi l a(V , Candidato + 1, Cuenta + Pe sos[Candi dato] , S) ;
if not S then {Es excluido Candi dato , para s egu i r
tant eando con sig ui e n te }
begin
Bo l sa : = Bolsa - [ Candida t o ];
Mochila(V, Ca nd idato + 1 , Cuen ta , S)
end
end
end
-

292 Estructura de datos


La llamada a Mochila desde el bloque principal transmite el objetivo V, el candi-
dato 1 y la suma de pesos O.
Mochila (V , 1. o, Solue i on) ;
Eliminacin de la recursin en el problema de la mochila
Para eliminar la recursividad introducimos una pila de enteros para almacenar el candi-
dato actual y en otra pila de nmeros reales almacenar la suma parcial de pesos.
Las llamadas recursivas a Mochila se producen en dos puntos, por lo cual el proble-
ma de guardar la direccin de retomo lo solventamos con otra pila de enteros, en la que
almacenamos tres posibles valores:
O. Indica que la llamada a Mochila procede de fuera del procedimiento.
l . Indica que es una llamada recursiva a Mochila, en la cual se incluye Pesos
[Candidato] dentro de la solucin.
2. Indica que es la llamada recursiva a Mochila, consecuencia de la vuelta atrs al
no alcanzarse la solucin completa.
Para realizar el procedimiento no recursivo de Mochila hay que incorporar la unidad
Pilas para nmeros enteros y para nmeros reales.
uses p i laint , Pi l areal ;
procedure Mo chi l a (V : intege r; Candi dat o: int ege r; Cu enta : integer;
var s : boo l ean ) ;
var
Pc and i , Ps tat : Pi l i nt ;
Pcuent : Pi lreal;
St, C: i n t eger ;
Pso : real ;
begin
S : = f a l se;
Pcr e ar(Pca ndi) ;
Pi lareal .Pc r ear (Pcuent ) ;
Pcrear(Ps t at) ;
Pmeter(O, Pstat) ; {Es as i gnado e l estado inicial}
repeat
if Cuen ta = V then
S : = true
el se if (Cuent a < V) and (Candi d at o <= N) then
begin
{Es anot ado e l objet o Candi dato y sigue l a b squeda}
Bols a : = Bo lsa + [ Cand ida t o ];
Cuenta := Cuen ta + Pesos [Candi dato] ;
Pi l area l. Pmeter(Cuen ta , Peuent ) ;
Candi d ato := Candi dato + 1 ;
Pmet er (1 , Pstat) ;
end
el se if (Cuenta> V) and (Cima (Pstat) = O) or
(Candidato > N) then
begin
Ca ndida t o : = Can d i dato - 1;
Pborrar( Pstat ) ;
end
else if Cima (Pstat) = 1 then
Recursividad: algoritmos recursivos 293
begin {Se excluye al c andidato y se vuelve a proba r}
Bols a : = Bol sa - [Candidato ];
Pi lareal. Ps a car (Cuenta , Pcue n t);
Ca ndidato := Candidat o + 1;
Pborr ar (Pstat) ;
Pmeter(2, Pstat)
end
el se if Cima (Pstat) = 2 then
begin
Candi dato : = Can d idat o - 1 ;
Pborrar( Pstat )
end
until Pva c ia (Ps t at) or S
end;
{Al h abe r dos unidades de p i las las refer e n cias a l as r utinas d e l a
unidad Pil a real las cual ifi c amos con s u nombre . }
9.5.5. PROBLEMA DEL LABERINTO
Se desea simular el juego del laberinto. En el laberinto hay muros por los que no se
puede pasar. El viajero debe moverse desde una posicin inicial hasta la salida del labe-
rinto. El laberinto est representado por una matriz de N x N, los muros son representa-
dos en la matriz por celdas que contienen el carcter 0, los caminos por celdas con el
carcter l. La salida del laberinto viene indicada por la celda que contiene una S. La
entrada al laberinto es nica, sus coordenadas son conocidas.
La representacin de datos es:
const
N = 12 ; {tamao del laberi nto}
Nor t e = 1;
Sur = N;
Oe s t e = 1;
Es t e = N;
type
La t i tud = Norte .. Su r;
Lo ngitud = Oes te .. Este ;
Labe rint o = array[ Lat i tud , Lon g itud] of char o
ALGORITMO
El viajero parte de una casilla inicial. Desde una casilla puede moverse a cuatro posibles
casillas (hacia el Norte, el Oeste, el Sur o el Este). El movimiento estar permitido si en
la nueva casilla no hay un muro. Cada vez que se pasa por una casilla se marca con
un '*' para as saber el camino seguido hasta la salida. Si llegamos a una situacin de
impasse, es decir estamos en una casilla desde la cual ya no podemos avanzar: se
desanota la casilla, se marca la casilla como si fuera un muro para no volver a pasar por

296 Estructura de datos
L [ Af.Lf] := ' S ';
Ex i to := f a l se ;
So l ue l abe r ( AO , LO, Ex ito) ;
if Ex i t o then
Ve rlab(L)
else
writeln ( , HorrOr n o sa limos del laber into !!' )
end.
9.5.6. Generacin de las permutaciones de n elementos
La resolucin est basada en la ley de fOlmacin de las permutaciones de n elementos.
Partiendo de las Permutaciones de O elementos se obtienen las Pelmutaciones monarias
tomando l(k) elemento y situndolo en todas las posiciones posibles: p = l. Las Permu-
taciones binarias se obtienen tomando el 2(k) elemento y situndolo en todas las posi-
ciones posibles: p = 2, p = l. En definitiva, en el paso i el elemento i debe colocarse en
las p = i, P = i - 1, p = i - 2, ... , p = 1. Para ello el array A est indexado de O a n,
guardando en la posicin p el ordinal de la permutacin (k) y en la posicin k, ordinal de
la anterior permutacin. El primer valor de p = O. Cuando se alcanza k = n es escrito el
contenido de la permutacin y despus el elemento k es colocado en A[P] para as
colocar el elemento k en posicin anterior. La solucin se plantea recursivamente,
aplicando una variacin a la estrategia de backtracking para as agotar todas las solu-
ciones que ahora se convierten en grupos de n elementos.
CODIFICACiN
program Generadorpermu t a eion e s ;
uses e rt;
const
Maxg r a d o = 1 0 ;
B: array [O .. Maxgrado ] of ehar =
( X , ~ , ' B ' , 'C' , ' D " , ' , ' F', ' G ' , ' H ' , '1', ' J ') ;
type
Apun t ado r = O .. Ma xgrado ;
var
A: array [ Apun tador ] of Apu ntador;
N: integer;
X : e har;
procedure proee sopermut ac i on ;
var
q :Apuntador;
begin
q : = O;
while A[ q ] <> O do
begin
wri te ( B [ A [q]] ) ;

q : =A[ q ];
end;
wr i t e ( , , : 1 0 - N)
end;
procedure permuta( K,N: Apun tador ) ;


,
.\





,

,

j
var
p : Apuntador ;
begin
P
. - O .
. - ,
repeat
A[K ]
A[p]
:=A[pJ;
'-K' . - ,
if K = N then
procesopermutac i o n
else
pe r muta(K+1.N) ;
Recursividad: algoritmos recursivos 297

{Ahora se " col o ca" en la a n t eri o r , repr esentado por A[K ] )


A[ p] : =A [ K] ;
p : = A[ p];
until p = O;
write l n ;
end;
begin
c lr scr ;
repeat
write( 'Numero de e l eme n t o s a permutar:') ;read ln(N);
until N in [l .. Maxgr a d o] ;
write l n( 'Permut aci on es de ': 50 ,N, 'el e mentos ' );
A [ O] : = O;
Permu t a (l , N);
X := readkey
end.
9.6. PROBLEMA DE LA SELECCiN PTIMA
En los problemas del Salto de caballo, Ocho reinas y Mochila se ha aplicado la estrate-
gia de vuelta atrs para encontrar una nica solucin. Con la misma base, se ha hecho
una ampliacin para encontrar as todas las soluciones. Ahora no se trata de encontrar
una situacin fija o un valor predeterminado, sino de encontrar del conjunto de solucio-
nes la ptima segn unas restricciones definidas.
En trminos reales, este es el problema del viajante que tiene que hacer las maletas
seleccionando entre n artculos, aquellos cuyo valor total sea un mximo (lo ptimo, en
este caso, es el mximo establecido) y su peso no exceda de una cantidad.
Seguimos aplicando la estrategia de vuelta atrs para generar todas las soluciones
posibles, y cada vez que se alcance una solucin guardarla si es mejor que las solucio-
nes anteriores segn la restriccin definida.
if solucion then
if mej o r ( s o luc i on) then
opti mo :=soluc ion
La tarea bsica en esta bsqueda sistemtica es investigar si un objeto i es adecuado
incluirlo en la seleccin que se ir acercando a una solucin aceptable, y continuar la
bsqueda con el siguiente objeto. En el caso de que lo que haya que hacer sea excluirlo
298 Estructura de datos
de la seleccin actual, el criterio para seguir con el proceso de seleccin actual es que el
valor total todava alcanzable despus de esta exclusin no sea menor que el valor pti-
mo (mximo) encontrado hasta ahora. Cada tarea realiza las mismas acciones que la
tarea anterior, por lo que puede expresarse recursivamente. Al estar buscando la selec-
cin ptima, hay que probar con todos los objetos del conjunto.
Consideramos que el valor mximo alcanzable inicialmente es la suma de todos los
valores de los objetos que disponemos. Debido a la restriccin del peso, posiblemente el
valor ptimo alcanzado sea menor.
9.6.1. El viajante de comercio
Suponemos que el viajante tiene 10 objetos. La entrada de datos es la informacin aso-
ciada con cada objeto: <Peso, Valor>. El peso mximo que puede ser transportado varia-
r desde el mnimo peso hasta el peso total de los objetos, con un incremento de 3 y un
mximo de 10 salidas.
El valor mximo que pueden alcanzar los objetos es la suma de los valores de cada
uno, est representado por la variable Tva 1 o r. El valor ptimo alcanzado en el proceso
transcurrido est en la variable Mvalor.
Los parmetros del procedimiento recursivo son los necesarios para realizar una nueva
tarea: r, nmero de objetos a probar; Pt, peso de la seleccin actual; Va , valor mximo
alcanzable por la seleccin actual; y Mva 1 o r , que es el valor mximo obtenido en el
proceso transcurrido.
CODIFICACIN
program Optima(input , output);
uses crt;
const
N = 10 ;
type
Indice - 1 .. N;
Objet o - Record
va l: i nteger;
pso : integer
end;
Li sta = array [Indicel of Objeto ;
Conj = set of Indice;
var
A: Lista;
Psomx, Tpeso,
Tvalor, Mva lor ,
T, K: integer ;
Ac t, Opt o Conj ;
procedure Obj etos(var G:Li s t a ; var TV, Tp :int eger) ;
var
K:integer;
begin
writeln;
Recursividad: algoritmos recursivos 299
Tv := O; Tp := o;
for K := 1 to N do
begin
write( 'Objeto', K,'.', 'Peso y Valor:');
readln(G[K] .pso,G[K] .val);
Tv := Tv + G[K] .val;
Tp := Tp + G[K] .pso
end
end;
function Min(A:Lista) :integer;
var
K,M:integer;
begin
M := A[l] .pso;
for K := 2 to N do
if A[K] .pso < M then
M := A[K] .pso;
Min := M
end;
procedure Solucion (S:Conj; P,V:integer);
{Salida del conjunto de objetos}
var
K:integer;
begin
i f S < > [ ] then
begin
end;
wri te (' Seleccion ptima: ') ;
for K := 1 to N do

if K in S then
Wr i t e (' < ' , A [ K] . P s o, ' , ' , A [ K] . val, '>' ) ;
wr i t e 1 n (' P e s o: ' , P, ' Va 1 o r: ' , V)
end
{El procedimiento

recurSlVO, Maleta, es el que encuentra la seleccin
ptima}
procedure Maleta (1:indice; Pt,Va:integer;var Mvalor: integer);
var
VaEx:integer;
begin
if Pt + A[1] .pso <= Psomx then {El objeto 1 se incluye}
begin
Act := Act + [1];
if 1 < N then
Maleta (1+l,Pt+A[1] .pso,Va, Mvalor)
elee if Va > Mvalor then {Todos los objetos han sido probados y}
begin {se ha obtenido un nuevo valor ptimo}
Opt : = Act;
Mvalor := Va
end;
Act := Act - [1] {Vuelta atrs para ensayar la exclusin}
end;
{Proceso de exclusin del objeto 1 para seguir la bsqueda
sistemtica con el objeto Y+l}

300 Estructura de datos
Va Ex : = Va - A [ 1 ] . val ;
{VaEx es e l va l or mx i mo q u e podr a alcan za r la se l ecc i n ac t ua l)
if VaEx > Mvalor then
end;
if 1 < N then
Maleta ( 1+1, Pt , Va Ex, Mv alor)
el Be begin
Opt := Act;
Mvalor : = Va Ex
end;
{s i Va Ex < Mvalor es i ntil seguir ensayan do ya que no va a
s up erar e l va l o r pt imo act u a l : Mval o r}
begin
c l rscr ;
end.
write l n ('Entrada de ' , N, 'Objetos') ;
Obje t os (A , Tval o r , Tpeso) ;
c l rs cr;
wri te ('Peso: ') ;
for K := 1 to N do
wr i t e (A [ K] . P s o : 6 ) ;
write l n ;
write ('val or : ') ;
for K : = 1 to N do
wr ite (A [ K]. va l: 6) ;
wr it e ln;
{El p eso mxi mo i r variand o d esde el mni mo , h as t a al canzar e l
mx i mo o 10 pruebas , cada prueba aumenta e l peso e n 3 uni dades}
T := Min (A) ; Psomx : = T ;
repeat
Ac t :=
Mvalor
Maleta
[ ]; Op t : = [ 1;
: = O;
(l, O,Tva l or , Mvalor ) ;
so luc ion (Opt,Psomx , Mvalo r ) ;
Psomx := Psomx+3
until (Psomx > Tpeso) or (Psomx > T+I0 * 3)
9.7. PROBLEMA DE LOS MATRIMONIOS ESTABLES
El planteamiento del problema es el siguiente: dados dos conjuntos A y B, disjuntos y
con igual nmero de elementos, n, hay que encontrar un conjunto de n pares (a,b) , tales
que a pertenece A, b pertenece a B y cumplan ciertas condiciones.
Una concrecin de este planteamiento es el problema de los matrimonios esta-
bles. Ahora A es un conjunto de hombres y B un conjunto de mujeres. A la hora de
elegir pareja, cada hombre y cada mujer tienen distintas preferencias. Se trata de for-
mar parejas, matrimonios estables. De las n parejas, en cuanto exista un hombre y
una mujer que no formen pareja pero que se prefieran frente a sus respectivas parejas,
se dice que la asignacin es inestable ya que tender a una ruptura para buscar la pre-
ferencia comn. Si no existe ninguna pareja inestable se dice que la asignacin es es-
table.
,
1
Recursividad: algoritmos recursivos 301
En el problema se hace la abstraccin de que la lista de preferencias no cambia al
hacer una asignacin.
Este planteamiento caracteriza ciertos problemas en los que hay dos conjuntos de
elementos y se ha de hacer una eleccin segn una lista de preferencias. As, pensemos
en el conjunto de ofertas de vacaciones y el conjunto de turistas que quieren elegir una
de ellas; la eleccin de facultad por los chicos de COU ...
ALGORITMO
Una forma de buscar solucin es aplicar la bsqueda sistemtica de los algoritmos de
vuelta atrs. La tarea bsica es encontrar una pareja para un hombre h segn la lista de
preferencias, esta tarea bsica la realiza el procedimiento ensayar:
procedimiento En sayar(H : TipoHombr e)
var
R: ent e ro
inicio
Desde R r 1 hasta n hacer
<Toma r pre f erenc i a R-s ima de hombr e H>
si acept able entonces
<Anot ar matri mon io>
si <H no es el l timo hombre> entonces
En sayar(H+l)
sino
<El conjunt o d e mat rimonios e s e st able >
fin_Si
<Cancelar el ma t r i mon i o>
fin_si
fin_Desde
fin
Ahora afrontamos la tarea de representacin de datos. El Tipohombre, Tipomujer
son representados por un subrango entero; por tanto, hacemos la abstraccin de repre-
sentar tanto un hombre como una mujer por un nmero que es el ordinal del rango de
hombres o de mujeres. Para representar las preferencias de los hombres por las mujeres
se utiliza una matriz de mujeres. Recprocamente, las preferencias de las mujeres por los
hombres son representadas por una matriz de hombres.
La solucin del problema ha de ser tal que nos muestre las parejas (hombre-mujer)
que forman la asignacin estable. Dos vectores, uno de las parejas de los hombres y el
otro de parejas de las mujeres, representan la solucin.
const
N = ... ; {Nme ro de pa rej as}
type
Tipohombre = 1 .. N;
Tipomujer = 1 .. N;
Pr efhombre s = array [Tipohombre , 1 .. NJ of Tipomujer;
Pr ef muje re s = array [Ti pomu j er, l .. NJ of Ti pohombr e ;
Parhombres= array [Tipohombre J of Ti pomu j e r;
302 Estructura de datos
Parmujer es = array [ Ti p omu j eres ] of Ti poh ombre;
var
Phb: Pre fh ombr es ;
Pmj : Pr e f mujeres ;
V: Parhomb re s ;
F: Par mujeres;
La informacin representada por V y F determina la estabilidad de un conjunto de
matrimonios. Este conjunto se construye paso a paso casando hombre-mujer y compro-
bando la estabilidad despus de cada propuesta de matrimonio. Para facilitar la inspec-
cin de las parejas ya forllladas utilizamos un array lgico:
Soltera: array [ Tipomu j er] of boolean;
Soltera [J] a true quiere decir que la mujer J todava no ha encontrado pareja. Para
determinar si un hombre K ha encontrado pareja puede utilizarse otro array similar al de
Soltera, o bien sencillamente si K< H es que K ya encontr pareja (H es el hombre actual
que busca pareja).
Con todas estas consideraciones de tipos de datos ya podemos proponer una solu-
cin ms elaborada:
procedimiento Ensayar(H : Ti poHombre)
var
R: e n tero ;
M: Tipomu jer;
inicio
Desde R r 1 hasta
M r Phb [H, R]
N hacer
{Mujer candidata }
si Soltera[M] y <Establ e> entonces
V [H ] r M
F[ M] r H
So l ter a [M] r False
si H < N entonces
Ensayar(H+ l)
sino
<Ano t a r, conjunt o ya es es t abl e>
fin_si
Soltera [ M] r True
fin_si
fin_desde
fin_procedimiento
La accin ms importante que nos falta es determinar la estabilidad que ha sido
expresada como <Estable>. Pues bien, la buscada estabilidad se encuentra por com-
paraciones entre las distintas preferencias. Las preferencias vienen dadas por el rango
de 1 a N. Para facilitar el clculo de la estabilidad son definidas dos matrices:
Rhm : array [ Tipohombr e ,Ti pomu j er] of 1 .. N;
Rmh : array [Tipomujer, Tipohombre ] of 1 .. N;
Recursividad: algoritmos recursivos 303
tal que Rhm [H , M 1 contiene el orden que ocupa, o rango, de la mujer M en la lista de
preferencias del hombre H. De igual forma, Rmh [M, H 1 contiene el orden del hombre H
en la lista de preferencias de la mujer M. Ambas matrices se determinan inicialmente a
partir de las matrices de preferencias.
El predicado <Estable> parte de la hiptesis de que lo normal es la estabilidad y se
buscan posibles fuentes de perturbarla. Recordemos que se est analizando la estabili-
dad de la posible pareja H y M, siendo M la mujer que ocupa la posicin R en la lista de
preferencias de H (M f- Phb [H , R 1 ) . Hay dos posibilidades:
1. Puede haber otra mujer Mm, por la que H tenga ms preferencia que M, y a su
vez Mm prefiera ms a H que a su actual pareja.
De forma simtrica.
2. Puede haber otro hombre Hh, por el que M tenga ms preferencia que a H, y a su
vez ese hombre prefiera ms a M que a su actual pareja.
La posibilidad 1 se dilucida comparando los rangos Rhm [Mm, H J Y Rmh [Mm, F [Mm J J
para todas las mujeres ms preferidas que M por el hombre H. Es decir, para todas las
Mm f- Phb [H, 1 1 tales que 1 < R. Adems, todas estas mujeres tienen ya pareja,
ya que si alguna estuviera soltera el hombre H la hubiera elegido ya. Esta posibilidad
puede expresarse:
Es t able true
1 1
mientras (1 < R) Y Est able hacer
Mm Phb [ H,I ]
si no so ltera[Mm] entonces
Estable Rmh [ Mm, H] < Rmh [ Mm, F [Mm] ] {Es e s table s i p r e f iere ms }
fin si {a su act ual pare ja }
fin_mientras
Para analizar la posibilidad 2 razonamos de forma simtrica. Hay que investigar a
todos los hombres Hh por los cuales tiene ms predileccin la mujer M que a su pareja
actual H:
1 1
Tope Rmh[M,H ]
mientras (1 < Tope) y Estable hacer

1 1 +1
si Hh < H entonces
Est able Rhm [ Hh,
fin si
{ Hh ya tiene par eja }
M] > Rhm[ Hh , V[Hh]] {Es table s i Hh pr efi ere }
{ a su actual p areja . }
La codificacin de estas dos posibles fuentes de inestabilidad la realizamos en una
funcin lgica anidada al procedimiento ensayar.
304 Estructura de datos
CODIFICACiN
program MatrimonioEstable;
uses
crt;
const
N = 9;
type
{Nmer o de parejas a formar}
Tipohombre = 1 .. N;
Tipomujer = 1 .. N;
Prefhombres = array [Tipohombre, 1 .. Nl of Tipomu jer;
prefmujeres = array [Tipomuje r , 1 .. Nl of Tipohombre;
Parhombres = array [Tipohombrel of Tipomujer;

Parmujeres = array [Tipomujerl of Tipohombre;


Flags = array[Tipomujerl of boolean;
Matranghb = array[Tipohombre, TipomujerJ of 1 .. N;
Matrangmj = array[Tipomujer, Tipohombrel of 1 .. N;
var
Phb: Prefhombres;
Pmj: Prefmujeres;
V: Parhombres;
F: Parmujeres;
Soltera: Flags;
Rhm: Matranghb;
Rmh: Matrangmj;
H: Tipohombre;
M: Tipomujer;
R: integer;
procedure Escribir;
var
H: Tipohombre;
begin
write('Solucin: ');
for H := 1 to N do
write('<H', H, ',M', V [H), '>; ');
writeln
end;
procedure Ensayar(H: Tipohombre);
var

R: lnteger;
M: Tipomujer;
function Estable(H:Tipohombre;M:Tipomujer;R:integer) :boo lean;
var
Hh: Tipohombre;
Mm: Tipomujer;
1, Tope: integer;
Es: boolean;
begin
Es := true;
1 : = 1;
while (1 < R) and Es do
begin
Mm := Phb[H,11;
1 := 1+1;
I
,

Recursividad: algoritmos recursivos 305


if not Sol t era[Mm) then
Es := Rmh[Mm,H) < Rmh[Mm,F[Mm))
end;
1 : = 1;
To-pe : = Rmh [M, H) ;
while (1 < Tope) and Es do
begin
Hh : = Pmj [M, 1) ;
1 : = 1 + 1;
if Hh < H then
Es : = Rhm[ Hh,M) > Rhm[Hh,V[Hh ))
end;
Estable := Es
end;
begin {Ensayar}
for R := 1 to N do
begin
end;
M := Phb [ H, R];
if So ltera [Ml and Es table( H, M, R) then
begin
V[H)
F [ M)
" - M"
" - ,
" - H"
" - ,
SOltera [M) := false;
if H < N then
Ensayar (H + 1)
else {Encontrada una asignaci n estable }
Escribi r ;
Soltera [M) : = true
end
end
begin (bloque principal)
clr scr ;
(Entrada de rango de preferencias de hombres)
for H := 1 to N do
begin
writeln('Preferenc ias de hombre', H,' segn rango de 1 a " N);
for R := 1 to N do
begin
read(Phb[H, R)) ;
Rhm[H, Phb[H, R]) : = R
end
end;
( En trada de rango de preferencias de mujeres)
for M : = 1 to N do
begin
wr i te ln('Preferencias de mujer',
for R := 1 to N do
begin
read(Pmj [M, R]);
Rmh[M,Pmj [M, Rl] := R
end
end;
for M := 1 to N do
Soltera [M) : = true;
Ensayar(l)
end.
M ' , seg n rango de 1 a " N) ;
-

,
306 Estructura de datos
RESUMEN
La recursin (recursividad) pellnite resolver problemas cuyas soluciones iterativas son dificiles
de conceptualizar: un procedimiento o funcin que se \lama a s misma. Normalmente, una solu-
cin recursiva es menos eficiente en trminos de tiempo y operaciones suplementarias que entra-
an las \lamadas extra a procedimientos; sin embargo, en numerosas ocasiones el uso de la recur-
sin permite especificar una solucin muy natural y senci\la a problemas que en caso contrario
seran muy difciles de resolver. Por esta razn, la recursividad es una herramienta muy importan-
te y potente para la resolucin de problemas con programacin.
El uso apropiado de la recursividad se debe considerar antes de su utilizacin. Una vez toma-
da la decisin, el programador debe tener mucha precaucin en proporcionar condiciones de ter-
minacin para detener las llamadas recursivas. Es muy fcil entrar en un bucle infinito si no se
incluyen condiciones de terminacin adecuadas.
Algunos lenguajes de programacin no permiten la recursividad. Por consiguiente, un progra-
mador puede desear resolver un problema utilizando tcnicas recursivas mediante el uso de pseu-
docdigo. Incluso, como en el caso de Pascal, que soporta recursividad, el programador puede
tratar de intentar reducir las operaciones y el tiempo auxiliar implicado en el proceso recursivo
simulando la recursividad.
EJERCICIOS
9.1. Suponer que la funcin G est definida recursivamente de la siguiente forma:
G(x, y) =
G(x-y+I)+l
1 si x y

SI Y < x
Siendo x,y enteros positivos.
a) Encontrar el valor de G (8,6).
b) Encontrar el valor de G (100,10).
9.2. Sea H(x) una funcin definida recursivamente '<fx > O, siendo x un entero:
1 si x = 1
H(x) =
H(x / 2) + 1 si x> I
a) Encontrar el valor de H(80).
b) Cmo podemos describir lo que hace esta funcin?
9.3. Oefinimos C(n,k) como el nmero de combinaciones de n elementos agrupados de k en k,
es decir, el nmero de los diferentes grupos que se pueden formar con k miembros dado un
conjunto de n miembros para elegir. As, por ejemplo, si n = 4 ({ A,B,C,O}) C( 4,2) = 6 que
sern: (A,B), (A,C), (A,O), (B,C), (B,O), (C,O).
matemticamente C(n,k) podemos definirla:
C(n,I)=n
C(n,n) = I

C(n,k) = C(n - 1, k - 1) + C(n - 1, k) '<fn > k, k > I
. -
Recursividad: algoritmos recursivos 307
a) Encontrar el valor de C(8,5).
b) Escribir una funcin recursiva para calcular C(n,k).
9.4. Eliminar la recursividad de la funcin C(n,k). Escribir la funcin C(n,k) de forma iterativa
utilizando una pila para eliminar la recursividad.
9.5. Dada la siguiente funcin recursiva:
function Reves( N: i n teger) : c h a r;
var e: char;
begin
r e ad (e) ;
if eoln then
Reve s := ' * '
el Be
Reve s := Reves(l) ;
wr it e(e )
end;
a) Qu hace la funcin?
b) Hacer un seguimiento con esta llamada: Reves(l).
9.6. Dado el siguiente procedimiento recursivo:

procedure Descon ocido(N, Despl : i nteger ) ;
var
K: intege r;
begin
if N > O then
begin
Des c onocido( N- l , Despl +l) ;
for K := 1 to Des pl do
wri te( ' ' ) ;
for K : = 1 to Des p l do
wri t e ( ' I ' ) ;
writeln;
Des c onoc i do( N- l, Desp l +l )
end
end;
Hacer un seguimiento del procedimiento para la llamada Desconocido (4, 1).
9.7. Eliminar la recursividad del procedimiento escrito en 9.6. Escribir de nuevo el procedi-
miento Desconocido del ejercicio 9.6 utilizando una pila.
9.8. Realizar una funcin recursiva que calcule la funcin de Ackermann definida de la siguien-
te fOIlIla:
A(m,n) = n+ l
A(m,n) = A(m-l,l)
A(m,n) = A(m-I,A(m,n-l
si m = O
si n = O
si m > O Y n > O
9.9. Escribir la funcin de Ackellnann eliminando la recursividad.
9.10. La resolucin recursiva de las Torres de Hanoi ha sido realizada con dos llamadas recursi-
vas. Volver a escribir el procedimiento de resolucin con una sola lmmada recursiva.
Nota: Sustituir la ltima llamada por un bucle repetir-hasta.
-----------------------------------.
308 Estructura de datos
PROBLEMAS
9.1. En el problema de las 8 reinas se encuentran 92 soluciones diferentes. Hacer los cambios
necesarios en el procedimiento de resolucin para que nos muestre nicamente las solucio-
. , .
nes no slmetncas.
9.2. Escribir un programa que tenga como entrada una secuencia de nmeros enteros positivos
(mediante una variable entera). El programa debe de hallar la suma de los dgitos de cada
entero y encontrar cul es el entero cuya suma de dgitos es mayor. La suma de dgitos ha
de ser con una funcin recursiva.
9.3. Sea A una matriz cuadrada de n x n elementos, el determinante de A podemos definirlo de

manera recursIva:
a) Si n = 1 entonces Deter(A) = al.l'
b) Para n > 1, el determinante es la suma alternada de productos de los elementos de una
fila o columna elegida al azar por sus menores complementarios. A su vez, los menores
complementarios son los detellninantes de orden n-l obtenidos al suprimir la fila y
columna en que se encuentra el elemento.
Podemos expresarlo:
n
Det(A)= L (-ly+J *A[i,j] * Det(Menor(A[i,j])); para cualquier columna}
; = 1
o
n
Det(A)= L (-ly+J *A[i,j] * Det(Menor(A[i,j])); para cualquier fila i
j ~
Se observa que la resolucin del problema sigue la estrategia de los algoritmos divide y
vence.
Escribir un programa que tenga como entrada los elementos de la matriz A, y tenga como
salida la matriz A y el determinante de A. Eligiendo la fila 1 para calcular el determinante.
9.4. Escribir un programa que transforme nmeros enteros en base lOa otro en base B. Siendo
la base B de 8 a 16. La transformacin se ha de realizar siguiendo una estrategia recursiva.
9.S. Escribir un programa para resolver el problema de la sub secuencia creciente ms larga. La
entrada es una secuencia de n nmeros a" a2' a3, ... , a
n
; hay que encontrar la subsecuencia
ms larga ail, a2, ... ak tal que a1 < aj2 < a3 ... < ak Y que il < i2 < i3 < ... < ik. El programa
escribir tal subsecuencia.
Por ejemplo, si la entrada es 3, 2, 7, 4, 5, 9, 6, 8, 1, la subsecuencia creciente ms larga
tiene longitud cinco: 2, 4, 5, 6, 8.
9.6. El sistema monetario consta de monedas de valor PI' P2, P3' ... ,Pn (orden creciente) pesetas.
Escribir un programa que tenga como entrada el valor de las n monedas en pesetas, en
orden creciente, y una cantidad X pesetas de cambio. Calcule:
a) El nmero mnimo de monedas que se necesitan para dar el cambio X.
b) Calcule el nmero de formas diferentes de dar el cambio de X pesetas con lap monedas.
Aplicar tcnicas recursivas para resolver el problema.
9.7. Dadas las m primeras del alfabeto, escribir un programa que escriba las diferentes agrupa-
ciones que se pueden formar con n letras (n < m) cada una diferencindose una agrupacin
de otra por el orden que ocupan las letras, o bien por tener alguna letra diferente (en defini-
tiva, formar variaciones Vm,n).
Recursividad: algoritmos recursivos 309
9.8. En un tablero de ajedrez se coloca un alfil en la posicin (xo, Yo) Y un pen en la posicin
(1, ), siendo 1 < = ) < = 8. Se pretende encontrar una ruta para el pen que llegue a la
fila 8 sin ser comido por el alfil. Siendo el nico movimiento permitido para el pen el de
avance desde la posicin (i,) a la posicin (i + 1, ). Si se encuentra que el pen est
amenazado por el alfil en la posicin (i,), entonces debe de retroceder a la fila 1, columna
) + l o) - 1 {(l,) + 1), (1,) - 1)}.
Escribir un programa para resolver el supuesto problema. Hay que tener en cuenta que el
alfil ataca por diagonales.
9.9. Dados n nmeros enteros positivos, encontrar combinacin de ellos que mediante sumas o
restas totalicen exactamente un valor objetivo Z. El programa debe de tener como entrada
los n nmeros y el objetivo Z; la salida ha de ser la combinacin de nmeros con el opera-
dor que le corresponde.
Tener en cuenta que pueden formar parte de la combinacin los n nmeros o parte de
ellos.
9.10. Dados n nmeros, encontrar combinacin con sumas o restas que ms se aproxime a un
objetivo Z. La aproximacin puede ser por defecto o por exceso. La entrada son los n n-
meros y el objetivo y la salida la combinacin ms prxima al objetivo.
9.11. Dados n nmeros encontrar, si existe, la combinacin con los n nmeros que mediante
sumas o restas totalice exactamente el objetivo Z.
9.12. Dados n nmeros, encontrar la combinacin con los n nmeros que mediante sumas o res-
tas ms se aproxime a el objetivo Z.
9.13. Un laberinto podemos emularlo con una matriz n x n en la que los pasos libres estn repre-
sentados por un carcter (el blanco, por ejemplo) y los muros por otro carcter (el # por
ejemplo). Escribir un programa en el que se genere aleatoriamente un laberinto, se pida las
coordenadas de entrada (la fila ser la 1), las coordenadas de salida (la fila ser la n) y
encontrar todas las rutas que nos llevan de la entrada a la salida.
9.14. Realizar las modificaciones necesarias en el problema del laberinto 9.12 para encontrar
la ruta ms corta. Considerando ruta ms corta la que pasa por un menor nmero de ca-
sillas.
9.15. Una regin castellana est formada por n pueblos dispersos. Hay conexiones directas entre
algunos de estos pueblos y entre otros no existe conexin aunque puede haber un camino.
Escribir un programa que tenga como entrada la matriz que representa las conexiones di-
rectas entre pueblos, de tal forma que el elemento M(i,j) de la matriz sea:
o si no hay conexin directa entre pueblo i y pueblo j.
M(i,j) =
d hay conexin entre pueblo i y pueblo) de distancia d.
Tambin tenga como entrada un par de pueblos (x,y) y encuentre un camino entre ambos
pueblos utilizando tcnicas recursivas. La salida ha de ser la ruta que se ha de seguir para ir
de x a Y junto a la distancia de la ruta.
9.16. En el programa escrito en 9.14, hacer las modificaciones necesarias para encontrar todos
los caminos posibles entre el par de pueblos (x,y).
9.17. Referente al problema 9.14, escribir un programa que genere una matriz P de n x n en la
que cada elemento P(i,j) contiene el camino ms corto entre el pueblo i y el pueblo j. Utili-
, . , . .
zar umcamente tecmcas recursIvas.
9.18. El celebre presidiario Seor S quiere fugarse de la crcel de Carabanchel, por el sistema de
alcantarillado, pero tiene dos problemas:

0 - __________________
310 Estructura de datos
1) El dimetro de la bola que arrastra es de 50 cm, resulta demasiado grande para pasar
por algunos pasillos.
2) Los pasillos que comunican unas alcantarillas con otras tienen demasiada pendiente y
slo puede circular por ellos en un sentido.
Ha conseguido hacerse con los planos que le indican el dimetro de salida de las al-
cantarillas, as como el dimetro de los pasillos y el sentido de la pendiente que lo
conectan.
Suponiendo que:
1) El Nmero de alcantarillas es N.
2) El Seor S se encuentra inicialmente en la alcantarilla 1 (dentro de la prisin).
3) Todas las alcantarillas (excepto la 1) tienen su salida fuera de la prisin, si bien puede
que sean demasiado estrechas para sacar la bola fuera.
4) Se puede pasar de un pasillo a otro a travs de las alcantarillas estrechas aunque a
travs de dichas alcantarillas no se pueda salir al exterior.
5) Todos los pasillos tienen un dimetro, si bien ste puede ser demasiado estrecho para
poder pasar con la bola.
Escribir un programa que contenga al menos estos procedimientos:
a) Un procedimiento para generar aleatoriamente los dimetros de los tneles del alcanta-
rillado as como los dimetros de salida de las distintas alcantarillas. (Tenga en cuenta
que si se puede ir de la alcantarilla i a la j por el tnel, entonces no se puede ir por el
tnel desde j hasta i.)
b) Un procedimiento de backtraking que resuelva el problema del seor S.
e) Procedimientos para escribir en pantalla el sistema de conexiones as como la posible
solucn encontrada.
.
.
[
,
CAPITULO

o es In arios

10.1. Concepto de rbol.

10.2. Arboles binarios.

10.3. Arboles de expresin.
10.4. Construccin de un rbol binario.
10.5. Recorrido de un rbol.
10.6. Aplicacin de rboles binarios: evaluacin de expresiones.

10.7. Arbol binario de bsqueda.
10.8. Operaciones con rboles binarios de bsqueda.
RESUMEN.
EJERCICIOS.
PROBLEMAS.
REFERENCIAS BIBLIOGRFICAS.
En este captulo se centra la atencin sobre una estructura de datos, el
rbol, cuyo uso est muy extendido y es muy til en numerosas aplica-
ciones. Se definen formas de esta estructura de datos (rboles genera-
les, rboles binarios y rboles binarios de bsqueda) y cmo se pueden
representar en Pascal, as como el mtodo para su aplicacin en la re-
solucin de una amplia variedad de problemas. Al igual que ha sucedi-
do anteriormente con las listas, los rboles se tratan principalmente
como estructura de datos en lugar de como tipos de datos. Es decir, nos
centraremos principalmente en los algoritmos e implementaciones en
lugar de en definiciones matemticas.
Los rboles junto con los grafos constituyen estructuras de datos no
lineales. Las listas enlazadas tienen grandes ventajas o flexibilidad sobre
la representacin contigua de estructura de datos (los arrays), pero tienen
una gran debilidad: son listas secuenciales; es decir, estn dispuestas de
modo que es necesario moverse a travs de ellas, una posicin cada vez.
311
.

,
!
0,

,
o o _____ __ __ ..,
312 Estructura de datos
Los rboles superan estas desventajas utilizando los mtodos de pun-
teros y listas enlazadas para su implementacin. Las estructuras de datos
organizadas como rboles sern muy valiosas en una gama grande de
aplicaciones, sobre todo problemas de recuperacin de informacin .

10.1. CONCEPTO DE ARBOL
Un rbol (en ingls, tree) es una estructura que organiza sus elementos, denominados
nodos, formando jerarquas. Los cientficos utilizan los rboles generales para represen-
tar relaciones. Fundamentalmente, la relacin clave es la de <<padre-hijo entre los nodos
del rbol. Si existe una arista (rama) dirigida del nodo n al nodo m, entonces n es el
padre de m y m es un hijo de n. En el rbol de la Figura 10.1, los nodos B y C son hijos
del nodoA. Los hijos del mismo padre se llaman hermanos, por ejemplo B y C. Cada nodo
de un rbol tiene al menos un padre, y existe un nico nodo, denominado raz del rbol,
que no tiene padre. El nodo A es el raz del rbol de la Figura 10.1. Un nodo que no tiene
hijos se llama hoja del rbol. Las hojas del rbol de la Figura 10.1 son C, D, E Y F.
, ' "
.
. ". hola
La relacin padre-hijo entre los nodos se generaliza en las relaciones ascendiente
(antecesor) y descendiente. En la Figura 10.1 A es un antecesor de D, y por consiguien-
te D es un descendiente de A. Obsrvese que no todos los nodos estn relacionados por
las relaciones ascendente/descendiente: B y C, por ejemplo, no estn relacionados. Sin
embargo, el raz de cualquier rbol es un ascendiente de todos los nodos de ese rbol. Un
subrbol de un rbol es cualquier nodo del rbol junto con todos sus descendientes.
Un subrbol de un nodo n es un subrbol enraizado en un hijo de n. Por ejemplo, la
Figura 10.2 muestra un subrbol de la Figura 10.1. Este subrbol tiene a B como su raz
y es un subrbol del nodo A.
A Padre
A
B, e hijos del nodo A
D, E, F hijos del nodo B
D F
B, e hermanos

Figura 10.1. Arbol general.

i
,
,
.
,
,-
,
,

-
. , _.-
rboles binarios 313
o
Figura 10.2. Un subrbol del rbol de la Figura 10.1.
Debido a la naturaleza jerrquica de los rboles, se puede utilizar para representar en
formacin que sea jerrquica por naturaleza, por ejemplo, diagramas de organizaciones,
rboles genealgicos, rboles de especies animales, etc.
Terminologa complementaria
Adems de los trminos ya citados anteriormente, existen otros tambin de gran impor-
tancia.
Camino
Longitud del camino
Altura del rbol
I
Nivel (profundidad)
Grado (aridad)
Hermanos
Una secuencia de nodos conectados dentro de un rbol.
Es el nmero de nodos menos uno (r - 1). Si r > 0, se dice que
el camino es propio.
Es el nivel ms alto del rbol. La altura es igual a la longitud del
camino desde el nodo raz a la hoja ms lejana que sea alcanza-
ble desde l. Por ejemplo, la altura del rbol de la Figura 10.3
es 4. Un rbol que contiene slo un raz, tiene de altura l.
De un rbol (levelo depth), es el nmero de nodos que se
encuentra entre l y la raz. El nodo Luis Carchelejo est en el
nivel 3. Por definicin el nmero de niveles de un rbol se
define como el nivel de la hoja ms profunda; as, el nmero de
niveles del rbol de la Figura 10.3 es 4. Observemos que por
definicin, el nmero de niveles de un rbol es igual a la altu-
ra por lo que pueden usarse ambas magnitudes indistintamente.
Es el nmero de hijos del nodo. La aridad de un rbol se defi-
ne como el mximo de la aridad de sus nodos.
Dos nodos son hermanos si tienen el mismo padre. Se llamarn
hermano izquierdo de n y hermano derecho de n, respectiva-
mente.
Un tipo especial de rbol es el denominado rbol binario y un rbol binario espec-
fico de gran utilidad es el rbol binario de bsqueda.
1 Las definiciones de altura, profundidad y nivel, como se seala en [Franch 93], pg. 220, son contra-
dictorias en algunos textos, que no definen algunos de estos conceptos o los definen slo para un rbol y no
para sus nodos; o bien empiezan a numerar a partir del cero y no del nodo, etc. En nuestro caso y al igual
que hace Franch preferimos numerar a partir del uno para que el rbol vaCo tenga una altura diferente al
rbol con un nico nodo.


,
,


314 Estructura de datos
Micaela
Graciela
Luis
(Carchelejo)
Victoria
Luis y Juana

Lucas
Luis
(Madrid)
Figura 10.3. Arbol genealgico.
10.2. RBOLES BINARIOS
Mara
Juana Mara
Un rbol binario es un rbol en el que cada nodo no puede tener ms de dos hijos o
descendientes.
En particular, un rbol binario es un conjunto de nodos que es, o bien el conjunto
vaco, o un conjunto que consta de un nodo raz enlazado a dos rboles binarios disjuntos
denominados subrbol izquierdo y subrbol derecho. Cada uno de estos subrboles
es, a su vez, un rbol binario. La Figura 10.4 muestra diversos ejemplos de rboles binarios.
A
B
B C B
E
D H
(a) (b) (e)
Figura 10.4. Diversos tipos de rboles binarios .

,
--

rboles binarios 315
10.2.1. Terminologa
En un rbol binario los hijos se conocen como hijo izquierdo e hijo derecho, lo que
supone automticamente una diferencia. Los dos rboles de la Figura 10.5 no represen-
tan el mismo rbol binario, ya que sus hijos izquierdo y derecho estn en orden inverso.
Un nodo que no tiene hijos se denomina hoja.
Por consiguiente, los nodos H, r, E, F Y J son hojas en el rbol de la Figura 1O.4-b.
Los nodos con descendientes se denominan nodos interiores.
El nodo raz se dice que est en el nivel 1 en el rbol, los nodos B y e estn en el
nivel 2, y los nodos D, E, F Y G estn en el nivel 3. La altura del rbol se define como el
nivel ms alto del rbol. Por consiguiente, la altura del rbol (b) de la Figura 10.4 es 4.
Cualquier nodo sin sucesores se denomina un nodo terminal. Por ejemplo, los no-
dos H, r, E, F, J son todos hojas o nodos terminales, en el rbol 10.4 (b).
En la Figura 10.7, los nodos B, D Y E forman el subrbol izquierdo. De modo similar
C, F y G forlllan el subrbol derecho. Cada uno de estos subrboles es un verdadero
rbol.
Los subrboles izquierdo y derecho de un rbol binario deben ser subconjuntos disjun-
tos de nodos. Esto es, ningn nodo puede estar en ambos subrboles.
1 1
2 3 3 2
Figura 10.5. rboles binarios distintos.
D
Padre
Hijo izquierdo H J Hijo derecho
Figura 10.6. Padre e hijos de un rbol binario.

,
I
,
,
,
,
,
I

,
,
,
j
,
,

.- ...... _ - -------
316 Estructura de datos
A
Subrbol izquierdo Subrbol derecho
B e
o E
F G
Figura 10.7. Subrboles de un rbol binario.
La definicin de rbol conlleva el hecho de que un rbol binario es un tipo de estruc-
tura de datos recursiva. Esto es, cada subrbol se define como un rbol ms simple. La
naturaleza recursiva del rbol binario ayuda a simplificar la operacin con rboles binarios.
Un rbol binario lleno es aquel en el que cada nodo tiene o dos hijos o ninguno si es
una hoja. La Figura 10.8 (a) muestra un rbol binario lleno y, sin embargo, la Fi-
gura 10.8 (b) representa un rbol binario no lleno pero s completo (se define posterior-
mente).
10.2.2. Nivel de un nodo y altura de un rbol
El nivelo profundidad de un nodo se define como una cantidad mayor en uno al nme-
ro de sus ascendientes. As, suponiendo el nivel de nodo n:
Si n es la raz de un rbol T, entonces est en el nivel 1.
Si n no es la raz de T, entonces su nivel es mayor que el nivel de su padre.
Por ejemplo, en la Figura 10.9

A A
B e B e
o E F G o E I
(a) (b)
Figura 10.8. rbol binario: (a) completo; (b) no completo.


, ,
rboles binarios 317
A
nodo A est en nivel 1
nodo B est en nivel 2
B c
nodo D est en nivel 3
D E F G
Figura 10.9. rbol binario con diferentes niveles.
La altura de un rbol es el nmero de nodos en el camino ms largo desde la raz
a una hoja; dicho de otro modo, la altura de un rbol es el nmero de niveles distintos.
As, en un rbol general T, en trminos de los niveles de sus nodos se define como

sigue:
Si T es vaco, entonces la altura es O.
Si T no es vaco, entonces su altura es igual al nivel mximo de sus nodos.
Los rboles de la Figura 10.10 tienen por altura 3, 4 Y 6.
A
B
c_
(a)
(b)
(e)
Figura 10.10. rboles binarios con los mismos nodos pero alturas diferentes.
,
,
I
,
;

318 Estructura de datos


Definicin recursiva de altura
Si T est vaco, su altura es O
Si T no es un rbol binario vaco, entonces debido a que T es de la forma
La altura de T se puede definir como:
altura (T) = 1 + max [altura (TI)' altura (T
D
)]
,
10.2.3. Arboles binario, lleno y completo
Un rbol binario lleno de altura h tiene todas sus hojas a nivel h y todos los nodos que
estn a nivel menor que h tiene cada uno dos hijos. La Figura 10.11 representa un rbol
binario lleno de altura 3.
Se puede dar una definicin recursiva de rbol binario lleno:
Si T est vaco, entonces T es un rbol binario lleno de altura O.
Si no est vaco y tiene altura h > 0, entonces T es un rbol binario lleno si los
subrboles de la raz son ambos rboles binarios llenos de altura h - 1.
Un rbol binario completo de altura h es un rbol binario que est relJeno a partir
del nivel h - 1, con el nivel h relleno de izquierda a derecha (Figura 10.12). Ms formal-
mente, un rbol binario de altura h es completo si:
Todos los nodos de nivel h - 2 Y superiores tienen dos hijos cada uno.
Cuando un nodo tiene un descendiente derecho a nivel h, todas las hojas de su
subrbol izquierdo estn a nivel h .

Figura 10.11. Arbol binario lleno de altura 3.
rboles binarios 319


;

Figura 10. 12. rbol binario completo.
Un rbol binario es completamente (totalmente) equilibrado si los subrboles izquierdo
y derecho de cada nodo tienen la misma altura. .
(d)
(a) (b) (e)
Figura 10.13.
,
Arbol binario: (a) equilibrado, (b) completamente equilibrado;
(e) y (d) rboles no equilibrados.

,
,

,
1

I
I
320 Estructura de datos
10.2.4. Recorrido de un rbol binario
El proceso u operacin de acceder o visitar a todos los nodos (datos) de un rbol se
conoce normalmente como recorrido de un rbol. El rbol puede ser recorrido en va-
rios rdenes. Los tres recorridos ms tpicos se clasifican de acuerdo al momento en que
se visita su raz en relacin con la visita a sus subrboles.
recorrido preorden
l. Visitar el raz
2. Ir a subrbol izquierdo
3. Ir a subrbol derecho
,
recorrido enorden
l. Ir a subrbol izquierdo
2. Visitar el raz
3. Ir a subrbol derecho
. - - -
", '"
, ,.',,;', .
-_._.- -': '
.. : ... _.- ,
:,. ::_---,--- -
.': .. : ' : ,". , .. .. .. .
recorrido postorden
l. Ir a subrbol izquierdo
2. Ir a subrbol derecho
3. Visitar el raz
En el rbol de la Figura 10.14 los posibles recorridos pueden ser:
Recorrido preorden visita los nodos en el orden GDBACEFKHJIML.
Recorrido enorden visita los nodos en el orden ABCDEFGIJHKLM.
Recorrido postorden visita los nodos en el orden ACBFEDIJHLMKG.
10.3. RBOLES DE EXPRESiN
Los rboles binarios se utilizan para representar expresiones en memoria; esencialmente,
en compiladores de lenguaje de programacin. La Figura 10.15 muestra un rbol binario
de expresiones para la expresin aritmtica (a + b) * c.
G
o K
B E
H M
J
L
A e F
I

Figura 10.14. Arbol binario.

' .

~
,
,
l
,
,

1
,
,

l
1

>1
,
,
I
l
,j
1
A
,
",
,

..
,

.
,

Arboles binarios 321

+ e
A B
Figura 10.15. rbol binario de expresiones que representa (A + B) C.
Obsrvese que los parntesis no se almacenan en el rbol pero estn implicados en la
forma del rbol. Si se supone que todos los operadores tienen dos operandos, se puede
representar una expresin por un rbol binario cuya raz contiene un operador y cuyos
subrboles izquierdo y derecho son los operandos izquierdo y derecho, respectivamente,
cada operando puede ser una letra (x , Y, A, B, etc.) o una subexpresin representada como
un subrbol. En la Figura 10.16 se puede ver cmo el operador que est en la raz es *,
su subrbol izquierdo representa la subexpresin (x + y ) y su subrbol derecho repre-
senta la subexpresin (A - B). El nodo raz del subrbol izquierdo contiene el opera-
dor (+) de la subexpresin izquierda y el nodo raz del subrbol derecho contiene el
operador (-) de la subexpresin derecha. Todos los operandos letras se almacenan en
nodos hojas.
Utilizando el razonamiento anterior, se puede escribir la expresin almacenada como
(x + Y) * (A-B)
en donde se han insertado parntesis alrededor de subexpresiones del rbol. En la Fi-
gura 10.17 aparece el rbol de la expresin [x + (Y * Z)] * (A- B).
EJEMPLO 10.1
Deducir las expresiones que representan los siguientes rboles binarios
+

A e
y
B
A

z
(a) (e)
(b)

322 Estructura de datos

+ -
x
y
A B
,
Figura 10.16. Arbol de expresin (x+y) * (A - B) .
Solucin
a) X* (Y / - Z )
b) A+ [( B *-(C+D)]
e) [A* ( X+Y) J * C
EJEMPLO 10.2
Dibujar la representacin en rbol binario de cada una de las siguientes expresiones
a) X *Y / [ (A+B) * C ]
b) (X*Y l A) + ( B* C)
Solucin
e
B
e
A B
y
(a) (b)
, ,
10.4. CONSTRUCCION DE UN ARBOL BINARIO
Los rboles binarios se construyen de igual forma que las listas enlazadas, utilizando
diferentes elementos con la misma estructura bsica. Esta estructura bsica es un nodo
_ _ _ o __ ~ _ ~ ___ _
, ..."
Arboles binarios 323


+
-
x

A B
y
z
,
Figura 10.17. Arbol de expresin [x+ ( y*Z) 1 * (A-B).
con un espacio de almacenamiento para datos y enlaces para sus hijos izquierdo y
derecho. Existe una diferencia clara con las listas y es el enlace de los nodos; esto se
debe a que el rbol es bidimensional, tiene una estructura de registro ms compleja
y tiene muchos punteros ni 1 frente a uno solo que aparece al final de una lista en-
lazada.
Con este formato cada nodo tiene tres elementos: datos, un puntero izquierdo y un
puntero derecho. Los punteros son otros nodos que llevan a declaraciones muy similares
a las de una lista enlazada.
type
Pt rAr bo l = ANodoArbol
NodoArbol = record
Da to s:NombreTipo;
Izda, Dcha: PtrArbo l; ( p unteros a hi j os )
end; (Nodo Ar bo l )
Aadir una hoja
Dada esta definicin, un rbol se puede construir mediante llamadas sucesivas a new,
cada una de las cuales asigna un nodo nuevo al rbol.
La implementacin de un rbol binario comienza disponiendo al principio de una
variable puntero externo T que apunta a la raz del rbol. Si el rbol est vaco, T es
nil. La Figura 10.18 ilustra esta implementacin. La definicin recursiva de un rbol
binario conduce a que cada rbol binario no vaco conste de un subrbol izquierdo y un
subrbol derecho, cada uno de los cuales es un rbol binario. AS, si T apunta a la raz de
un rbol binario, entonces T " . 1 z do apunta a la raz del subrbol izquierdo y T " . De ho
apunta a la raz del subrbol derecho.
,
324 Estructura de datos
T
Nombre
Izdo. Ocho .



Figura 10.18. Implementacin de un rbol binario.
El procedimiento para crear una hoja de un rbol y una funcin que comprueba si un
nodo es una hoja se muestran a continuacin:
procedure NuevaHoj a (var Nuev o lt e mP t r : Pt r Arbo l ; Num : NombreTi po) ;
begin
new (NuevoltemPt r ) ;
Nuevo ltemP t rA .Da t os : = Num;
Nuevolt emPt rA . lzdo := n i l ' ,
Nu evo lt emPtrA . Dcho := n i l;
end {NuevaHoja}
function Es Hoja (unNodo : Pt rArbol) : boolean ;
begin
if unNodo = n i l then
Es Hoja : = fa l se ;
elBe
EsHo j a : =(unNodo A.lzdo - n il ) and (unNod oA.Dc ho = nil) ;
end; {Es Hoja }
,
10.5. RECORRIDO DE UN ARBOL
Para visualizar o consultar los datos almacenados en un rbol se necesita recorrer el
rbol o visitar los nodos del mismo. Al contrario que las listas enlazadas, los rboles
binarios no tienen realmente un primer valor, un segundo valor, tercer valor, etc. Se pue-
de afirmar que el raz viene el primero, pero quin viene a continuacin? Existen di fe-
rboles binarios 325
rentes mtodos de recorrido de rbol, como ya se coment en el apartado 10.2. La mayo-
ra de las aplicaciones binarias son bastante sensibles al orden en el que se visitan los
nodos, de forma que ser preciso elegir cuidadosamente el tipo de recorrido.
El recorrido de un rbol supone visitar cada nodo slo una vez. Las tres etapas
bsicas en el recorrido de un rbol binario recursivamente son:
l. Visitar el nodo (N)
2. Recorrer el subrbol izquierdo (I)
3. Recorrer el subrbol derecho (D)
Segn sea la estrategia a seguir, los recorridos se conocen como enorden (inorder),
preorden (preorder) y postorden (postorder)
preorden (nodo-izdo-dcho) (NID)
enorden (izdo-nodo-dcho) (IND)
postorden (izdo-dcho-nodo) (IDN)
10.5.1. Recorrido enorden
Si el rbol no est vaco, el mtodo implica los siguientes pasos:
l. Recorrer el subrbol izquierdo (1).
2. Visitar el nodo raz (N).
3. Recorrer el subrbol derecho (D).
El algoritmo correspondiente es
Eno rden(A)
Si el arbo l no
inicio

e st a v c ~ o entonces
Recorrer el suba r bol izquierdo
visitar el nodo raiz
Re correr el subarbol d er echo
fin
En el rbol de la Figura 10.19, los nodos se han numerado en el orden en que son
visitados durante el recorrido enorden. El primer subrbol recorrido es el subrbol iz-
quierdo del nodo raz (rbol cuyo nodo contiene la letra B. Este subrbol consta de los
nodos B, D Y E Y es a su vez otro rbol con el nodo B como raz, por lo que siguiendo el
orden IND, se visita primero D, a continuacin B (nodo o raz) y por ltimo E (derecha).
Despus de la visita a este subrbol izquierdo se visita .el nodo raz A y por ltimo se
visita el subrbol derecho que consta de los nodos C, F y G. A continuacin, siguiendo el
orden I ND para el subrbol derecho, se visita primero F, despus C (nodo o raz) y por
ltimo G. Por consiguiente, el orden del recorrido de la Figura 10.19 es D-B-E-A-F-C-G.



I
!
,
1

I
I

,
326 Estructura de datos
D
1
S
2
A
4
E
3
Visita de los nodos: D, S, E, A, F, e, G
e
6
F G
5 7
Figura 10.19. Recorrido enorden de un rbol binario.
10.5.2. Recorrido preorden
El recorrido preorden (NID) conlleva los siguientes pasos:
l. Visitar el raz (N).
2. Recorrer el subrbol izquierdo (1).
3. Recorrer el subrbol derecho (D).
El algoritmo recursivo correspondiente es:
si T no es va c i o entonces
inicio
fin
ver los datos e n el r a iz de T
preorden (subarbo l izq uierdo del rai z d e T)
preorden (subarb o l de re c ho del raiz de T)
Si utilizamos el recorrido preorden del rbol de la Figura 10.20 se visita primero el
raz (nodo A). A continuacin se visita el subrbol A, que consta de los nodos B, O Y E.
Dado que el subrbol es a su vez un rbol, se visitan los nodos utilizando el orden NIO.
Por consiguiente, se visita primero el nodo B, despus O (izquierdo) y por ltimo E
(derecho).
A continuacin se visita subrbol derecho de A, que es un rbol que contiene los
nodos C, F y G. De nuevo siguiendo el orden NIO, se visita primero el nodo C, a conti-
nuacin F (izquierdo) y por ltimo G (derecho). En consecuencia, el orden del recorrido
preorden para el rbol de la Figura 10.20 es A-B-O-E-C-F-G.
10.5.3. Recorrido postorden
El recorrido postorden (IDN) realiza los pasos siguientes:
l.
2.
3.
Recorrer el subrbol izquierdo (1).

Recorrer el subrbol derecho (D).
Visitar el raz (N).
rboles binarios 327
A
1
Visita los nodos: A-B-D-E-C-F-G
B C
2 5
o E F G
3 4 6 7
Figura 10.20. Recorrido preorden de un rbol binario.
El algoritmo recursivo es
si A no es ta y ac io entonces

~ n ~ ~ o
fin
Postorde n ( s ubarbol izqu i e rdo del ra iz de A)
Postorde n (suba r bol derecho del raiz de A)
Vi sua l i zar l os datos de l r a i z de A
Si se utiliza el recorrido postorden del rbol de la Figura 10.21, se visita primero el
subrbol izquierdo A. Este subrbol consta de los nodos B, D Y E Y siguiendo el orden
IDN, se visitar primero D (izquierdo), luego E (derecho) y por ltimo B (nodo). A con-
tinuacin se visita el subrbol derecho A que consta de los nodos C, F y G. Siguiendo el
orden 1 DN para este rbol , se visita primero F (izquierdo), despus G (derecho) y por
ltimo C (nodo). Finalmente se visita el raz A (nodo). AS , el orden del recorrido postor-
den del rbol de la Figura 10.21 es D-E-B- F-G-C- A.
A
7
B
3
o E
1 2
F
4
Visita los nodos D-E-B-F-G-C-A
C
6
G
5
Figura 10.21. Recorrido postorden de un rbol binario.
I
I
I




328 Estructura de datos
EJEMPLO 10.3
Deducir los tres recorridos del rbol binario siguiente:
Solucin
Preorden
Enorden
Postorden

E
A
:MEAGZPQ
:AEGMPQZ
:AGEQPZM
M
G
(NID)
( IND)
( IDN)
z
p
.." ..... , ... _-------
Q
10.5.4. Implementacin de los algoritmos de recorrido
Los mtodos utnizados para recorrer un rbol binario son recursivos y por lo tanto se
emplearn procedimientos recursivos para implementar los recorridos. Un rbol se re-
presenta utilizando las siguientes sentencias Pascal:
const LongMax = 30 (longitud mxima del nombre)
type NombreTipo = string [LongMaxl ;
ptrTipo =
nodoTipo - record
Nombre:nombreTipo;
Hijolzdo:ptrTipo;
HijoDcho:ptrTipo
end;
TipoArbo lBin = ptrTipo;
(puntero a Hijo izquierdo )
(puntero a Hij o derecho )
var A : TipoArbolBin; ( puntero a raz del rbol)
,
j
,
,
;
)

Por ejemplo el procedimiento EnOrden puede ser:


procedure EnOrden (A : TipoArbolBin);
begin
end;
if A < > nil then {rbol no esta vaco}
begin
EnOrden (AA.Hij o lzdo); {operacin I}
WriteLn (AA.Nombre); {operacin N}
EnOrden (AA. HijoDcho); {operacin D}
end;
rboles binarios 329

La implementacin de los recorridos preorden y postorden se realiza siguiendo el
esquema algortmico de los apartados 10.5.2 y 10.5.3, respectivamente.
10.6. APLICACiN DE RBOLES BINARIOS:
EVALUACiN DE EXPRESIONES
Una expresin aritmtica est formada por operandos y operadores aritmticos. As, la
. ,
expreSlOn
R =(A+B)*D+A*B/ D
R est escrita de la forma habitual, el operador en medio de los operando, se conoce
como notacin infija. Recordemos que ya hemos realizado la aplicacin de evaluar una
expresin utilizando nicamente el T AD pila. Ahora va a ser utilizada tanto las pilas
como el T AD rbol binario para la evaluacin. La pila ser utilizada para pasar la expre-
sin de infija a postfija. La expresin en postfija ser almacenada en el rbol para que la
evaluacin se realice utilizando el rbol binario. En primer lugar, recordamos la priori-
dad de operadores, de mayor a menor:
, .
( ) ParenteslS



A
Potencla


Multipl / divisin

*
/ I
Suma / Resta

+ ,
-

A igualdad de precedencia son evaluados de izquierda a derecha.
10.6.1. Notacin postfija: notacin polaca
La forma habitual de escribir operaciones aritmticas es situando el operador entre sus
dos operandos, la llamada notacin infija. Esta forma de notacin obliga en muchas oca-
siones a utilizar parntesis para indicar el orden de evaluacin.
A*B / (A+C) A*B / A+ C
Representan distintas expresiones al no poner parntesis. Igual ocurre con las expre-

SlOnes:

..
..
..


I
..
,
..
..
i
..
..
,
:
..
!
..
!
..
330 Estructura de datos
La notacin en la que el operador se coloca delante de los dos operandos, notacin
prefija, se conoce como notacin polaca (en honor del matemtico polaco que la estudi).
A*B / (A+C) (infija) ~ A*B / +AC ~ *AB / +AC ~ / *AB+AC (polaca)
A*B / A+C (infija) ~ *AB/A+C ~ / *ABA+C ~ + / *ABAC (polaca)
(A-B) ~ C D (infija ) ~ - A B ~ C D ~ ~ - A B C D ~ ~ - A B C D (polaca)
Podemos observar que no es necesario la utilizacin de parntesis al escribir la
expresin en notacin polaca. Es la propiedad fundamental de la notacin polaca, el
orden en que se van a realizar las operaciones est determinado por las posiciones de los
operadores y los operandos en la expresin.
Hay ms formas de escribir las operaciones. As, la notacin postfija o polaca inver-
sa coloca el operador a continuacin de sus dos operandos.
A*B /( A+C) (infija) ~ A*B / AC+ ~ AB* / AC+ ~ AB*AC+ /
A*B / A+C (infija) ~ AB* /A+C ~ AB*A/+C AB*A/ C+
(A-B) ~ C D (infija) ~ AB - ~ C D A B - C ~ D ~ A B - C ~ D
10.6.2. rbol de expresin
(polaca inversa)
(polaca inversa)
(polaca inversa)
Una vez que se tiene la expresin en postfija la formacin del rbol binario es fcil: se
crean dos nodos del rbol con respectivos operandos que se enlazan como rama izquier-
da y rama derecha del nodo operador. As, la expresin A * B - C * D + H se transforma en
postfija: AB*CD*-H+ y el rbol de la expresin:
+
-
H
* *
A B
e D
Pasos a seguir
A la hora de evaluar una expresin aritmtica en notacin infija se siguen estos pasos:
l. Transformar la expresin de infija a postfija.
2. Formar a partir de la expresin en postfija el rbol de expresin.
3. Evaluar la expresin utilizando el rbol.
..
..


..
..
..
..
..
,
,
;,
,
.
'O"
rboles binarios 331
En el algoritmo para resolver el primer paso se utiliza una pila de caracteres. Para el
segundo paso se utiliza otra pila y el rbol de caracteres. Y en el tercer paso un vector
con los valores numricos de los operandos que es utilizado para evaluar la expresin en
el rbol.
10.6.3. Transformacin de expresin infija a postfija
.
Partimos de una expresin en notacin infija que tiene operandos, operadores y puede
tener parntesis. Los operandos vienen representados por letras, los operadores van a ser:
A (potenciacin), *, /, +, _ .
La transformacin se realiza utilizando una pila en la que se almacenan los operado-
res y los parntesis izquierdos. Esta transformacin puede verse en el captulo de Pilas,
apartado 7.4, Evaluacin de expresiones mediante Pilas.
10.6.4. Creacin de un rbol a partir de la expresin en postfija
El rbol se forma de tal manera que en la raz se encuentra el operador, en el subrbol
izquierdo y derecho los operandos. En una pila se guardan las direcciones de los nodos
que contienen a los operandos. Cuando se va a formar el nodo de un operador, se saca
de la pila los dos ltimos nodos metidos para formar el nodo operador enlazando la
rama izquierda y la derecha con las direcciones de los nodos que se han sacado de la
pila.
La unidad que encapsula el TAD pila necesario para guardar las direcciones de los
nodos del rbol, tambin define los tipos necesarios para manejar el rbol. Esto es as
porque el campo Info de los elementos de la pila es PtrA (puntero a nodos del rbol).
A continuacin se escribe la interfaz de la unidad pila. La seccin de definicin est ya
escrita anteriormente.
unit Pilaptr;
interface
type
PtrA = ANodoAb;
NodoAb = record
e : char;
Izqdo,
Drcho : PtrA
end;
Plaptr = ANodopt;
Nodopt = record
end;
Info: PtrA;
Sgte: Plaptr

,
,
i
i
I



332 Estructura de datos
function pvacia(P; Plaptr ); boolean;
procedure Pcrear(var P; Plaptr );
procedure Pmeter(D; PtrA; var P; Plaptr);
procedure Psacar(var D; PtrA; var P; Plaptr);
function Pcima (P:Plapt r); PtrA; {devuelve el elemento cima de la pila}
procedure Pborrar(var P: Plaptr);
implementation

end.
El siguiente procedimiento genera el rbol de expresin a partir del vector de regis-
tros que contiene la expresin en postfija.
procedure ArbolExpresion(var Ar;Tag; J:integer; var R;PtrA);
var {el tipo Tag est definido en la unidad ExpPost}
1: integer;
P: Pilaptr;
Al, A2, A3: PtrA;
procedure Crearnodo( 1z: PtrA; 1nf:char; Dr:PtrA; var A:PtrA);
begin
new(A) ;
AA.C ;= 1nf;
AA.1zqdo ;= 1z;
AA.Drcho := Dr
endl
begin
Pcrear(P);
for 1:= 1 to J do
if not Ar[I] .Oprdor then
begin
end
Crearnodo(nil, Ar[1].C, nil, A3);
Pmeter(A3, P)
elBe begin
Psacar(A2, P);
Psacar(Al, P);
end;
Crearnodo(Al, Ar[1] .C, A2, A3);
Pmeter(A3, P)
Psacar (A3, P); {Devuelve el rbol con la expresin}
R:= A3
end;
10.6.5. Evaluacin de la expresin en postfija
La primera accin que se va a realizar es dar valores numricos a los operandos. Una
vez que tenemos los valores de los operandos, la expresin es evaluada. El algoritmo de
evaluacin recorre el rbol con la expresin en postorden. De esta forma se evala pri-
mer operando (rama izquierda), segundo operando (rama derecha) y segn el operador
(raz) se obtiene el resultado.
Es en la unidad ExpPost donde est definido el tipo de los Oprdos para as poder
i'
,
rboles binarios 335
queda, debido a que se pueden buscar en ellos un trmino utilizando un algoritmo de
bsqueda binaria similar al empleado en arrays.
Un rbol binario de bsqueda es aquel que dado un nodo, todos los datos del sub-
rbol izquierdo son menores que los datos de ese nodo, mientras que todos los datos del
subrbol derecho son mayores que los datos del nodo. Por consiguiente, este rbol no es
un rbol binario de bsqueda,
4
,
9 5
6
ya que 9 no es menor que 4. Sin embargo, el siguiente rbol s es binario de bsqueda.
4
EJEMPLO 10.4

Arbol binario de bsqueda
55
30
4 41
6
5
75
9
4 menor que 30
30 menor que 55
41 mayor que 30
75 mayor que 55
85 mayor que 75
85
r
I
,
,
,
,
,
,
,
,



336 Estructura de datos
10.7.1. Creacin de un rbol binario
Supongamos que se desea almacenar los nmeros
8 3 1 20 10 5 4
en un rbol binario de bsqueda. Siguiendo la regla, dado un nodo en el rbol todos los
datos a su izquierda deben ser menores que todos los datos del nodo actual, mientras que
todos los datos a la derecha deben ser mayores que dichos datos. Inicialmente el rbol
est vaco y se desea insertar el 8. La nica eleccin es almacenar el 8 en el raz:
8
A continuacin viene el 3. Ya que 3 es menor que 8, el 3 debe ir en el subrbol
izquierdo
8
3
A continuacin se ha de insertar 1, que es menor que 8 y que 3, por consiguiente ir
a la izquierda y debajo de 3.
8
3
1
El siguiente nmero es 20, mayor que 8, lo que implica debe ir a la derecha de 8 .

;




!
,
rboles binarios 337
8
3
20
1
Cada nuevo elemento se inserta como una hoja del rbol. Los restantes elementos se
pueden situar fcilmente.
8
3
20
8
1
10
3
20
8
1 5 10
3
20
1 5 10
4





I

i
,
!




,

338 Estructura de datos
Una propiedad de los rboles binarios de bsqueda es que no son nicos para los
datos dados .
EJEMPLO 10.5
Construir un rbol binario para almacenar los datos 12, 8, 7, 16 Y 11.
Solucin
12
8
16
7 11
PROBLEMA 10.1 2
Este programa genera un rbol binario de nmeros enteros con un nmero aleatorio de
nodos y en un rango de valores tambin aleatorio. Se utiliza un procedimiento recursivo
para contar el nmero de nodos del rbol, otro procedimiento para mostrar los nodos
ordenados ascendentemente y un procedimiento de altas para insertar cada nuevo n-
mero generado en su correspondiente nodo.
Diagrama de estructura
PROCEDIMIENTO
ALTAS
PROGRAMA
NMERODENODOS
FUNCiN
NODOS
PROCEDIMIENTO
INORDEN
2 Este problema ha sido extrado de la obra Pascal y Turbo Pascal: Un enfoque prctico, de Luis Joya-
nes, Ignacio Zahonero y ngel Hermoso, McGraw-Hill, 1995, y con permiso de los autores.




I

,
,

,

l
!
Arboles binarios
CODIFICACiN
program NumeroDeNodos;
{Este programa genera un rbol binario de nmeros enteros, y
posteriormente muestra y cuenta el nmero de nodos}
uses
Crt;
const
MaxNumNodos = 30;
MaximoValor - 100;
type
,
RangoNodos = o, ,MaxNumNodos - 1 ;
TipoClave = l .. Maximovalor;
Puntero = ANodoArbol;
NodoArbol - record
var
Clave : TipoClave;
Izdo ,
Ocho : Puntero
end;
Raiz : Puntero;
NodosGenerados,
NodosContados,
Indi ce : RangoNodos;
Val o r : TipoClave;
funtion Nodos (P : Punt ero) : RangoNodos;
339
{Funcin recursiva para contar el nmero de nodos del rbol. El nmero de
nodos es la suma del nmero de nodos de cada uno de sus subrboles
izquierdo y derecho ms el nodo raz}
begin
if P = nil then
Nodos := O
else
Nodos : = 1 + Nodos (PA.lzdo) + Nodos (PA .Dcho)
end;
procedure InOrden (P : Puntero);
begin
if P < > nil then
begin
InOrden (PA .Izdo) ;
Write (pA.Clave : 5);
Inorden (PA.Dcho)
end
end;
procedure Altas (var Root : Puntero; Valor : TipoClave);
(Inserta el nuevo valor generado, como nodo del rbol)
var
Padre,
Actual,
NodoAlt a : Puntero;
begin
new (NodoAlta);
NodoAltaA.Clave := Va lor;
NodoAltaA.lzdo := nil; (el nuevo nodo es el nodo hoja)
,
340 Estructura de datos
NodoAltaA.Dcho := nil;
Padre := nil;
Actual := Root;
while Actual <> nil do
begin
Padre := Actual;
if ActualA.Clave >= Valor then
Actual := ActualA.Izdo
elee
Actual := ActualA.Dcho
end;
if Padre = nil then {se situar como raiz}
Root := NodoAlta
elee
if padreA.Clave >= Valor then
PadreA.Izdo := NodoAlta {se sita a la izquierda}
elee
padreA.Dcho := NodoAlta {se sita a la derecha}
end;
begin
ClrScr;
Randomize;
NodosGenerados := Random (MaxNumNodos);
Raiz : = nil;
Writeln (' conjunto de nodos generados al azar': 52);
for Indice := 1 to NodosGenerados do
begin
Valor := Random (maximoValor) + 1;
Write (valor:5);
Altas (Raiz o valor) {insercin del nodo en el rbol}
end;
WriteLn;
WriteLn;
NodosContados := Nodos (Raiz);
WriteLn( 'recorrido InOrden. Nodos encontrados':65);
InOrden (Raiz);
WriteLn;
WriteLn;
WriteLn
WriteLn
end.
('Numero de nodos
('Numero de nodos
generados:
contados:
'o NodosGenerados);
'o NodosContados)
10.8. OPERACIONES EN RBOLES BINARIOS DE BSQUEDA
De lo expuesto hasta ahora se deduce que los rboles binarios tienen naturaleza recursi-
va y en consecuencia las operaciones sobre los rboles son recursivas, si bien siempre
tenemos la opcin de realizarlas de forma iterativa. Estas operaciones son:
Bsqueda de un nodo.
Insercin de un nodo.
Recorrido de un rbol.
Supresin de un nodo.
,
,
i
I
,
,
]
,
,
1
;
,
i
,
,
I
1
,
!
I
i
1
'1
,
I
I
i
,
,
,
i
,
I
,
,
']
!
,
,
,
,
,
,
,
I
i
,
,
,
I
,
,
i
1
j

,
Arboles binarios
10.8.1. Bsqueda
La bsqueda de un nodo comienza en el nodo raz y sigue estos pasos:
l. La clave buscada se compara con la clave del nodo raz.
341
2. Si las claves son iguales, la bsqueda se detiene, o si el subrbol est vaco.
3. Si la clave buscada es mayor que la clave raz, la bsqueda se reanuda en el
subrbol derecho. Si la clave buscada es menor que la clave raz, la bsqueda se
reanuda con el subrbol izquierdo.
La funcin de bsqueda de una clave devuelve la direccin del nodo que contiene a
la clave, o bien ni 1 en caso de encontrarse en el rbol.
funct10n busqueda (R: Ptr; x: TipoInfo): Ptr;
var Esta: boolean;
beg1n
Esta:=false;
wh1le not Esta and (R<>nil) do
1f RA.elemento=X then
Esta:=true
el Be 1f RA.elemento >X then
R:= R
A
. izquierdo
elBe
R:= RA.derecho;
busqueda := R
end;
Se deja al lector la implementacin recursiva como ejercicio prctico.
10.8.2. Insercin
La operacin de insercin de un nodo es una extensin de la operacin de bsqueda. Los

pasos a segUIr son:
l. Asignar memoria para una nueva estructura nodo.
2. Buscar en el rbol para encontrar la posicin de insercin del nuevo nodo, que
se colocar como nodo hoja.
3. Enlazar el nuevo nodo al rbol.
La implementacin de la operacin insertar una nueva clave en un rbol de bsqueda
se realiza, en primer lugar, de founa recursiva. Siempre se inserta como nodo hoja; la
posicin de insercin se determina siguiendo el camino de bsqueda: izquierda para
claves menores, derecha para claves mayores. Hay veces que no se permiten claves repe-
tidas; en nuestro caso se permitir y se inserta por la derecha.
procedure Insertar (var R: Ptr; X: TipoInfo);
beg1n
1f R - nil then
R: - CrearNodo (X)

I
,
I

,
I

I
I
,
!


,

i

342 Estructura de datos
elee if X< RA . elemento then
I nsert ar (RA. izqui erdo . X)
elee if X>=RA.elemento then
Insertar(RA .derecho . X}
end;
El mecanismo de enlace del nodo creado con el nodo antecedente se explica tenien-
do presente el significado de paso de parmetros por referencia (var).
La funcin Cr earNo d o reserva memoria y devuelve su direccin.
function CrearNodo (x : TipoInfo) : Pt r ;
var T: Ptr;
begin
new (T) ;
TA.e l emen to . - x
. - .
TA.izqui e r do := nil; TA. derecho : = ni l ;
CrearNodo : =T
end;
El procedimiento I n ser tar tambin puede plantearse de manera iterativa, como

se muestra a contmuaClOn:
procedure I nsertar (var R: Ptr; X: TipoInf o ) ;
var Q; P : Ptr;
begin
P := R; Q:= R;
while P<> nil do
begin
Q: = P ; {Q tiene l a direccin d el nodo ant e cedente}
if X< pA. e l emento then P:=PA .izquier do
elee P:= p A: derec ho;
end;
P := CrearNodo(X} ;
if Q = n i l then R: = P {Se crea e l nodo r az }
elee if X<QA : e l emento then QA . izquierdo : = P
elee if X<=QA . eleme nt o then QA .derecho : = P
end;
10.8.3. Eliminacin
La operacin de eliminacin de un nodo es tambin una extensin de la operacin de
bsqueda, si bien es ms compleja que la insercin debido a que el nodo a suprimir
puede ser cualquiera y la operacin de supresin debe mantener la estructura de rbol
binario de bsqueda despus de la eliminacin de datos. Los pasos a seguir son:
l. Buscar en el rbol para encontrar la posicin de nodo a eliminar.
2. Reajustar los punteros de sus antecesores si el nodo a suprimir tiene menos de
dos hijos, o subir a la posicin que ste ocupa el nodo descendiente con la clave
inmediatamente superior o inferior con objeto de mantener la estructura de rbol
binario.

,
l

rboles binarios 343


La eliminacin de una clave y su correspondiente nodo, presenta dos casos clara-
mente diferenciados. En primer lugar, si es un nodo hoja o tiene un nico descendiente,
resulta una tarea fcil, ya que lo nico que hay que hacer es asignar al enlace desde
el nodo padre (segn el camino de bsqueda) el descendiente del nodo a eliminar (o
bien, ni 1). En segundo lugar, que el nodo tenga los dos descendientes. Para mantener la
estructura de rbol de bsqueda tenemos dos alternativas, reemplazar la clave a eliminar
por la mayor de las claves menores, o bien reemplazar por la menor de las claves mayo-
res. Se elige la primera alternativa, lo que supone bajan> por la derecha en la rama
izquierda del nodo a eliminar hasta llegar al nodo hoja, que ser el que est ms a la
derecha dentro del subrbol izquierdo de la clave a borrar.
EJEMPLO 10.6 En el rbol de la figura se quiere eliminar la clave 34. El nodo ms a la
derecha de su rama izquierda es 28. Se reemplaza y por ltimo se elimina
el nodo hoja 28.
100
25
6
En la codificacin, el procedimiento anidado Reemplazar realiza la tarea explica-
da anteriormente. La codificacin recursiva es la que se ajusta al planteamiento recursi-
vo de la operacin, y as se implementa:
procedure Eliminar (var R: Pt r; X: Tipo Info) ;
var Q: Ptr ;
procedure Reemplazar (var N: Ptr);
begin
if <> nil then
Reempl azar (NA.de rec ho) ( " ba ja" por rama de recha)
el se begin
: = (reemp l aza i n f o rmacin)
Q : = N;
N :=
end
end;
!
I
,

I

344 Estructura de datos


begin
if R=n i l then wr i te ln ( ' No es t l a c l ave' )
elBe if then
El i mi na r X)
elBe if then
El i mi nar X)
el Be begin
Q : = R ;
if = n i l then {No t i ene d os des c end i e n tes}
R : =
el Be if = n i l then
R : =
el Be
Reempl az a r
d i s pose(Q)
end
end;
10.8.4. Recorrido de un rbol

Existen dos tipos de recorrido de los nodos de un rbol: el recorrido en anchura y el
recorrido en profundidad. En el recorrido en anchura se visitan los nodos por niveles.
Para ello se utiliza una estructura auxiliar tipo cola en la que despus de mostrar el
contenido de un nodo, empezando por el nodo raz, se almacenan los punteros corres-
pondientes a sus hijos izquierdo y derecho. De esta forma si recorremos los nodos de un
nivel, mientras mostramos su contenido, almacenamos en la cola los punteros a todos los
nodos del nivel siguiente.
El recorrido en profundidad se realiza por uno de los tres mtodos recursivos: preorden,
enorden y postorden. El primer mtodo consiste en visitar el nodo raz, su rbol izquier-
do y su rbol derecho, por este orden. El recorrido enorden visita el rbol izquierdo, a
continuacin el nodo raz y finalmente el rbol derecho. El recorrido postorden consiste
en visitar primero el rbol izquierdo, a continuacin el derecho y finalmente el raz.
preorden
en orden
postorden
Raz
Izdo
Izdo
Izdo
Raz
Dcho
Dcho
Dcho
Raz
procedure preorden (p : ptr) ;
begin
if p <> nil then
begin
write elemento : 6) ;
pr eorden
preor den
end
end;
procedure e n_orden (p : ptr);
begin
if p <> nil then





begin
en_orden
Wri te : 6) ;
e n_or den
end
end;
procedure postorden (p : ptr);
begin
if p <> ni1 then
begin
po sto rden
po s torden de r ec ho) ;
wri te el e me n to : 6);
end;
end;
10.8.5. Determinacin de la altura de un rbol
rboles binarios 345
La altura de un rbol depender del criterio que se siga para definir dicho concepto. As, si
en el caso de un rbol que tiene nodo raz, se considera que su altura es 1, la altura del rbol
de la Figura lO.22a es 2, y la altura del rbol de la Figura lO.22b es 4. Por ltimo, si la
altura de un rbol con un nodo es 1, la altura de un rbol vaco (el puntero es ni 1) es O.
7
7
2 15
2 8
1 2
(a)
(b)
6

Figura 10.22. Arboles binarios de diferente altura.
Nota
La altura de un rbol es 1 ms que la mayor de las alturas de sus subrboles iz-
quierdo y derecho.
i
,
I
I
,
,
,

,
,
,

,
,

,
,

346 datos
La funcin recursiva Al t ur a encuentra la altura de un rbol
type Nodo Punt e r o = Apa dr e ;
Padr e = record
i nfo : i n t e ger ;
I zdo , Dc ho : NodoPuntero
end;
function Alt u r a (T : Nodo Puntero) : Int ege r;
{Det e rmina l a a ltura d e un rbo l}
function Max (A, B : integer ) : Int eger ;
begin
if A > B then
Ma x : = A
elee
Ma x : = B
end; {Max}
begin {Altura }
if T = nil then
Al t ura : = O
elee

Altura:=l+Max(Altura(TA.lzdo) , Al t ura(TA.Dc h o))


end; {Al t ura }
RESUMEN
En este captulo se introdujo y desarroll la estructura de datos dinmica rbol. Esta estructura,
muy potente, se puede utilizar en una gran variedad de aplicaciones de programacin.
x
y
z
x
y
z
padre o raz
hijo izquierdo de x
hijo derecho de x
La estructura rbol ms utilizada normalmente es el rbol binario. Un rbol binario es un
rbol en el que cada nodo tiene como mximo dos hijos, llamados subrbol izquierdo y subrbol
derecho.
En un rbol binario, cada elemento tiene cero, uno o dos hijos. El nodo raz no tiene un padre,
pero s cada elemento restante tiene un padre. X es un antecesor o ascendente del elemento Y.
La altura de un rbol binario es el nmero de ramas entre el raz y la hoja ms lejana. Si el
rbol A es vaco, la altura es O. La altura del rbol siguiente es 6. El nivelo profundidad de un
elemento es un concepto similar al de altura. En el rbol siguiente el nivel de 30 es 4 y el nivel
de 36 es 6. Un nivel de un elemento se conoce tambin como profundidad.
Un rbol binario no vaco est equilibrado totalmente si sus subrboles izquierdo y derecho
tienen la misma altura y ambos son o bien vacos o totalmente equilibrados.
- - - - --
,
,
,
,
,
,
,
,
,
,


,
,
j
,
,
,
,
i
,
1
,
j
,
,

,

,
,
."
i
el
,

;
,

,
,

, ,
,
,
,
,
,
,

,
,
,

,
,

,
,
,
1
;
1
1
J
rboles binarios 347
60
-
37
75
25
62
15 30
28 32
69
36
Los rboles binarios presentan dos tipos caractersticos: rboles binarios de bsqueda y r-
boles binarios de expresiones. Los rboles binarios de bsqueda se utilizan fundamentalmente
para mantener una coleccin ordenada de datos y los rboles binarios de expresiones para almace-

nar expresIOnes.
EJERCICIOS
10.1. Considrese el rbol siguiente:
a) Cul es su altura?
b) Est el rbol equilibrado? Por qu?
e) Listar todos los nodos hoja.
d) Cul es el predecesor inmediato (padre) del nodo U?
e) Listar los hijos del nodo R.
j) Listar los sucesores del nodo R.
Q
s
T
w
x
v

1
,

348 Estructura de datos
10.2. Explicar por qu cada una de las siguientes estructuras no es un rbol binario:
A A
B e B B e
D E F D E
D
10.3. Para cada una de las siguientes listas de letras:
1. M,Y,T,E,R
2. R,E,M,Y,T
3. T,Y,M,E,R
4. C,O,R,N,F,L,A,K,E,S
a) Dibujar el rbol binario de bsqueda que se construye cuando las letras se insertan en
el orden dado.
b) Realizar recorridos enorden, preorden y postorden del rbol y mostrar la secuencia de
letras que resultan en cada caso.
10.4. Para los rboles del ejercicio 10.1, recorrer cada rbol utilizando los rdenes siguientes:
NDI, DNI, DIN.
10.5. Dibujar los rboles binarios que representan las siguientes expresiones:
a) (A+B) I (C-O)
b) A+B+C / 0
e) A- (B- (C-D) I (E+F))
d) (A+B) * ((C+D) / (E+F))
e) (A-B) / ((C*D) - (E / F))
10.6. El recorrido preorden de un cierto rbol binario produce
ADFGHKLPQRWZ
y en recorrido enorden produce
GFHKDLAWRQPZ
Dibujar el rbol binario.
10.7. Escribir una funcin recursiva que cuente las hojas de un rbol binario.
10.8. Escribir un programa que procese un rbol binario cuyos nodos contengan caracteres y a
partir del siguiente men de opciones:


.;


1
B
RE
RP
RT
SA
'- -
----------------.--------------------------------------
(seguido de un carcter) :
(seguido de un carcter) :








Insertar un carcter
Buscar un carcter
Recorrido en orden
Recorrido en preorden
Recorrido postorden
Salir
rboles binarios 349
10.9. Escribir una funcin que tome un rbol como entrada y devuelva el nmero de hijos del
rbol.
10.10. Escribir una funcin booleana a la que se le pase un puntero a un rbol binario y devuel-
va verdadero (true) si el rbol es completo y falso (fa/se) en caso contrario.
10.11. Disear una funcin recursiva que devuelva un puntero a un elemento en un rbol bina-
rio de bsqueda.
10.12. Disear una funcin iterativa que encuentre un elemento en un rbol binario de bs-
queda.
PROBLEMAS
10.1. Crear un archivo de datos en el que cada lnea contenga la siguiente informacin:
Columnas 1-20
21-31
32-78
Nombre
Nmero de la Seguridad Social
Direccin
Escribir un programa que lea cada registro de datos de un rbol, de modo que cuando el
rbol se recorra utilizando recorrido en orden, los nmeros de la seguridad social se orde-
nen en orden ascendente. Imprimir una cabecera DATOS DE EMPLEADOS ORDENA-

DOS POR NUMERO SEGURIDAD SOCIAL. A continuacin se han de imprimir los tres
datos utilizando el siguiente formato de salida:
Columnas 1-11
25-44
58-104
Nmero de la Seguridad Social
Nombre
Direccin
10.2. Escribir un programa que lea un texto de longitud indeterminada y que produzca como
resultado la lista de todas las palabras diferentes contenidas en el texto, as como su fre-
cuencia de aparicin.
10.3. Se dispone de un rbol binario de elementos de tipo integer. Escribir funciones que cal-
culen:
10.4.
10.5.

a) La suma de sus elementos.


b) La suma de sus elementos que son mltiplos de 3 .

Escribir una funcin booleana IDENTICOS que pellnita decir si dos rboles binarios son
iguales.
Escribir un programa que tenga como entrada de datos el archivo generado en el proble-
ma 10.1; de forma interactiva permita:
l. Crear un rbol binario de bsqueda T tomando como clave el nmero de la Seguridad
Social.

--_ ...
.
!
,
,
,
,

,



I
!

!

;
,
,

I
350 Estructura de datos
10.6.
10.7.
10.8.
10.9.
10.10.
10.11.
10.12.
10.13.
2. Aadir nuevos registros al rbol T.
3. Eliminar un registro dada la clave,
4. FIN (lo que supone almacenar el rbol en el archivo original.
Disear un programa interactivo que permita dar altas, bajas, listar, etc., en un rbol
binario de bsqueda.
Construir un procedimiento recursivo para encontrar una determinada clave en un rbol
binario de bsqueda.
Calcular el nmero de hojas en un rbol binario.
Disear procedimientos no recursivos que listen los nodos de un rbol en inorden, preor-
den y postorden.
Dados dos rboles binarios de bsqueda indicar mediante un programa si los rboles
tienen o no elementos comunes.
,
Dado un rbol binario de bsqueda construir su rbol espejo. (Arbol espejo es el que se
construye a partir de uno dado, convirtiendo el subrbol izquierdo en subrbol derecho y
viceversa. )
Un rbol binario de bsqueda puede implementarse con un array. La representacin no
enlazada correspondiente consiste en que para cualquier nodo del rbol almacenado en
la posicin 1 del array, su hijo 'izquierdo se encuentra en la posicin 2*1 y su hijo derecho
en la posicin 21 + 1. Disear a partir de esta representacin los correspondientes proce-
dimientos y funciones para gestionar interactivamente un rbol de nmeros enteros. (Co-
mente el inconveniente de esta representacin de cara al mximo y mnimo nmero de
nodos que pueden almacenarse.)
Una matriz de N elementos almacena cadenas de caracteres. Utilizando un rbol bina-
rio de bsqueda como estructura auxiliar ordene ascendentemente la cadena de carac-
teres.
10.14. Dado un rbol binario de bsqueda disee un procedimiento que liste los nodos del rbol
ordenados descendentemente.
10.15. En tres rboles binarios de bsqueda (ORO, PLATA, COBRE) estn representados los
medallistas de cada una de las pruebas de una reunin atltica. Cada nodo tiene la infor-
macin: nombre de la prueba, nombre del participante y nacionalidad. El rbol ORO
almacena los atletas ganadores de dicha medalla, y as respectivamente con los rboles
PLATA y COBRE. El criterio de ordenacin de los rboles ha sido el nombre del atleta.
Escribir los procedimientos/funciones necesarias para resolver este supuesto:
Dado el nombre de un atleta y su nacionalidad, del cual no se sabe si tiene medalla,
encontrar un equipo de atletas de su mismo pas, incluyendo al mismo que tenga una
suma de puntos comprendida entre N y M. Hay que tener en cuenta que una medalla de
oro son 10 puntos, plata 5 puntos y cobre 2 puntos.
,
REFERENCIAS BIBLlOGRAFICAS
Aho, Alfred v., y Ullman, Jeffrey D.: Foundations ofComputer Science, Computer Science Press,
1992.
Cormen, Thomas H.; Leiserson Charles, E. , y Rivert Ronal, L.: lntroduction fo Algorithms, The
Mit Press, McGraw-Hill, 1992.
Carrasco, Hellman y Veroff: Data Structures and problem solving with Turbo Pascal, The Benja-
min/Cummings, 1993.

- - - - -- - - - - - - - - - - - - - - - - - - - -
,
,

l

j
,
rboles binarios 351
Collins, William J.: Data structures. An Object-Oriented Approach, Addison-Wesley, 1992.
Franch Gutierrez, Xavier: Estructura de datos. Especificacin, Diseo e implementacin, Barce-
lona, Edicions UPC, 1994.
Hale, Guy l, y Easton, Richard J.: Applied Data Structures Using Pascal, Massachusetts, Heath,
1987.
Horowitz, Ellis, y Sartaj, Sahni: Data Structures in Pascal, Third edition, New York, Computer
Science Press, 1990.
Joyanes AguiJar, Luis: Fundamentos de programacin, 2." edicin, Madrid, McGraw-Hill, 1996.
Joyanes, L.; Zahonero, l., y Hermoso, A.: Pascal y Turbo Pascal. Un enfoque prctico, Madrid,
McGraw-Hill, 1995.
Krase, Robert L.: Data Structures and program design, Prentice-Hall, 1994.
Koffman, Elliot B., y Maxim, Bruce R.: Software Design and Data Structures in Turbo Pascal,
Addison-WesJey, 1994.
Salmon, William J.: Structures and abstractions, Irwin, 1991.
Tenembaum Aaron, M., y Angenstein Moshe: Data structures using Pascal, Prentice-Hall, 1986.
.



,
,
,


,




1
."
. '. ' .. . , J '. ,
CONTENIDO
','", ' , , ..
,
,
,
CAPITULO

UII
..
" , "J ,',", .
11.1. Eficiencia de la bsqueda en un rbol binario.
,
11.2. Arbol binario equilibrado (AVL).
11.3. Creacin de un rbol equilibrado de N claves.
11.4. Insercin en rboles equilibrados. Rotaciones.
11.5. Eliminacin de un nodo en un rbol equilibrado.
11.6. Programa para manejar un rbol equilibrado.
RESUMEN.
EJERCICIOS.
PROBLEMAS.
En el Captulo 10 se introdujo el concepto de rbol binario. Se utiliza
un rbol binario de bsqueda para almacenar datos organizados jerr-
quicamente. Sin embargo, en muchas ocasiones, las inserciones y eli-
minaciones de elementos en el rbol no ocurren en un orden predeci-
ble; es decir, los datos no estn organizados jerrquicamente.
En este captulo se estudian tipos de rboles adicionales: los rbo-
les equilibrados o rboles AVL, como tambin se les conoce, que ayu-
dan eficientemente a resolver estas situaciones.
El concepto de rbol equilibrado as como los algoritmos de mani-
pulacin son el motivo central de este captulo. Los mtodos que des-
criben este tipo de rboles fueron descritos en 1962 por los matemti-
cos rusos G. M. Adelson-Velskii y E. M. Landis.
11.1. EFICIENCIA DE LA BSQUEDA EN UN RBOL BINARIO
La eficiencia para una bsqueda de una clave en un rbol binario de bsqueda vara
entre O (n) y O ( 1 og (n) ) , dependiendo de la estructura que presente el rbol.
Si los elementos se aaden en el rbol mediante el algoritmo de insercin expuesto
en el captulo anterior, la estructura resultante del rbol depender del orden en que sean
353
354 Estructura de datos
aadidos. As, si todos los elementos se insertan en orden creciente o decreciente, el
rbol va a tener todas la ramas izquierda o derecha, respectivamente, vacas. Entonces,
la bsqueda en dicho rbol ser totalmente secuencial.
R R
Figura 11.1. Bsqueda en un rbol binario.
Sin embargo, si la mitad de los elementos insertados despus de otro con clave K
tienen claves menores de K y la otra mitad claves mayores de K, se obtiene un rbol
equilibrado (tambin llamado balanceado), en el cual son suficientes un mximo de
Lag 2 (n) comparaciones para obtener un elemento.
Como resumen, en los rboles de bsqueda el nmero promedio de comparaciones
que debe de realizarse para localizar a una determinada clave es N/ 2. Esta cifra en el
rendimiento de la bsqueda resulta ser poco eficiente.
Para mejorar el rendimiento en la bsqueda surgen los rboles equilibrados.
,
11.2. ARBOL BINARIO EQUILIBRADO (AVL)
La altura o profundidad de un rbol binario es el nivel mximo de sus hojas. La altura de
un rbol nulo se considera cero.
Un rbol equilibrado es un rbol binario en el cual las alturas de los dos subrboles
para cada nodo nunca difieren en ms de una unidad. A los rboles equilibrados tambin
se les llama rboles AVL en honor de Adelson- Velskii-Landis que fueron los primeros
en proponer y desarrollar este tipo abstracto de datos.
La Figura 11.2 nos muestra un rbol AVL.
R

......,0
L
Figura 11.2. Arbol binario equilibrado (AVL).
rboles equilibrados 355
El factor de equilibrio o balance de un nodo se define como la altura del subrbol
derecho menos la altura del subrbol izquierdo correspondiente. El factor de equilibrio
de cada nodo en un rbol equilibrado ser 1, -1 o O. La Figura 11.2 nos muestra un rbol
equilibrado con el factor de equilibrio de cada nodo.
, ,
11.3. CREACION DE UN ARBOL EQUILIBRADO DE N CLAVES
Considerando la formacin de los rboles balanceados, se parecen mucho a la secuencia
de los nmeros de Fibonacci:
a(n) = a(n-2) + a(n-l)
De igual forma, un rbol de Fibonacci (rbol equilibrado) puede definirse:
1. Un rbol vaco es el rbol de Fibonacci de altura O.
2. Un nodo nico es un rbol de Fibonacci de altura 1.
3. A
h
. Y Ah_2 son rboles de Fibonacci de alturas h-I y h-2 entonces
Ah = < A
h
., x, A
h
_
2
> es rbol de Fibonacci de altura h.
El nmero de nodos Ah viene dado por la sencilla relacin recurrente:
No = O
N = 1
N
h
= N
h
. + 1 + N
h
.
2
Para conseguir un rbol AVL con un nmero dado, N, de nodos hay que distribuir
equitativamente los nodos a la izquierda y a la derecha de un nodo dado. En definitiva,
es seguir la relacin de recurrencia anterior, que podemos expresar recursivamente:
1. Crear nodo raz.
2. Generar el subrbol izquierdo con n = nl2 nodos del nodo raz utilizando la
misma estrategia.
3. Generar el subrbol derecho con nd = n-n-l nodos del nodo raz utilizando
la misma estrategia.
El programa GeneraBalanceado implementa la creacin de un rbol equilibra-
do de n claves.
program GeneraBal a n c eado( input , ou t put};
us es crt ;
type
Ptrae= ANodo ;
Nodo =record
Clave :integer;
Izdo ,Dc ho :Ptrar
end;
var
,

,
,

356 Estructura de datos


R:Ptrae ;
N:i n teger ;
function ArbolEq (N:integer) : Ptrae ;
( f u n c i n para generar e l rbol equi l i brado de c l ave s . Devue l ve
puntero a l nodo r a z )
var
Nu evo : Ptrae ;
Niz; Ndr : i nt eger ;
begin
if N=O then
Arbol Eq: =n i l
el se begin
Ni z :=N di v 2 ;
Ndr : =N- Ni z - l;
new (Nuev o) ;
with Nu evo
A
do
begin
wri t e ( ' Clave :' ) readl n (Clave) ;
I zdo : =Arbo leq (Niz) ;
Drc h:=Arbol eq (De r )
end;
Arboleq : =Nuevo
end
end;
procedure Di bujarar bol(R : Ptrae ; H: integer) ;
{Di buja l os nodos d e l rbol . H nos permi te e stab l e cer separacin e n tre
l os nodos}
var
I : int ege r;
begin
if R<> n i l then
beg in
Di bujar arbol(R
A
. I z do ,H+ 1 ) ;
f o r 1 :=1 to H d o
write( " ) ;
wri te ln( RA. Clave ) ;
Dibujar arbol( R
A
. Drcho,H+l )
end
end;
begin {Gene raBalanc e ado }
c l rscr ;
wri te('Nmero d e nodos de l rbo l ? : '); readln(N) ;
R: =Ar bo l eq (N) ;
c lrs c r ;
Dibujarar b o l ( R,O )
end. (GeneraBa l a nceado}
11.4. INSERCiN EN RBOLES EQUILIBRADOS: ROTACIONES
Para determinar si un rbol est equilibrado debe de manejarse informacin relativa al
balanceo o factor de equilibrio de cada nodo del rbol. Por esta razn aadimos al tipo
de datos que representa cada nodo un campo ms: el factor de equilibrio (Fe).

,
,


,

I

,

358 Estructura de datos


factor de equilibrio de los restantes nodos, debido a que dicho factor queda como el que
tena antes de la insercin, pues el efecto de la reestructuracin hace que no aumente la
altura.
Las violaciones del factor de equilibrio de un nodo pueden darse de cuatro maneras
distintas. El reequilibrio o reestructuracin se realizan con un desplazamiento particular
de los nodos implicados, rotando los nodos. Hay rotacin derecha (D) de un nodo y
rotacin izquierda de un nodo (I).
Los cuatro casos de violacin del balance de un nodo los mostramos en las siguien-
tes figuras, as como la reestructuracin que equilibra el rbol:
a) El rbol original
....... -1
B o
Ahora se inserta el nodo A (siguiendo el camino de bsqueda) y cambia el factor de
equilibrio.
"""' -2
e
-1
A o
En el nodo e se ha roto el criterio de equilibrio, la reestructuracin del rbol consis-
te en una rotacin izquierda, izquierda (rotacin I I).
b) El rbol original
A
....... 0
B
Ahora se inserta el nodo e, cambia el factor de equilibrio.
....... 0

,

,
,

j
1
1
l
!
,
,
. ,
,
,
rboles equilibrados 359
En el nodo A se ha roto el criterio de equilibrio, la reestructuracin del rbol consis-
te en una rotacin derecha, derecha (rotacin DD).
c) El rbol original
A
........ 0
Ahora se inserta el nodo B, cambia el factor de equilibrio .
........ -1
En el nodo A se ha roto el criterio de equilibrio, la reestructuracin del rbol consis-
te en una rotacin derecha, izquierda (rotacin DI).
d) El rbol original
""""'-1
e
Ahora se inserta el nodo B (siguiendo el camino de bsqueda) y cambia el factor de
equilibrio.
,......., -2
B o
En el nodo e se ha roto el criterio de equilibrio, la reestructuracin del rbol consis-
te en una rotacin izquierda, derecha (rotacin ID).
A

I

360 Estructura de datos
Restructurar el rbol implica mover, rotar los nodos del mismo. Las rotaciones pue-
den considerarse simples o compuestas. La rotacin simple involucra a dos nodos,
la rotacin compuesta involucra a tres nodos. Las rotaciones simples se realizan, o
bien por las ramas DD o 1 1. Las rotaciones compuestas se realizan por las ramas DI
o ID.
11.4.3. Formacin de un rbol equilibrado
A continuacin se simulan las inserciones de nodos en un rbol de bsqueda equilibra-
do, partiendo del rbol vaco. Por comodidad se supone que el campo clave es entero. El
factor de equilibrio actual de un nodo y el nuevo al aadir un nodo se representan como
superndices de los nodos. Los punteros n, nl y n2 referencian al nodo que viola la
condicin de equilibrio y a los descendientes en el camino de bsqueda.
Insercin de las claves 68 - 4 5 - 29 :
,,-.. o
68
45 o
o -1
29 o
Una vez insertado el nodo con la clave 29, al regresar por el camino de bsqueda
cambia los factores de equilibrio, as el del nodo 45 pasa a -1, Y en el nodo 68 se
pasa a -2. Se ha roto el criterio de equilibrio y debe de reestructurarse. Al ser
los factores de equilibrio -1 y -2 debe de realizarse una rotacin de los nodos JI
para rehacer el equilibrio. Los movimientos de los punteros para realizar esta ro-
tacin 11
n A.lzqdo f-- nI A .Drc ho
nlA.Drcho f-- n
n f-- nI
Realizada la rotacin, los factores de equilibrio sern siempre O en las rotaciones
simples. El rbol queda de la forma siguiente:
,,-.. o
45
29 o

,




1
i
,
1

1
Insercin de las claves 75 y 90
29 o
........ 01
45
-o
29 o
rboles equilibrados 361
_12
68 .... n
......... 01
75 .... n1
90 o
Una vez insertado el nodo con la clave 90, a la derecha del nodo 75, y regresar por
el camino de bsqueda para as calcular los nuevos factores de equilibrio, se ob-
serva que dicho factor queda incrementado en 1 pues la insercin ha sido por la
derecha. En el nodo con clave 68 queda roto el equilibrio. Para reestructurar se
realiza una rotacin DD. Los movimientos de los punteros para realizar esta rota-

clOn DD:
n A. Drcho
nl A.Izqdo
n
n l
A
. Izqdo
n
nI
Una vez realizada la rotacin, los factores de equilibrio de los nodos implicados
ser O, como ocurre en todas las rotaciones simples, el rbol queda como sigue:
Insercin de la clave 70
n2
........ 1
45
68 o
........ 12
-o
45 .... n
......... 0-1
75 .... n1
......... 0
Para insertar el nodo con la clave 70 se sigue el camino: derecha de 45, izquierda
de 75 y se inserta por la derecha del nodo 68. Al regresar por el camino de bs-
,
.
I
,
.
I
362 Estructura de datos
queda, los factores de equilibrio se incrementan en 1 si se fue por la rama dere-
cha, se decrementa en 1 si se fue por la rama izquierda. En el nodo 45 el balanceo
se ha roto. La rotacin de los nodos para reestablecer el equilibrio es DI. Los
movimientos de los punteros para realizar esta rotacin DI
nl
A
.Izqdo f- n2
A
.Drcho
n2
A
.Drcho f- ni
n A.Drcho f- n2
A
.Izqdo
n2
A
.Izqdo f- n
n f- n2
Los factores de equilibrio de los nodos implicados en la rotacin depende del
valor antes de la insercin del nodo referenciado por n2 segn esta tabla:
si
nA. Fe f- O
ni A Fe f- 1
n2
A
.Fe f- O
O
O
O
Con esta rotacin el rbol quedara
Insercin de la clave 34
n --. 45 -1-2

-1
O
O
90
El camino seguido para insertar el nodo con clave 34 ha seguido el camino de
izquierda de 68, izquierda de 45, derecha de 29. Al regresar por el camino de
bsqueda, el factor de equilibrio del nodo 29 se incrementa en 1 por seguir el
camino de la rama derecha, el del nodo 45 se decrementa en 1 por seguir la rama
izquierda y pasa a ser -2, se ha roto el criterio de equilibrio. La rotacin de los
nodos para reestablecer el equilibrio es 1 D.

,



,
rboles equilibrados 363
Los movimientos de los punteros para realizar esta rotacin 1 D
n1
A
. Drcho n 2
A
. lzqdo
n2
A
. lzqdo n1
nA . lzqdo n2
A
. Drcho
n 2
A
. Drcho n
n n2
Los factores de equilibrio de los nodos implicados en la rotacin depende del
valor antes de la insercin del nodo referenciado por n2, segn esta tabla:
si
n A.Fe 1
n 1
A
. Fe o
n 2
A
Fe O
n2
A
. Fe= O
O
O
O
Con esta rotacin el rbol quedara
n2
A
.Fe= 1
O
- 1
O
11.4.4. Procedimiento de insercin con balanceo
En el procedimiento I nsert a _ba l anceado se realizan las operaciones descritas
anteriormente.
En primer lugar el recorrido baja por el camino de bsqueda hasta insertar el nuevo
nodo como hoja del rbol. Una vez insertado, activa un indicador (flag) si ha crecido en
altura para regresar por el camino de bsqueda, determinar los nuevos factores de equi-
librio y si procede equilibrar.
function Arbolvacio( R: Pt rae ): bool ean;
begin
Arbo l vac i o := R= nil
end;
function Crea r (X : Ti p o info) : Ptrae ;
var
Nuevo : Pt r ae ;
begin
new(Nuevo) ;
with Nuevo
A
do
364 Estructura de datos
begin
Inf o : =x;
Izqdo :=nil;
Drc ho :=n i l ;
Fe := O
end;
Crear : =Nuevo
end;
procedure Rotac i o n_dd (var N: Ptrae ; N1: Pt rae);
begin
N
A
.Drcho :=N1
A
. lzqdo ;
N1
A
. lzqdo:=N;
if 1 then
begin
{S i la r otacin es p o r una inserc i n siempre se cumple la
condici n }


end
elee begin
NA. Fe:= 1;
N1
A
.Fe := - 1
end;
N: =N 1 ;
end;
procedure Rotac i on_ di (var N: Ptrae; N1: Ptrae) ;
{es una Rot aci n d oble, impl ica e l moy o de dos no d os}
var
N2:Ptrae ;
begin
N2 :=NI
A
.Izqdo ;
N
A
. Drc ho:=N2
A
. l zqdo;
N2
A
.l zqdo :=N;
N1
A
.lzqdo:=N2
A
.Drcho ;
N2
A
. Drcho:=N1 ;
if (N2
A
.Fe=1 ) then
NA.Fe:=-l
elee
NA . Fe:=O ;
if (N2
A
.Fe= - 1) then
N1
A
.Fe :=1
elee
N1
A
.Fe:=O;
N2
A
.Fe : =O;
N:=N2 ;
end;
procedure Rotacion_ ii( var N: Ptrae ; N1: Ptrae) ;
begin
NA.lzqdo := N1
A
. Drcho;
N1
A
.Drcho :=N;
if N1
A
.Fe= - 1 then
begin
{Si l a r o tacin es p o r una inserc i n siempre se cumple l a condicin}
." '
NA.Fe:=O;
NI
A
.Fe:=O
end
el Be begin
NA.Fe: = -1;
NI A.Fe: = 1
end;
N:=Nl ;
end;

procedure Rotacion_id(var N:Ptrae; NI:Ptrae);
rboles equilibrados 365
{es una Rotacin doble, implica el mov. de dos nodos}
var
N2 : Ptrae;
begin
N2:= NI A.Drcho;
NA.lzqdo:= N2
A
.Drcho;
N2
A
.Drcho:= N;
NIA.Drcho:= N2
A
.lzqdo;
N2
A
.lzqdo:= NI;
if (N2
A
.Fe =l) then
NIA.Fe:= - l
el Be
NI
A
.Fe:=O;
if (N2
A
.Fe =-1) then
NA. Fe:=l
elBe
NA .Fe:=O;
N2
A
.Fe:=O;
N:= N2;
end;
procedure insertar_balanceado (var R: Ptra e;
var hh: boolean; x:Tipoinfo);
{hh : act iva do cuando ha crec i do en altura}
var
NI :Ptrae;
begin
if Arbolvacio(R) then
{se ha llegado a un nodo hoja, se crea un nuevo nodo}
begin
end
el se
R:= crear(x);
hh: =true {La altura del rbol cuya
if (x< RA.lnfo) then
begin
,
raJ.z
insertar_balanceado(RA.lzqdo, hh, x);
if (hh) then
es el anc estro ha crecido}
{Hay que decrementar en 1 al Fe porqu e se
case RA.Fe of
1: begin
RA.Fe:=O;
hh:=false
end;
insert por rama izquierda}
,
,
;
,
,
,
,



!
;


366 Estructura de datos
end
o: R
A
.Fe := - l;
-1: begin (hay que reestruc tura r ya que
pasar a a va ler -2.Es un desequilibrio I zda)
N1 : =R
A
. lzqdo ;
{tipos de Rotacin}
end
if (N1
A
. Fe = -1) then
(De n uevo desequilibri o I zda . Por lo que: Rotacin ii)
Ro t ac i on_ii(R, NI)
elee {Rotacion id}
Rotac i o n_id(R,N1) ;
hh:=false
elee if (x > RA.ln f o ) then
begin
insertar balanceado(RA .Drcho, hh, x);
if (hh) then
{Al Fe hay que incrementarlo en I porque l a
insercin fue p o r rama derecha}
caee RA.Fe of
-1: begin {se r eequilibra el solo}
RA .Fe: =O;
hh: =fa l se
end;
O: RA.Fe: = 1;
1: begin ( Hay que reequilibrar. El
desequilibri o es por Derecha)
NI:=RA. Drcho ;
( t ipos de Rotacin)
if (N1
A
.Fe = 1) then {Rotacin dd}
Rot ac i on_dd(R, NI)
elee (Rotac in d i)
Rotacion_di(R,N1) ;
hh := false;
end
end
end
elee begin ( x = RA. l nf o )
end
end;
write ln ('No est p r ev ist o i nse rt a r claves repe t i das ' ) ;
hh:=false
, ,
11.5. ELlMINACION DE UN NODO EN UN ARBOL EQUILIBRADO
La operacin de eliminacin consiste en suprimir un nodo con cierta clave de un rbol
equilibrado. Evidentemente, el rbol resultante debe de seguir siendo un rbol equili-
brado (/h
Ri
- h
Rd
/ < = 1).
El algoritmo de eliminacin sigue la misma estrategia que el algoritmo de supresin
en rboles de bsqueda. Hay que aadirle las operaciones de restauracin del equilibrio

rboles equilibrados 367


utilizadas en el algoritmo de insercin en rboles balanceados (rotacin de nodos sim-
pIes) (dd, i i ) o dobles (d i, id). Se distinguen los siguientes casos:
l. El nodo a suprimir es un nodo hoja, o con un nico descendiente. Entonces,
simplemente se suprime, o bien se sustituye por su descendiente.
2. El nodo a eliminar tiene dos subrboles. En este caso se busca el nodo ms a la
derecha del subrbol izquierdo, y se sustituye.
Una vez eliminado el nodo siguiendo los criterios establecidos anteriormente, se re-
gresa por el camino de bsqueda calculando los nuevos factores de equilibrio (Fe) de los
nodos visitados. Si en alguno de los nodos se viola el criterio de equilibrio, debe de
restaurarse el equilibrio.
En el algoritmo de insercin, una vez que era efectuada una rotacin el proceso ter-
minaba ya que los nodos antecedentes mantenan el mismo factor de equilibrio. En la
eliminacin debe de continuar el proceso puesto que se puede producir ms de una rota-
cin en el retroceso realizado por el camino de bsqueda, pudiendo llegar hasta la raz
del rbol.
En los procedimientos se utiliza el argumento boolean hh, ser activado cuando la
altura del subrbol disminuya debido a que se haya eliminado un nodo, o bien porque al
reestructurar haya quedado reducida la altura del subrbol.
,........ -1
-1
69
En el rbol de la figura va a ser eliminado el nodo con la clave 42: al ser un nodo
hoja el borrado es simple, se suplime el nodo. Al volver por el camino de bsqueda para
determinar los Fe, resulta que el Fe del nodo con clave 39 pasara a ser -2 ya que ha
decrementado la altura de la rama derecha, es violado el criterio de equilibrio. Hay que
reestructurar el rbol de raz 39.
-1 -2
Rotacin i i porque
39 ~
nA.Fe ~ (-1-1) Y n 1
A
.Fe <= o
n1
1 1
i
I
Estructura de datos
El rbol resultante es:
,,-...-1
55
-1
Ahora se elimina el nodo con la clave 21. Al tener dos ramas, toma el nodo ms a la
derecha de la rama izquierda que es el de clave 11. Al volver por el camino de bsqueda
para calcular los Fe, el factor de equilibrio del nodo 11 pasara a ser 2 y por tanto hay
reestructurar el rbol de raz 11.
Rotacin di porque
1 2
n A. Fe (1 +1) y n1
A
. Fe < o
26 .- n2
El rbol resultante es:
En estos dos ejemplos se observa que despus de realizar la eliminacin de un nodo,
y cuando se regresa por el camino de bsqueda, el factor de equilibrio del nodo visi-
tado disminuye en 1 si la eliminacin se hizo por su rama derecha y se incrementa
en 1 si la eliminacin se hizo por su rama izquierda. Consideremos ahora este rbol
equilibrado:



,
-1
j

Arboles equilibrados 369
,.....1
65
......... 1
58
73
Se elimina el nodo de clave 25. Como es un nodo hoja se suprime. La supresin se
hace por la rama izquierda, por lo que la altura de la rama derecha correspondiente aumen-
ta en 1, Y lo mismo ocurre con el factor de equilibrio. Los factores de equilibrio quedan:
......... 12
43 ..... n
El rbol resultante es:
Rotacin dd porque
n A.Fe 1+1
n lA . Fe > = o
,-.:.1 2
65
Al seguir regresando por el camino de bsqueda, el nodo raz debe de incrementar su
Fe con lo que pasara a +2, por consiguiente hay que restaurar el rbol, la rotacin es
derecha-izquierda ya que
"...;.1 2
65 ..... n
....... -1
70 ..... n1
1
..... n2

i


370 Estructura de datos
El nuevo rbol queda as es:
67
62
73 86
En el algoritmo de supresin se introducen dos procedimientos simtricos de equili-
brado: Equ i 1 i br ar 1 se invoca cuando la altura de la rama izquierda ha disminuido y
Equ ilibra r2 se invocar cuando la altura de la rama derecha haya disminuido.
En el procedimiento Equ i 1 i br a r 1 al disminuir la altura de la rama izquierda, el
factor de equilibrio se incrementa en l. Por lo que de violarse el factor de equilibrio la
rotacin que se produce es del tipo derecha-derecha, o derecha-izquierda.
procedure Equili br arl (var N:Ptrae ; var hh : boolean) ;
{hh : a ct ivado cuando ha dismi nuido en alt ur a l a rama i zqu ierda
del nodo N}
var
NI : Ptrae;
begin
case NA. Fe of
- 1 : NA. Fe: = O;
O: begin
NA . Fe : = 1 ;
hh := fa lse
end;
1 : begin {Hay que res taurar el equi l ibrio }
Nl := NA. Dr cho ;
end
end;
{Es determinado e l t ipo de r otacin}
if N1
A
. Fe >= O then
begin
if N1
A
.Fe= O then
h h: = f al se; {No disminu ye de nuevo l a altura }
Ro ta cion dd(N, Nl )
end
else
Rota ci on di(N, Nl )
end
En el procedimiento Equilibrar2 al disminuir la altura de la rama derecha, el
factor de equilibrio queda decrementado en l. De producirse una violacin del criterio
de equilibrio, la rotacin ser del tipo izquierda-izquierda, o izquierda-derecha.
- - - - - - - - - ------------ - - - -
,

rboles equilibrados 371
procedure Equilibrar2(var N: Ptrae; var hh: boolean);
(hh : activado cuand o ha disminuido e n alt ur a la rama derecha del n odo N)
var
NI :Ptrae ;
begin
case NA.Fe of
1 : NA.Fe:= O;
O: begin
NA.Fe:= -1;
hh: = fal s e
end;
-1: begin ( Hay que restaurar el equilibrio)
N1:= NA.lzqdo ;
(Es d et erminado el tipo de rotacin )
if NIA.Fe <= O then
begin
if NI A.Fe= O then
hh: = fal se ;
Ro tacion_ii(N, NI)
end
else
Rotacion_id(N, NI)
end
end
end;
A continuacin son escritos los procedimientos de borrar_balanceado y el
procedimiento anidado boro El algoritmo que sigue es el mismo que el de borrado en los
rboles de bsqueda sin criterio de equilibrio. La principal diferencia est en que en el
momento que una rama disminuye en altura es llamado el procedimiento respectivo de
equilibrar.
procedure borrar_balanceado(var R:Ptrae;var hh:boo 1ean;x: Tipoinfo);
var
q:Ptrae;
procedure bor(var d: Ptrae ; var hh: boolean);
begin
if dA.Drcho<>nil then 1
end;
begin
begin
bor(dA.Drcho, hh);
if hh then (Ha disminuido rama derecha)
Equilibrar2 (d, hh)
end
else begin
end
A . f dA f
q .lno:= .ln o ;
q:=d;
d: =d A.l zqdo;
hh:= true
if not ArbolVacio(R) then
if x < RA. info then
372 Estructura de datos
end;
begin
bor r ar _ bal anceado(RA. Izqdo, hh, x);
if h h then
Equi l ibr ar l(R, hh)
end
else if x>R A.info then
begin
bo rra r _ balanceado(RA. Drcho , hh , x ) ;
if hh then
Equil i brar2(R , h h)
end
else begin {Ha sido e n c o n trado el n odo}
q:=R;
if q A.Dr cho= nil then
begin
R:= q A.lzqdo ;
h h : = true {Dismi n uy e la altura}
end
else if q A. l z q do =n il then
begin
R: =q A. Drc ho ;
h h : = true
end
el se begin
bor( qA . lzqdo, hh ) ;
if hh then
Equi l i b r arl (R, h h)
end;
d ispos e (q) ;
end
, ,
.. _._---------------
11.6. MANIPULACION DE UN ARBOL EQUILIBRADO
Agrupamos todas las operaciones relativas a los rboles equilibrados en la unidad U_ av 1.
De esta forma realizamos el TAD rbol binario equilibrado. Slo presentamos la seccin
de i nt er face, interfaz (en definitiva la parte pblica).
El campo de informacin se supone por comodidad que es entero. Incorporamos la
realizacin de la operacin b uscdi r y mo s trar. La operacin b uscd ir devuelve
la direccin del nodo que contiene el campo de informacin X. El procedimiento mo s -
t r a r visualiza el rbol, girado 90 grados a la izquierda respecto a la forma habitual que
se tiene de verlo en papel.
unit u Av l ;
interface
type
Ti poinfo= integer ;
Ptr a e = ANodo ae ;
Nodoae = record
Info
Fe
: Tipoinfo;
: -1. .1 ;
I
,

376 Estructura de datos


RESU N
Un rbol AVL o equilibrado es un rbol binario de bsqueda en el que las alturas de los subrbo-
les izquierdo y derecho del raz difieren a lo sumo en uno y en los que los subrboles izquierdo y
derecho son, a su vez, rboles equilibrados.
-
-

Arboles equilibrados
Insercin de un nodo. Se puede insertar un nuevo nodo en un rbol equilibrado utilizando en
primer lugar el algoritmo de insercin de rbol binario, comparando la clave del nuevo nodo
con el raz e insertando el nuevo nodo en el subrbol izquierdo o derecho apropiado.
Supresin de un nodo. La supresin de un nodo x de un rbol equilibrado requiere las mismas
ideas bsicas, incluyendo rotaciones simples y dobles, que se utilizan por insercin.

Arbol de Fibonacci. Es un rbol equilibrado que se define as:
l. Un rbol vaco es el rbol de Fibonacci de altura O.
2. Un nodo nico es un rbol de Fibonacci de altura l.
3. A
h
.
l
Y A h.2 son rboles de Fibonacci de alturas h-l y h-2, entonces, A
h
=< A
h
.
l
, x, A
h

2
>
es un rbol de Fibonacci de altura h.
-

"



,
,
!
i

,

,


,
1 ,

j

,
1
1

1
i
1
l
j
1
!
1
I
I
,





,
Arboles equilibrados 377
EJERCICIOS
11.1. Dibuje el rbol AVL T que resulta de insertar las claves 14,6, 24,35,59, 17,21,32,4, 7,
15, 22 partiendo de un rbol vaCo.
11.2. Dada la secuencia de claves enteras: 100,29, 71,82,48, 39, 101,22, 46, 17, 3,20, 25, 10.
Dibujar el rbol avl correspondiente. Eliminar claves consecutivamente hasta encontrar un
desequilibrio cuya restauracin sea del tipo rotacin simple, rotacin compuesta.
11.3. En el rbol T resultante del ejercicio 11.1 realiza eliminaciones consecutivas de claves y
reequilibrios, si fueran necesarios, hasta encontrar una rotacin compuesta.
11.4. Tenemos que el rbol equilibrado B est vaCo. Encontrar una secuencia de n claves que al
ser insertadas siguiendo el procedimiento descrito en el captulo, se realicen al menos una
vez las distintas rotaciones: 11, DD, ID, DI. Cul es el valor mnimo de n para una secuen-
cia del tipo descrito?
11.5. Encontrar un rbol equilibrado con n claves de tal forma que despus al eliminarlas se
realicen las cuatro rotaciones para restablecer el equilibrio.
11.6. a) Cul es el nmero mnimo de nodos en un rbol equilibrado de altura lO? b) Generali-
zando, cul es el nmero mnimo de nodos de un rbol equilibrado de altura n?
11.7. El procedimiento de insertar una clave en un rbol equilibrado est escrito de manera re-
cursiva. Escribir el procedimiento de insertar en un rbol equilibrado de forma iterativa.
11.8. Escribir el procedimiento de borrar una clave en un rbol equilibrado de forma iterativa.
PROBLEMAS
11.1. Se quiere leer un archivo de texto y almacenar en memoria todas las palabras de dicho
texto y su frecuencia. La estructura de datos va a ser tal que permita realizar una bsqueda
en un tiempo O(logn), sin que dependa de la entrada de datos, por lo que se requiere utili-
zar un rbol av!. El archivo de texto se llama carta.dat, se pide almacenar dicho texto en
memoria, utilizando la estructura de rbol indicada anteriormente. Posteriormente se ha de
realizar un procedimiento, que dada una palabra nos indique el nmero de veces que apa-
rece en el texto.
11.2. En un archivo de texto se encuentran los nombres completos de los alumnos del taller de
teatro de la universidad. Escribir un programa que lea el archivo y forme un rbol binario
de bsqueda con respecto a la clave apellido. Una vez formado el rbol binario de bsque-
da, formar con sus nodos un rbol de fibonacci Tn.
11.3. Los n pueblos del distrito judicial Lupianense estn dispuestos en un archivo. Cada regis-
tro del archivo tiene el nombre del pueblo y el nmero de sus habitantes. Escribir un pro-
grama para disponer en memoria los pueblos de la comarca de la siguiente forllla: en un
vector almacenamos el nmero de pueblos, cada elemento del vector tiene el nombre del
pueblo y la raz de un rbol AVL con los nombres de los habitantes de cada pueblo. Al no
estar los habitantes almacenados en el archivo se tienen que pedir por entrada directa al

usuano.
Nota: Como es conocido el nmero de nodos de cada rbol AVL, aplicar la construccifm
de rbol de fibonacci.
11.4. Al problema 11.3 se desea aadir la posibilidad de manejar la estructura. As , aadir la
opcin de cambiar el nombre de una persona de un determinado pueblo; habr que tener
en cuenta que esto puede suponer que ya no sea un rbol de bsqueda, por ello ser nece-
,
,

I
,

378 Estructura de datos


sario eliminar el nodo y despus crear otro nuevo con la modificacin introducida. Tam-
bin queremos que tenga la opcin de que dado el pueblo A y el pueblo B, se elimine el
pueblo A aadiendo sus habitantes al pueblo B; en cuyo caso hay que liberar la memoria
ocupada por los habitantes de A.
11.5. Un archivo F contiene los nombres que formaban un rbol binario de bsqueda equi-
librado R, y que fueron grabados en F en el transcurso de un recorrido en anchura de R.
Escribir un programa que realice las siguientes tareas: a) Leer el archivo F para recons-
truir el rbol R. b) Buscar un nombre determinado en R, en caso de encuentro mostrar la
secuencia de nombres contenidos entre la raz de R y el nodo donde figura el nombre
buscado.
11.6. Una empresa de servicios tiene tres departamentos, comercial (1), explotacin (2) y comu-
nicaciones (3). Cada empleado est adscrito a uno de ellos. Se ha realizado un redistribu-
cin del personal entre ambos departamentos. El archivo EMPRESA contiene en cada re-
gistro los campos Nmero-Idt, Origen, Destino. El campo Origen toma los
valores 1, 2, 3 dependiendo del departamento inicial al que pertenece el empleado. El
campo Destino toma los mismos valores, dependiendo del nuevo departamento asignado
al empleado. El archivo no est ordenado. Escribir un programa que almacene los registros
del archivo EMPRESA en tres rboles AVL, uno por cada departamento origen, y realice el
intercambio de registros en los rboles segn el campo destino .


,

,
,


,
o es
-- .. ----0 ,- '
.. . _ .. " . . .. ,.
CONTENIDO
12.1. Definicin de un rbol 8.
12.2. Representacin de un rbol 8 de orden m.
12.3. Proceso de creacin en un rbol 8.
12.4. 8squeda de una clave en un rbol 8.
,
,
12.5. Algoritmo de insercin en un rbol 8 de orden m.
12.6. Recorrido en un rbol 8 de orden m.
12.7. Eliminacin de una clave en un rbol 8 de orden m.
12.8. TAO rbol 8 de orden m.
12.9. Realizacin de un rbol 8 en memoria externa.
RESUMEN.
EJERCICIOS.
PR08LEMAS.
,
CAPITULO
Los rboles B se utilizan para la creacin de bases de datos. As, una
forma de implementar los ndices de una base de datos relacional es a
travs de un rbol B.
Otra aplicacin dada a los rboles B es en la gestin del sistema de
archivos del sistema operativo OS/2, con el fin de aumentar la eficacia
en la bsqueda de archivos por los subdirectorios.
Tambin se conocen aplicaciones de los rboles B en sistemas de
comprensin de datos. Bastantes algoritmos de comprensin utilizan
rboles B para la bsqueda por clave de datos comprimidos.

I 12.1. DEFINICiN DE UN RBOL B


Es costumbre denominar a los nodos de un rbol B, pgina. Cada nodo, cada pgina, es
una unidad a la que se accede en bloque.
Las estructuras de datos que representan un rbol B de orden m tienen las siguientes
, .
caractenstlcas:
379
380 Estructura de datos
Todas las pginas hoja estn en el mismo nivel.
Todos las pginas internas, menos la raz, tienen a lo sumo m ramas (no vacas) y
como mnimo m/2 (redondeando al mximo entero) ramas.
El nmero de claves en cada pgina interna es uno menos que el nmero de sus
ramas, y estas claves dividen las de las ramas a manera de un rbol de bsqueda.
La raz tiene como mximo m ramas, puede llegar a tener hasta 2 y ninguna si el
rbol consta de la raz solamente.
Los rboles B ms utilizados cuando se manejan datos en memoria principal son los
de orden 5; un orden mayor aumenta considerablemente la complejidad de los algorit-
mos y un orden menor disminuye la eficacia de la localizacin de claves.
En la Figura 12.1 se muestra un rbol B de orden 5, donde las claves son las letras
del alfabeto.
P
I L S X
....... .......
A e D J K M o
Q
R T U Y Z
Figura 12.1. rbol de orden 5.
En el rbol B de la figura hay 3 niveles. Todas las pginas contienen 2, 3 o 4 elemen-
tos. La raz es la excepcin, tiene un solo elemento. Todas las pginas que son hojas
estn en el nivel ms bajo del rbol, en la figura en el nivel 3.
Las claves mantienen una ordenacin de izquierda a derecha dentro de cada pgina.
Estas claves dividen a los nodos descendientes a la manera de un rbol de bsqueda,
claves de nodo izquierdo menores, claves de nodo derecho mayores. Esta organizacin
supone una extensin natural de los rboles binarios de bsqueda. El mtodo a seguir
para localizar una clave en el rbol B va a seguir un camino de bsqueda.
12.2. REPRESENTACiN DE UN RBOL B DE ORDEN m
Para representar una pgina o nodo del rbol B tenemos que pensar en almacenar las
claves y almacenar las direcciones de las ramas que cuelgan de los nodos. Para ello se
utilizan dos vectores, y un campo adicional que en todo momento contenga el nmero de
claves de la pgina.
Las declaraciones siguientes se refieren a un rbol B de orden 5.
const
Max= 4; {Nmer o mximo de c l a ves de una pgina. max = m-l,siendo m el
orden del rbOl }
Min= 2 ; {Nmero mni mo de c laves en u n nodo distinto de la raz;
mi n = l!2m-l}
rboles B 381
type
Ti poclave=

I
Ptrb= ~ P a g i n a
posicion= O .. Max;
Pag ina = record
Cuenta : O .. max;
Claves: array [1 .. max] of Tipoclave;
Ramas: array [Posi c i on] of Ptrb;
end;
La razn de indexar Ramas desde O est en que cada pgina tiene un nmero de
ramas igual al de claves ms 1, Y que es la forma ms fcil de acceder a la rama ms a la
izquierda.
12.3. PROCESO DE CREACiN EN UN RBOL B
La condicin de que todas la hojas de un rbol B se encuentren en el mismo nivel
impone el comportamiento caracterstico de los rboles B: crecen hacia arriba, cre-
cen en la raz.
El mtodo que se sigue para aadir un nueva clave en un rbol B es el siguiente:
Primero se busca si la clave a insertar est ya en el rbol, para 10 cual se sigue el
camino de bsqueda.
En el caso de que la clave no est en el rbol, la bsqueda termina en un nodo
hoja. Entonces la nueva clave se inserta en el nodo hoja. Ms bien, se intenta
insertar en el nodo hoja como a continuacin estudiamos.
De no estar lleno el nodo hoja, la insercin es posible en dicho nodo y termina la
insercin de la clave.
El comportamiento caracterstico de los rboles B se pone de manifiesto ahora.
De estar la hoja llena, la insercin no es posible en dicho nodo, entonces se
divide el nodo (incluyendo virtualmente la clave nueva) en dos nodos en el mis-
mo nivel del rbol, excepto la clave mediana que no se incluye en ninguno de
los dos nodos, sino que sube en el rbol por el camino de bsqueda para a su vez
insertarla en el nodo antecedente. Es por esto por 10 que se dice que el rbol
crece hacia arriba. En esta ascensin de claves medianas puede ocurrir que
llegue al nodo raz, entonces sta se divide en dos nodos y la clave enviada
hacia arriba se convierte en una nueva raz. Esta es la forma de que el rbol B
crezca en altura.
Un seguimiento de creacin de un rbol B de orden 5 con las claves enteros sin
signo. Al ser de orden 5 el nmero mximo de claves en cada nodo ser 4. Las claves que
se van a insertar:
6 11 5 4 8 9 12 21 14 10 1 9 28 3 17 3 2 15 16 26 27
382 Estructura de datos
Con las cuatro primeras se completa el primer nodo (recordar que tambin es lla-
mado pgina), eso s, ordenadas crecientemente a la manera de rbol de bsqueda.
4 5 6 11
La clave siguiente, 8, encuentra el nodo ya lleno. La clave mediana de las cinco
claves es 6. El nodo lleno se divide en dos, excepto la clave mediana que sube
. ,
y se convierte en nueva ralz:
6
L.
4 5 8 11
Las siguientes claves, 9, 12, se insertan siguiendo el criterio de bsqueda, en el
nodo rama derecha de la raz por ser ambas claves mayores que 6:
6
4 5 8 9 11 12
La clave 21 sigue por el camino de bsqueda, derecha del nodo raz. El nodo
donde debe de insertarse est lleno, se parte en dos nodos, y la clave mediana 11
asciende por el camino de bsqueda para ser insertada en el nodo raz:
6 1 1
4 5 8 9 12 21
Las siguientes claves, 14, 10, 19, son insertadas en los nodos de las ramas que
se corresponden con el camino de bsqueda:
6 11
4 5 8 9 1 0 12 14 19 21
Al insertar la clave 28 de nuevo se va a producir el proceso de divisin del nodo
derecho del ltimo nivel y ascensin por el camino de bsqueda de la clave me-
diana 19:
-

l
rboles B 383
6 11 19
4 5 8 9 10 12 14 21 28
Continuando con la insercin, las claves 3 1 7 32 15 son insertadas en los
nodos hoja siguiendo el camino de bsqueda:
6 11 1 9
~ ...
3 4 5 8 9 10 12 14 1 5 17 21 28 32
Al llegar la clave 16, baja por el camino de bsqueda (rama derecha de clave
11 en nodo raz). El nodo donde va a ser insertado est lleno. Se produce la divi-
sin en dos del nodo y la ascensin de la clave mediana 15:
6 11 1 5 19
3 45 8 9 1 0 12 14 16 17 21 28 32
Por ltimo, al insertar las claves 26 Y 27, primero se llena el nodo ms a la dere-
cha del ltimo nivel con la clave 2 6. Con la clave 27, que sigue el mismo camino
de bsqueda, ocurre que provoca que se divida en dos el nodo y ascienda al nodo
padre la clave mediana 27. Ahora bien, ocurre que el nodo padre tambin est
lleno por 10 que tambin se divide en dos, sube la clave mediana 15, pero como el
nodo dividido es la raz, con esta clave se forma un nuevo nodo raz: el rbol ha
crecido en altura. El rbol crece hacia arriba, hacia la raz.
15
lo ...
,
r
6 11 19 27
345 8 9 1 0 12 14 1 6 17 21 26 28 32
En esta formacin de rbol B que hemos ido realizando podemos observar estos dos
hechos relevantes:
Una divisin de un nodo, prepara a la ~ t r u c t u r para inserciones simples de nue-
vas claves.
384 Estructura de datos
Siempre es la clave mediana la que sube al nodo antecedente. La mediana no
tiene por qu coincidir con la clave que se est insertando. Por lo que podemos
afirmar que no importa el orden en que lleguen las claves en el balanceo del rbol.
12.4. BSQUEDA DE UNA CLAVE EN UN RBOL B
En los algoritmos de insercin se hace uso de la operacin de bsqueda; por ello se
expone a continuacin el algoritmo de bsqueda de una clave en un rbol B.
El algoritmo sigue la misma estrategia que la bsqueda en un rbol binario de bs-
queda. Salvo que en los rboles B cuando estamos posicionados en una pgina (nodo)
hay que inspeccionar las claves de que consta. La inspeccin da como resultado la posi-
cin de la clave, o bien el camino a seguir en la bsqueda.
La operacin es realizada por un procedimiento que tiene como entrada la ra z del
rbol B y la clave a localizar. Devuelve un valor lgico (true si encuentra la clave), la
direccin de la pgina que contiene a la clave y la posicin dentro del nodo. El examen
de cada pgina se realiza en el procedimiento auxiliar Buscarnodo.
procedure Buscarnodo (C l a v e : Tipoclave ; P : Ptr b;
var Encon t rado : boo l ea n; var K: Pos ic i on ) ;
( Examina l a pgi na r eferenciada por P. De no encon t r a rse , K ser el
ndice de l a rama p o r dond e ' ' baj ar ' ' )
begin
if Cl ave < then
begin
Encontrado : = false;
K: =O (Rama por donde descender)
end
el se begin
{Exami na claves de l a pgina }
K: = p A. Cuenta ; {Nmero de c l ave s de la pgina}
while (Clave< and (K> 1) do
K:= K- 1 ;
En cont rado : = (Clave =
end
end;
El procedimiento Bu scar controla el proceso de bsqueda:
procedure Bus c ar (Clave : Tipocl ave; Ra iz: Pt r b ;
var Encontrado : boolean ;var N:Ptrb; var Pos : Pos i cion );
begin
if Ar bolvaci o(Raiz) then
Encont rado : = fa l se
else begin
end
end;
Buscarnodo(Cl ave, Raiz , Encont rado , Pos) ;
if En con t r ado then
N: = Raiz {Direcc i n d e l a pg i na}
else (Pos e s e l nd i ce de la rama)
Buscar(Cl ave , Ra i z A. Ramas [ Posl , Encon trado, N, Pos)

rboles B 385
12.5. ALGORITMO DE INSERCiN EN UN RBOL B
DE ORDEN m
La insercin de una nueva clave en un rbol B es relativamente simple, como ocurre en
la bsqueda. Si hay que insertar una clave en una pgina (nodo) que no est llena (nme-
ro de claves < m-l), el proceso de insercin involucra a esa pgina nicamente. Slo si
la pgina est llena la insercin afecta a la estructura del rbol. La insercin de la clave
mediana en la pgina antecesora puede a su vez causar el desbordamiento de la misma,
con el resultado de propagarse el proceso de particin, pudiendo llegar a la raz. Esta es
la nica forma de aumentar la altura del rbol B.
Una formulacin recursiva va a ser la adecuada para reflejar el proceso de propaga-
cin en la divisin de las pginas, debido a que se realiza en el sentido inverso por el
camino de bsqueda.
El diagrama de bloques del proceso de insercin se muestra en la Figura 12.2
el Raz
Inserta
t
EmpujaArriba t Mdna
Empujar
Rama?

vacla
Si
Mdna
R
BuscarNodo MeterHoja
X
R
R,
Mdna
DividirNodo
Figura 12.2. Diagrama de bloques del proceso de insercin.
El procedimiento de insercin recibe la clave nueva y la raz del rbol B. Este proce-
dimiento pasa control al procedimiento empujar que baja por el camino de bsqueda
determinado por Buscarnodo, hasta llegar a un nodo hoja. El procedimiento Me-
terHoj a realiza la accin de aadir la clave en el nodo. Si el nodo tiene ya el mximo
de claves, es llamado el procedimiento dividimodo para que a partir del nodo lleno se
formen dos nodos y ascienda la clave mediana.
I

j
,

,
,
,
,
1
!
,

1

rboles B 387
procedure Empujar(Cl:Tipoclave ;R:Ptrb;var EmpujaArriba: boo l ean;
var Mdna : Tipoc l ave; var Xr: Pt r b) ;
var
K : Posicion ;
Esta : bool ean; {Detecta que la clave ya est en el nodo}
begin
if Arbolvacio(R) then
begin {Termina la recurs i n, estamos en rama vaca}
EmpujaArr iba: = true;
Mdna : = el;
Xr : = nil
end
else begin
end
end;
Buscarnodo(Cl , R, Esta, K) ; {K: rama por donde segu i r}
if Es t a then
begin
writeln (el, ' No permitido claves repet i das ' ) ;
halt ( 1)
end;
Empujar(e l,RA .Ramas [ K] ,EmpujaArriba, Mdna, Xr) ;
if EmpujaArriba then
if RA .euent a < Max then {No est lleno el nodo}
begin
EmpujaArriba : = fa l se; {Proceso t ermina }
MeterHoja(Mdna, Xr, R, K) ; { I nsertar l a c lave Mdna en e l nodo
R, posicin K+ 1 }
end
else begin {Nodo lleno}
Empu jaArriba : = t rue;
Div idi rnodo(Mdna, Xr, R, K, Mdna, Xr)
end
Procedimiento MeterHoj a
A este procedimiento se llama cuando ya se ha determinado que hay hueco para aadir
a la pgina una nueva clave. Se le pasa como argumentos la clave, la direccin de la
pgina (nodo), la direccin de la rama con el nodo sucesor, y la posicin a partir de la
cual se inserta.
procedure MeterHoja (X :Tipoc l ave ;Xder, P:Pt rb; K:Posic i on) ;
var
1: Posic ion;
begin
with PAdo
begin
for 1: = Cuenta downto K+1 do
begin {Son desplazadas c l aves / ramas para ins e r tar X}
Claves [1 +1 ] : = Claves [1] ;
Rama s [ 1 + 1] : = Rama S [ 1 ]
end;
..
388 Estructura de datos
Claves [K+l J : = X;
Ramas[K+IJ:= Xder;
Cuenta:= Cuenta+l
end
end;
Procedimiento de divisin de un nodo lleno
El nodo donde hay que insertar la clave x y la rama correspondiente est lleno. A nivel
lgico es dividido el nodo en dos nodos y la clave mediana enviada hacia arriba para una
reinsercin posterior. Para ello lo que se hace es crear un nuevo nodo donde se llevan las
claves mayores de la clave mediana, dejando en el nodo original las claves menores.
Primero se determina la posicin que ocupa la clave mediana, teniendo en cuenta la
posicin central del nodo y la posicin donde debera de insertarse la nueva clave. A
continuacin se divide el nodo, se inserta la nueva clave en el nodo que le corresponde y
por ltimo se extrae la clave mediana.
procedure DividirNodo(X:Tipoclave;Xder,P:Ptrb;K:Posicion;
var Mda: Tipoclave; var Mder:Ptrb);
var
I, Posmda: Posicion;
begin
if K <= Min then {Min es la posicin central}
{La clave se situa a la izquierda}
Posmda:= Min
else
Posmda:= Min+l;
new(Mder) ; { Nuevo nodo }
with PAdo
begin
end
end;
for I:= Posmda+l to Max do
begin
Mder
A
. Claves [I-PosmdaJ : =Claves [IJ ; {Es desplazada la mitad
derecha al nuevo nodo,la clave mediana se queda en nodo
izquierda}
MderA.Ramas[I- PosmdaJ:= Ramas[IJ
end;
MderA.Cuenta:= Max- Posmda; {Claves en el nuevo nodo}
Cuenta:=Posmda;{Claves que quedan en nodo izquierda}
{Insercin de clave X y su rama derecha}
if K<= Min then
Meterhoja(X,Xder,P,K) {inserta en nodo izquierda}
el se
Meterhoja(X, Xder, Mder, K-Posmda);
{extrae mediana. del nodo izquierdo}
Mda:= Claves [CuentaJ ;
MderA.Ramas[OJ:= Ramas [CuentaJ ; {Ramao del nuevo nodo es la rama de
la mediana}
Cuenta:= Cuenta-l {Disminuye ya que se quita la mediana}

,
j
,
,
!
'j
,
j
"
I
,
,
..
,
,
,
,
i
,
:1
i

i
,
.,
i
!
l
,
I
I
i

I
,
,

I
, ,
!
I
,
j
!

Arboles B 389
12.6. RECORRIDO EN UN RBOL B DE ORDEN m
El recorrido en un rbol B consiste en visitar todos los nodos del rbol , y para cada nodo
todas las claves de que consta. Con una pequea variacin de los recorridos de un rbol
binario, se puede aplicar al de un rbol B.
Se presenta a continuacin el recorrido que visita las claves en orden creciente, es un
recorrido en inorden. En primer lugar, la versin recursiva:
procedure InordenB(R : Ptrb ) ;
var
l : integer;
begin
it not Arbol vacio(R) then
begin
end
end;
I n ordenB( RA. Rama s[ Ol) ;
tor l:= 1 to RA . Cu en t a do
begin
wr i t e 1 n (R A . C 1 ave s [ 1 1 ) ;
lnorde nB (RA.Rama s[I] )
end
La versin no recursiva utiliza una pila para almacenar la direccin del nodo y el
ndice de la rama.
procedure InordenB (R : Ptrb) ;
var
1 : int eger ;
P : Pt rb;
Pila : ptrpla ;
begin
Pcrear(Pila) ;
P := R;
repeat
l : = O;
while not Arbolvac io(P ) do
begin
Pmeter(P , I, Pila ) ;
P : = PA .Ramas[ Il
end;
if not Pvacia(pila) then
begin
end
Psac ar( P, l, Pil a ) ;
1: = 1+ 1;
if l <= pA . Cuenta then
begin
end
wr i te l n(PA . Clavesl I l ) ; {Pr oce so d e l a clavel
if 1 < pA .Cuenta then
Pme ter ( P , 1, Pi 1 a) ;
P: = PA.Ramas [ I ]
until Pvac ia( Pi la) and Ar bolvacio(P)
end ;
I
,
,


!

,
390 Estructura de datos
, ,
12.7. ELlMINACION DE UNA CLAVE EN UN ARBOL B
DE ORDEN m
Al igual que las inserciones de una clave siempre se hacen en una pgina hoja, las elimi-
naciones siempre se harn en una pgina hoja. Es evidente que una clave no tiene por
qu estar en un nodo hoja, para eIlo se aplica la siguiente caracterstica de los rboles B:
si una clave no est en una hoja, su clave predecesora o sucesora (predecesora o suceso-
ra en el orden natural) estar en un nodo hoja.
4 5
.. ..
16 26 79 172
5 9 15 18 22 24 29 32 48 57 82 126 192 232
Una primera consecuencia es que si la clave a eliminar no est en una hoja, se pondr
a la clave predecesora en la posicin ocupada por la clave eliminada y se suprimir la
clave en la hoja. As se observa la figura con el rbol B de orden 5.
Se quiere eliminar la clave 1 6, esta clave no est en una hoja; el sucesor inmediato
de 16, que es 18, se pone en la posicin de 1 6 y luego 18 se suprime en el nodo hoja en
que se encuentra:
45
.. ..
18 26 79 172
5 9 15 22 2 4 29 32 48 57 82 126 192 23 2
Esta supresin que acaba de realizarse es el ms fcil , es el caso en el que la hoja
donde se va a eliminar contiene un nmero de claves mayor que el mnimo de claves que
puede haber en un nodo, una vez eliminada no hay que hacer una accin posterior.
En el caso de que la hoja donde se vaya a eliminar la clave tenga el nmero mnimo
de claves, al eliminar una clave se va a quedar con menos claves que el mnimo exigido
por nodo. Claro est que hay que realizar una operacin de movimiento de claves para
que el rbol siga siendo un rbol B: se procede a examinar las hojas inmediatamente
adyacentes al nodo con el mismo antecedente. Si una de estas hojas tiene ms del nme-
ro mnimo de claves, puede moverse una de eIlas para as restablecer el mnimo de clave.
Para que las claves del rbol sigan dividiendo a las claves de sus nodos descendientes a
la manera de rbol de bsqueda, el movimiento de claves consiste en subir una clave al
_ ~ _ o.
rboles B 391
nodo padre para que a su vez descienda de ste otra clave al nodo que se quiere restaurar.
As queda restaurado el nodo y sigue siendo un rbol B.
En el rbol resultante de la eliminacin anterior se elimina ahora la clave 2 4. El
nodo que la contiene tiene dos claves, entonces se elimina la clave y se analiza los nodos
contiguos del mismo antecedente. Resulta que en el nodo izquierda tiene tres claves, por
lo que asciende la clave 1 5 al nodo padre, y a su vez de ste desciende la clave 1 8 para
ser insertada en el nodo a restaurar. El rbol resultante:
45
L ..
.,
15 26 79 172
5 9 18 22 29 32 48 57 82 126 192 232
An queda otro caso ms complejo que los dos anteriores. Al eliminarla clave 22
del nodo hoja, ste se queda con una menos que el mnimo y las dos hojas contiguas
tienen nicamente el mnimo de claves. La estrategia a seguir en este caso: se toma la
hoja a eliminar, su contigua y la clave mediana de ambas, procedente del nodo antece-
dente, y se combinan como un nuevo nodo hoja. Claro est que esta combinacin puede
dejar al nodo antecedente con un nmero de claves menor que el mnimo, entonces el
proceso se propaga hacia arriba, hacia la raz. En el caso lmite, la ltima clave ser
extrada de la raz y luego disminuir la altura del rbol B.
Partiendo del ltimo rbol B, ahora queremos eliminar la clave 22. El nodo donde se
encuentra se queda con una sola clave, y los nodos adyacentes tienen justamente el m-
nimo de claves. La siguiente combinacin restaura al nodo:
1 5 26
5 9 18
El rbol que resulta inmediatamente despus del proceso:

45
L ..
r
2 6 79 172
5 9 1 5 18 29 3 2 48 57 82 12 6 192 23 2
Este proceso ha dejado al nodo antecedente con una sola clave, menos que el mnimo
necesario. El proceso se propaga al nivel anterior, producindose esta combinacin:
I

,
,
392 Estructura de datos

45
26 79 17 2
El rbol B que resulta
26 45 79 122
5 9 1 5 18 29 3 2 48 57 82 12 6 192 232
ha disminuido la altura del rbol, el proceso de combinacin de dos nodos ha alcanzado
a la raz.
Diagrama de bloques del proceso de eliminacin
El proceso empieza con la llamada al procedimiento El iminar, ste pasa control a
El i mina rRe g ist r o que es el encargado de controlar todo el proceso.
BuscarNodo
CI Raz
Eliminar
CI.
Raz t Encontrar
EliminarRegistro
Act
K K
K
Encontrar
Quitar Sucesor
{Elimina la clave
en nodo hoja}
{Reemplaza
clave por la
que le sucede}
Mover
derecha
K
r--R-e-s-ta .... b-Ie-ce-r- Restaura el nodo
act t Ramas [K]}
Act
K
Combina
Mover
izquierda
Figura 12.3. Diagramas de bloques del proceso de eliminacin.
rboles B 393
Procedimiento Eliminar
El procedimiento El i minar tiene la misma estructura que I nsertar. Tiene como
misin principal devolver la nueva raz si la raz inicial se ha quedado sin claves.
procedure Elimi na r (el : Tipoclave ; var Rai z : Pt r b) ;
var
Encontrado : boolean;
P: Ptrb;
begin
Eli minarRegist r o(e l, Raiz , Encontrad o};
if not Encon trado then
wr i te l n( 'Error :l a clave no est en e l rbo l ')
elae if Ra iz A. euenta= O then {La ra z se ha quedado vaca }
begin {Se libera el nodo y se obtiene la nueva ra z }
P:= Rai z;
Raiz : = RaizA.Ramas[O];
dispose (P)
end
end;
Procedimiento EliminarRegistro
Este procedimiento controla el proceso de borrado de una clave. Primero busca el nodo
donde se encuentra la clave a eliminar. Si el nodo es una hoja, llama a la rutina que
elimina. De no ser hoja, es hallado el inmediato sucesor de la clave, se coloca en el nodo
donde se encuentra la clave; despus se suprime la clave sucesor en el nodo hoja.
La forma ms fcil de expresar este proceso es la recursiva; al retornar la llamada
recursiva debe de comprobar si hay un nmero de claves suficientes, mayor o igual que
el mnimo necesario (2 en el caso de rbol B de orden 5), de no ser as hay que mover
claves al nodo para alcanzar el nmero necesario de claves.
procedure Eli minarRegistro(el : Ti poc l ave ; R: Ptrb;
var Encont rado : boo l ean) ;
var
K: Posic i o n;
begin
if Arbolvac io (R) then
Encontrado:= false {Se ha l l e gado "debajo " de una h oj a, la c l ave no
est e n el rbo l }
elae with R
A
do
begin
Buscarnodo(el, R, Enc ontrado , K) ;
if Encontrado then
if Ramas [ K-l ]= n i l then {Las r amas estn i nd e xadas desde ndice O
a Max, por 10 que este nodo es hoja}
Qu itar (R, K)
elae begin {No e s ho ja}
Sucesor(R, K); {Reempl aza e l aves [ K)por su sucesor}
Elimi narRegistro(Cl a ves [ K] , Ra mas[K] , Encontrado) ; {Elimi na la
c lave sucesor a e n su nodo}
394 Estructura de datos
if not Encontrado then {Es una inconsistencia, la clave debe de
estar en el nodo}
end
begin
writeln( 'Error en el proceso');
Halt (1)
end
elBe {No ha sido localizada la clave}
EliminarRegistro(Cl, Ramas[K] , Encontrado);
{Las llamadas recursivas devuelven control a este punto del
procedimiento: se comprueba que el nodo hijo mantenga un nmero de
claves igual o mayor que el mnimo necesario}
if Ramas[K]< > nil then {Condicin de que no sea hoja}
if Ramas[K]A.Cuenta< Min then
end
end;
Restablecer(R, K)
Procedimiento Qui tar
Esta rutina recibe la direccin del nodo y la posicin de la clave a eliminar. Elimina la
clave junto a la rama que le corresponde .
.
procedure Quitar(P: Ptrb; K: Posicion);
var
J: Posicion;
begin
with pA do
begin
for J:= K+l to Cuenta do
begin
Claves [J-1] : = Claves [J]; {Desplaza
ello es eliminada
Ramas [J-l] : = Ramas [J]
end;
Cuenta:= Cuenta- 1
end
end;
Procedimiento Sucesor
. "
una pOSlClon a la izquierda, con
la clave}
En esta rutina se busca la clave inmediatamente sucesor de la clave K, que por la propie-
dad de los rboles B est en una hoja, y sta reemplaza a la clave K.
procedure Sucesor(P: Ptrb; K: Posicion);
var
Q: Ptrb;
begin
Q:= pA.Ramas[K];
while QA.Ramas[O]<> nil do
Q:= QA.Ramas[O];
{Q referencia a un nodo hoja}
PA.Claves[K]:= QA.Claves[l]
end;
,

rboles B 395
Procedimiento Restablecer
En este procedimiento se realizan las acciones ms complejas del proceso. Restaura
el nodo p A Rama s [K) el cual se ha quedado con un nmero de claves menor que el
, .
mmlmo.
El procedimiento siempre toma una clave a partir del hermano de la izquierda (cla-
ves menores), slo utiliza al hermano derecho cuando no hay hermano izquierdo. Puede
ocurrir que no pueda tomar claves y entonces llamar a Combina para formar un nodo
con dos nodos.
procedure Restablecer(P : Pt rb ; K: Posi cion ) ;
{P t i ene l a direccin del nodo ant e ceden te de l nodo PA. Rama s[K] que s e
ha quedado con me no s claves que e l m nimo}
begin
if K > O then
{Ti ene "he rma no " i zqui erdo}
if PA. Ramas[ K- l]A .Cuent a> Mi n then
elee
{Tiene ms cl aves que e l mn i mo y por tan to puede
desplazarse una clave}
Mover Drcha(P , K)
Comb i na(P , K)
elee
{S l o t i e ne "herma no " der ec ho}
if P
A
. Ramas[l] A. Cuent a > Min then
elee
{Tiene ms c l aves que e l mnimo}
Mover l zqda(P , 1 )
Combina(P , 1)
end;
Procedimiento MoverDerecha
Este procedimiento mueve una clave del nodo antecedente ( p) al nodo que se est res-
taurando. A su vez, asciende la clave mayor del hermano izquierdo al nodo antecedente.
procedure MoverDrcha(P : Pt rb ; K: posic i o n );
{En este procedimiento se de j a "hueco " en el nodo pA. Ra mas [ K] A que es
el nodo qu e tiene me no s claves qu e el m nimo n ecesari o , i n serta l a
clave k del nodo ant ecedent e y a su v ez asc iende l a c lave mayor( l a
ms a l a der echa)del he rmano izquierdo}
var
J : Posic i o n ;
begin
with PA . Ramas [ K]A do {es e l nodo con menos claves que e l mnimo }
begin
for J := Cuenta downto 1 do
begin
c l aves [J+1 ] : = c l aves [ J ] ;
Ramas [ J +1 ] : = Ramas [ J ];
end;
396 Estructura de datos
Cue n ta:= Cue n ta+ l ;
Ra mas [l ] : = Ramas[O] ;
Claves [l] : = PA . Cl a ves [ K] { "ba ja " la clave del nod o padre }
end;
{Ahora " sube " la clav e desde el herma n o izqui erdo al nodo padre, para
reemplazar la que an t es baj }
with pA.Rama s [K- l ] A do {Hermano i zqu ierdo}
begin
pA . Claves [K ] : = Clave s [Cu enta] ;
PA. Ramas[K]A .Ramas [ O] : = Ramas [Cu e nta] ;
Cuent a := Cuenta -l
end
end ;
Procedimiento MoverIzquierda
Realiza la misma accin que el procedimiento Moverderecha, salvo que ahora la clave
que asciende al nodo antecedente es la clave menor (izquierda) del nodo a restaurar.
procedure MoverI zqda I P : Pt r b ; K: Pos i cion) ;
( Desci e n de l a c l ave KIl) del nodo padr e P al hijo izqu i erda y la
insert a e n l a pos icin ms alta , de esta forma se res t ablece el mnimo
de claves . Despus sube la clave 1 d el h ermano der echo . }
var
J : Posic i o n;
begin
with p A. Rama s[K- l ]A do {es el nodo con menos claves que el mnimo}
begin
Cue nta:= Cu e n ta +l ;
Claves [Cu e nt a ] : = PA . Claves [K] ;
Ramas[Cuent a ]: = pA .Ra mas[ K]A.Ramas[O ]
end;
with PA . Ramas[ K]A do {Herma no derecho}
begin
end
end;
PA. Cl aves [ K] : = Claves[l] ; {Su be al n o do padr e l a clave 1 de l
h erma no d erecho , sustituye a la qu e ba j}
Ramas [ O] : = Ramas [1] ;
Cuent a:= Cuenta -l ;
for J:= 1 to Cuenta do
begin
end
Claves [J] : = Claves [J+l ];
Ramas[ J] : = Ra mas [ J +l]
Procedimiento Combina
En este procedimiento se forman un solo nodo con dos nodos. Combina el nodo que est
en la rama K con el que est en la rama K - 1 Y la clave mediana de ambos que se encuen-
tra en el nodo antecedente. Una vez finalizado el proceso, libera el nodo obsoleto.
- -------
- - ------------------------- ----_ . .
rboles B 397
procedure Combi na(p : Ptrb ; K: Posicion);
{Forma un nuevo n odo con el herma no izquierdo , la mediana e n tre e l nodo
p r obl ema y su h ermano i zqu ierd o si t uada en el nodo p ad re , y l as claves
del nodo probl ema . Es liberado e l nodo pr oblema}
var
J: po sicion;
Q: Ptrb;
begin
Q: = PA. Rama s[K] ;
with p A. Ramas [ K- l ] A do {Herma no iz quierd o}
begin
Cuenta : = Cue n ta +l ;
Claves [ Cuent a ] : = p A . Cl a v es [K] ; { " b aja" c lave me di ana d esde el nodo
pad re }
Ramas [ Cuenta ] : = QA. Rama s [ O] ;
for J := 1 to QA.Cuenta do
begin
end
end;
Cu e n ta : = Cuenta+l ;
Cl aves [ Cuenta] : = QA. Cl aves [J ] ;
Ramas[Cuenta] := QA.Ramas[J] ;
{Son rea j ustadas las claves y ramas de l nodo padre debido a q u e
ant es descendi l a clave k}
with pA do
end;
begin
for J := K to Cuenta-l do
begin
Cl aves [ J ] : = Cl aves [ J +l];
Ramas [J] : = Ramas [ J+ l ]
end;
Cuenta : = Cuenta - l
end;
dis p ose( Q)
,
12.8. TAO ARBOL B DE ORDEN m
Hasta ahora se ha descrito un rbol B, cmo representar al rbol B de orden m y qu
operaciones son definidas sobre la estructura; es decir, se ha definido el tipo abstracto
de datos rbol B. A continuacin se escribe la unidad rbol B, aunque slo la seccin
de int erfac e; la seccin imp l e me n tat i o n ha sido escrita paso a paso en los
apartados anteriores.
unit Ar b o lB ;
interface
const
Or de n
- S ,
- ,
Max - Or d en - l ; {Nme ro mx imo d e c lav e s en un nodo }
Min = (Or den-l ) d i v 2; {Nme ro mni mo d e clav es e n un n odo di st into
de la ra z}
I


,
,

398 Estructura de datos


type
Tipoclave - integer;
Ptrb = APag ina ;
posicion= O .. Max;
Pagina= record
Cuenta: O ., max;
Claves: array [1 .. maxJ of Tipoclave ;
Ramas: array [PosicionJ of Ptrb ;
end;
procedure Buscarnodo (Clave : Tipoc lave ; P : Pt rb;
var En contrado : bool ean; var K: Posici o n);
procedure Bus car (Clave: Tipoclave; Raiz: Pt rb;
var Enc o ntrado: boolean ;
var N: Ptrb; var Pos : Posicion );
procedure Inserta (Cl: Tipoc l ave; var Raiz : Ptrb);
procedure Empujar (C l : Tipoclave; R: Ptrb;
var EmpujaAr ri ba : boolean ;
var Mdn a : Tipoclave; var Xr: Ptrb);
procedure Mete rHoja(X : Tipoclave ; Xder, P: Ptrb; K: Posicion);
procedure DividirNodo(X : Tipoc lave; Xder. P: Ptrb;
K: Posicion; var Mda: Tipoc lave ;
var Mder: Pt rb) ;
procedure Mos trarB (R : Pt rb); {Es el recorr i do en i norden}
function Arbolvacio(R: Ptrb) : bool ean;
{Operaciones para el proce so de borrado de una clave}
procedure El iminar (Cl : Tipoclave ; var Raiz: Ptrb);
procedure EliminarRegistro (Cl : Tipoc l ave; R: Ptrb;
var Enco ntrado: boo l ean);
procedure Restablecer(P: Ptrb; K: Posicion);
procedure Quit ar(P : Ptrb; K: Posi cion);
procedure Sucesor(P : Ptrb; K: Pos ici on) ;
procedure Moverlzqda(P: Ptrb; K: Posicion ) ;
procedure MoverDrcha(P: Ptrb; K: Posicion);
procedure Comb ina(P : Ptrb; K: Pos i cion) ;
implementation

begin
end.
Esta unidad se emplea a ttulo de ejemplo para crear un rbol B de orden 5, conside-
rando el tipo de las claves entero.
Las claves son generadas aleatoriamente para evitar problemas, antes de insertar la
clave se examina si ya est en el rbol. Tambin se realizan operaciones de eliminacin
de claves en el rbol creado.
,
CODIFICACION
program Procesa_arbolB(input,output);
uses crt , Arbo l b;
const
Mx=9999;

i




-




..



,

;
1
1


1
,
,

var
Rb: Ptrb ;
Cl: integer;
Op,N : integer;
procedure Menu( var Opc : int eger);
begin
clrscr;
gotoxy(10,2 ) ; wr it e1n(' 1 . I n sertar n claves') ;
gotoxy(10 , 4); wr i teln(' 2 . Ins er tar 1 clave');
gotoxy(10,6); write l n ( ' 3 . Eliminar c lave') ;
gotoxy(10 , 8) ; write1n( '4. Listar clave s') ;
g otoxy (10 , 10) ;wri t el n( '5. Fin p roc eso ' );
repeat
go t oxy (10,13) ; wr i teln (' Opci n ?: ');
readln(Opc)
un ti 1 Op c in [1. . 5 1 ;
end;
procedure Annade_Cl aves (var Rb:Pt rb;N:integer);
var
K:O .. 1 00 ;
X:int ege r;
P:Posi c i on ;
Es ta : boo1ean;
Nd:Pt rb ;
begin
K: =O;
write ( ' Claves ins ert adas: ' ) ;
repeat
X: = r andom (Mx) ;
Buscar(X,Rb,Esta,Nd,P) ;
if not Es ta then
begin
I n serta(X, Rb) ;
writ e( X,' '};
K:=K+l ;
end
unti1 K=N;
writel n;
end;
begin {Bloque pri n cipal}
Rb : =nil;
Ra ndomize;
repeat
Menu (Op) ;
case Op of
1 : begin
cl r scr; go toxy (4,5) ;
write ( 'Cant as c l aves: ? : ' ) ; read ln (N) ;
Annade_c laves ( Rb,N)
end;
2 : An na de_c l aves(Rb, 1 ) ;
3 : begin
Arboles B 399
write('Clave que se desea e limi na r:?');readln( Cl);
El iminar( Cl , Rb)
end;
,
,
400 Estructura de datos
4: Mo s trarB(Rb)
end;
repeat until readkey i n [ #0 .. #2551
until Op=5
end.
, ,
12.9. REALlZACION DE UN ARBOL B EN MEMORIA EXTERNA
En los apartados anteriores se ha definido la estructura rbol B, su representacin en
memoria y las operaciones para insertar claves y eliminar. Ahora bien, esta estructura
para que realmente sea til debe de estar almacenada en un archivo externo y ser mane-
jada accediendo al archivo.
Los procesos de bsqueda, insercin, eliminacin y recorrido van a ser los mismos,
salvo un cambio muy importante en la representacin y es que ya no se utilizan variables
dinmicas, los enlaces no sern punteros sino nmero de registros en los que se almace-
na el nodo o pgina descendiente. .
Para crear un nuevo nodo (pgina) hay que buscar un hueco en el archivo, repre-
sentado por un nmero de registro, posicionar el pointer del archivo en ese hueco y
escribir el nodo. De igual forma, cada vez que se modifica un nodo por un cambio en las
claves hay que escribir el registro en la posicin del archivo correspondiente.
En esta realizacin de rboles B las ramas van a ser nmero de registro. La funcin
Huecos concede el nmero de registro donde almacenar un nodo. Para ello se sigue la
siguiente estrategia:
De la pila de registros liberados, se saca el elemento cima.
Si la pila est vaca, se obtiene el siguiente registro libre de la memoria externa.
El proceso de liberacin de nodos supone almacenar en la pila de registros libres el
nodo que se libera. Los procedimientos de insercin y eliminacin son los mismos que
en la realizacin con estructuras dinmicas, salvo las modificaciones que supone no uti-
lizar punteros sino nmeros de registro. Son utilizados dos archivos, el que almacena el
rbol propiamente dicho (llamado F i c hab) y otro para almacenar el nmero de regis-
tro del nodo raz y la pila de registros libres (llamado Fh u e c o s). Es inmediato pensar
que hay que grabar el nmero de registro de la raz para que a partir de l pueda acceder-
se a toda la estructura.
Los tipos de datos para realizar a un rbol B de orden 5 en memoria externa:
const
Orden= 5;
Max=Orden-l;
Min=(Orden-l) div 2 ;
type
Tipoclave=
Apuntador=

I
intege r;
{Nme r o mximo de c laves en un nodo}
{Nmero mnimo de claves en un nodo d i stinto de l a
raz}

po sicion = O .. Max;
Pagina= record
Cuenta : O .. Max;
Claves : array [ 1 .. Max] of Tipoclave ;
Ramas: array [Posi c i on] of Apuntador
end;
Fi c hero = file of Pagina;
Flibre = file of integer;
rboles 8 401
Para adaptarse a la nueva manera de direccionar los nodos y para grabar o cargar la
estructura son necesarias estas nuevas rutinas.
Funcin Hueco
,
Devuelve la posicin del siguiente registro libre. Este puede venir de la pila de registros
liberados, o bien el registro siguiente al ltimo concedido.
function Hueco (Pila : Tpila; var F: Archivo) :integer;
begin
if not Pvacia (Pila ) then
Hueco:= Psac ar(Pi l a)
else
Hueco:= fil esize(F)
end;
Procedimiento Inicial
Ser el primer procedimiento en ser llamado. Asigna archivos y vuelca en la pila los
nmero de registros liberados. Devuelve la raz del rbol B.
procedure Inicializa (var F : Archivo; var Fh: Fl i bre;
var R:int eger ; var Pila: Tpi l a);
var
I : Apuntador;
begin
Pc rear (Pila) ;
assign(F, 'datosab.dat ');
assign(Fh , 'huecos . dat ' );
{$i - }
reset (Fh) ;
if ioresult < > O then
begin
rewrite(Fh) ;
rewrite(F) ;


R:= Yacio {c onstante predefi n ida, parametr i za rbol vaco}
end
else begin
rese t (F) ;
if eof (Fh) then
R: = Yac io
402 Estructura de datos
else
read (Fh , R) {El pr ime r r egist ro es l a

r a l Z del rbo l Bl
end;
{ $ i + l
while not eo f (Fh ) do
begin
end;
r ead (Fh , 1 ) ;
Pme te r (Pila, I )
end
Procedimiento de Finalizar
Este procedimiento ser el ltimo en llamarse. En l se escribe como primer registro el
nmero de registro de la raz del rbol. A continuacin, los registros liberados que estn
en la pila.
procedure f in (var Fh: Fl ibr e ; var F: Arch ivo ;
var
H: Apuntador ;
begin
re set(Fh );
writ e( Fh , R) ;
R : Apunt ador; var Pi l a : Tpi la );
while not Pvaci a(Pi l a) do
begin
wr i t e (Fh , Ci ma (Pi la) ;
Pbo rrar (Pi la )
end;
close(Fh) ;
cl ose( F )
end;
Procedimiento de liberar un nodo

Simplemente mete en la pila de registros libres el nmero de registro donde est el nodo
a ser liberado.

procedure Liber ar (P: Apunt ador ; var Pi l a : Tpila) ;
begin
Pmeter( Pil a ,
end;
P) ;
Operacin de recorrido del rbol B
Recorre el rbol B que se encuentra en el disco. Pasa por cada una de las claves y son
escritas en pantalla.
procedure recorrer ( R: Ap un tador ; var F : Archivo) ;
var
1 : Po s i c i on ;
Pg : Pagi na;

,
,
,

: \

j
,



,
l

,
,
,
I
I
i
I
I
begin
if R <> v a cio then
end;
begin
seek( F ,R);
read(F , Pg) ;
recorrer(Pg . Ra mas[O ] ,F ) ;
for 1 :=1 to Pg. Cuenta do
begin
write(Pg . Cl aves [ 1 ], ' ');
recor rer (Pg . Ramas[I] ,F )
end
end
Unidad con las operaciones de rbol B en archivo
rboles B 403
A continuacin se muestra la unidad para realizar el tipo abstracto de datos rbol B en archivo.
A las rutinas anteriores, se aaden las ya escritas para el proceso de insercin y el
proceso de borrado de claves. Presentan pequeas diferencias debido fundamentalmente
a la no utilizacin de punteros para acceder a un nodo o pgina.
Ahora este acceso se realiza con:
seek ( F, R) ;
read (F , Pg) ;
Siendo F el archivo, R el nmero de registro y Pg el nodo.
Unidad para realizar el TAO rbol B de orden 5 en un archivo
unit ArbolB;
interface
uses Pi l aPu n;
const
Vaci o = 29999 ; {Mar ca que indi ca registro vac o}
Or den = 5 ;
Max= Orden- 1 ;
Min = (Orden -l)
type
{Nmero m x imo de claves en un nodo}
div 2 ; {"Nme r o m nimo de cl aves e n u n nodo disti nto de
la raz}
Tipoclave = i nteger; {Por comodidad en las pruebas adoptamos este t i po
de c lave}
posicion= o .. Max;
Pagina = record
Cue n ta : O .. Max;
Cl aves : array [1 .. Ma x ] of Tipoclave ;
Ramas : array [pos icion] of Apunt ador
end;
Archivo= file of Pagina;
Flibre= file of Apun t ador ;
var
Pila: Tpi l a;
function Hue co (var Pla :Tpi l a; var F : Archivo) : Apuntador;
,
"
"
j
o
,

I
t
I
:
I
!-
o
!
I
"
"
404 Estructura de datos
procedure Inicializa (var F : Archivo; var Fh : Flibre ;
var R: integer);
procedure Fin (var Fh : Fl i br e;var F: Archivo ; R: Apunt a dor) ;
procedure Li be r a r (P:Ap un t ado r ; var Pila : Tpil a );
procedure Recorrer (R: Apun tador; var F: a r chivo) ;
procedure Buscarnodo (Clave : Tipocl a ve ; P : Pagina ;
var En contrado : boolean; var K: Po sic i o n ) ;
procedure Bu scar (C l ave : Tipoclave ; R: Apu ntador ;
var Encontrado : boo l ean ; var Pos : Posicion ;
var P: Apunt ador ; var F: Ar chi vo) ;
function Arbolvac i o(R : Apuntador ) : boolean ;
{Oper a ciones especf i cas para el proceso de insercin}
procedure Inse r t a (Cl :Ti poc lave ; var R: Apunt ador ;
var F: Archivo) ;
procedure Empu j a r( Cl : Ti poc l ave ; R: Apunt ador ;
var Empu jaArri ba : boo l e an;
var Mdna : Ti p oc l ave ; var Xr : Apuntador;
var F: Arch i vo) ;
procedure Di vidi rNod o( X: Ti pocl ave ; Xder : Apuntador ;
var P: Pagi na; K: Pos i ci on ;
var Mda : Tipoc l ave ;var Xd : Apun t ador;
var F: Archi vo) ;
procedure Me te rHoj a(X : Tipoc lave ; Xder : Apun tad o r;
var P : Pagina ; K: Posicion);
{Oper a c i ones para el proceso de bor rado de una c l ave}
procedure Eli minar (Cl : Ti pocl ave ; var Raiz: Apu n tador;
var F: Ar c h ivo) ;
procedure Eli mina Regi s t ro (C l: Ti poclave ;var P : Apuntador;
var Encontrado: boolea n;var F: Ar chivo);
---- - -"
procedure Restablecer (P : Apuntador ; K:Posic i on ;var F : Archi vo) ;
procedure Qu itar ( P : Apun tador ; K: Posic i o n;" var F:Archivo) ;
procedure Sucesor (P : Apuntador; K: Posi cion; var F: Ar ch ivo) ;
procedure Moverderecha( P:Apun tador ; K: Pos i c i on ;var F : Archivo);
procedure Mover i zqu ier da(P : Apun tador ; K: Posic i o n;var F: Arc hi vo) ;
procedure Comb i na (P : Apuntador; K: Po sicion; var F:Ar chi vo) ;
implementation
function Ar bo lvac i o(R : Apu nt a dor) :boo l ean;
begin
Ar b olvacio := R=vac i o
end;
function Hue co (var Pl a : Tpi l a ;var F: Arc hi vo) : Apun tador ;
var
H:Apuntado r ;
begin
if not Pvac i a( Pl a) then
Ps acar (H, Pl a)
else
H: = f ilesize( F ) ;
Hueco: = H
end;
procedure I nicializa (var F: Archivo ; var Fh : Fl ibre ;
var R :integer ) ;
var
.'
"
.'
.'
o
.'
.'
;
.'
o
j
'1
-
.'
.'
,
" o
o


,





,
,

,


,
,
,
,
406 Estructura de datos
seek(F, R);
read (F, Pg);
recorrer(Pg.Ramas[O ) ,F);
for I:=1 to Pg.Cuenta do
begin
write(Pg.C1aves [I),' ');
recorrer(Pg.Ramas[I), F)
end
end
end;
procedure buscarnodo (Cl ave:Tipoc l ave; P : Pagi na;
var Enco ntrado: bool ean; var K: Posic i on) ;
begin
if Clave < P.Claves[l] then
begin
Encontrado:=false;
K:=O
end
elBe begin
K:= P.Cu enta ;

while (Clave < P.Claves[k)) and (k >l) do
k:=k-1;
Encontrado: = (Clave = P.Cl aves[k ) )
end
end;
procedure buscar (Clave: Tipoc l ave ; R: Apuntador;
var Encontrado :boolean;
var Pos: Posicion ; var P: Apuntador;
var F: Archivo) ;
var
Pg :Pagina;
begin
Encontrado:=false;
while not Encontrado and ( R <>
begin
seek(F,R) ;
read(F,Pg) ;
,
vaClO ) do
buscarnodo(Clave, Pg, Enc ontrado , Pos) ;
if Encontrado then
P: = R
elBe
end
end;
R:= Pg.Ramas[Pos)
procedure Inserta (Cl:Tipoclave; var R: Apuntador ;var F : Archivo);
var
P: Pagina;
Sube: boolean;
Mdna: Tipoclave;
N, Xr: Apuntador;
begin
Empujar(Cl,R,Sube,Mdna,Xr,F) ;
if Sube then
- - - _.- _._-
begin
P.Cuenta:=l;
P . C 1 ave s [1] : = Mdna;
P.Ramas [0] := R;
P . Ramas [1] : = Xr;
N:= Hueco (Pila, F);
seek(F , N);
wr i t e (F, P);
R:= N
end
end;
procedure Empujar ( Cl: Tipoclave ; R: Apuntador;
var Empu j aArri b a : boolean ;
var
var Mdna: Tipo clave; var Xr:Apuntador;
var F: Archivo);
K: Posicion;
Pg: Pagina ;
Esta : boolean;
begin
if R= vacio tben
begin
Empu j aArriba:=true;
Mdna: =C l;
Xr:=vacio
end
else begin
s eek(F ,R) ;
read(F ,Pg) ;
buscarnodo(Cl,Pg,Esta,K) ;
if Esta tben
begin
writel n ( ' Clave ya e xi s te. Revisar c di go');
ha lt (1)
end
else begin
Empujar ( Cl ,pg.ramas [ K] ,EmpujaArriba , Mdn a,Xr,F);
if EmpujaArriba then .
if Pg .Cuenta < Max then
begin
EmpujaArriba:=false;
Meterhoja(Mdna,Xr,Pg,K) ;
seek(F,R) ;
write(F,Pg)
end

rboles B 407
else begin
Empu j aArriba : =true;Di vi dirNodo(Mdna,Xr , Pg,K,Mdna,Xr,F) ;
seek( F ,R);
end
end;
wri t e(F,Pg)
end
end

,
,
,

I
,
408 Estructura de datos
procedure Div i di r Nodo(X : T ipoc l ave ; Xd er : Apuntador ;
var P : Pag i na ; K: Pos i cion;
var
Mde : Pagina;
j , i ,pos:intege r;
begin
if K< = Min then
pos := Mi n
else
pos := Mi n+l ;
var Md a : T i pocl a ve ;var Xd : Ap u n tador ;
var F : Arch i vo) ;
xd : = Hueco( P ila ,F ) ;
for i:= pos+1 to Ma x do
begin
Mde . Claves [ i - pos J : =P . Claves [ i J;
Mde . Ra ma s [i- pos J : =P . Ramas [i J
end
Mde . Cuenta:= Ma x- pos ;
P . Cu e nta:=pos;
if K< = Min then
Met e r hoja ( X,Xder , P , K)
el se
Meterho ja(X, Xde r , Mde , K- pos) ;
Mda : = P . Cl aves [P . CuentaJ ;
Mde . Ramas [ Ol:= P.Ra mas [ P . Cuen t al;
P . Cue n ta := P . Cue n ta - 1 ;
seek ( F ,Xd ) ;
write(F , Md e) ;
end
procedure MeterHoja(X : T i poc l a ve; Xder: Apu n tador ;
var P : Pagina; K: Posic i on) ;
var
i:integer;
begin
for i := P. Cuenta downto K+1 do
begin
P . C 1 a v e s [ i + 1 J : = P . C 1 a ves [ i J ;
P . Ramas[i +1 J : = P . Ramas[iJ
end
P . Cl a v es[k+l1
. - X
. - ,
P. Ra mas [k+l1 : = Xder ;
P . Cu e nta:= P. Cuen ta +l
end;
procedure Eli mi n ar (C l: T i poc l ave ; var Raiz : Apuntador;
var F : Archivo) ;
var
Aux : Apun t ador ;
Encon tra do : boolea n;
Pg : Pag i n a;
i




;


I
I


--'!
.1
1
,
1
1



begin
EliminaRegistro(Cl,Raiz,Encontrado,F) ;
if not Encontrado then
writeln( 'No Encontrada la clave a eliminar')
else begin
seek(F,Raiz) ;
read(F,Pg) ;
if Pg.Cuenta = O then
begin
Aux:= Raiz;
Raiz:= Pg.Ramas[O];
Liberar(Aux,Pila)
end
end
end;
procedure EliminaRegistro (Cl:Tipoclave;var P:Apuntador;
var Encontrado:boolean;var F: Archivo);
var
K: Posicion;
Aux,Pg: Pagina;
begin
if P= vacio then
Encontrado:=false
else begin
seek(F,P);
read (F, Pg) ;
with Pg do
begin
buscarnodo(Cl,Pg,Encontrado,K) ;
if not Encontrado then
EliminaRegistro (Cl,Ramas[K] ,Encontrado,F)
else if Ramas[O]= vacio then
Quitar(P,K,F)
el se begin
Sucesor(P,K,F) ;
seek(F,P); {De nuevo se lee porque ha cambiado}
read (F, Pg) ;
rboles B
EliminaRegistro(claves[K] ,Ramas[K], Encontrado,F)
end;
if Ramas[K]< > vacio then
begin
seek(F,Ramas[K]) ;
read (F, Pg) ;
if Cuenta< Min then
Restablecer(P,K,F)
end
end
end
end;
procedure Restablecer (P: Apuntador; K: Posicion; var F:Archivo);
var
J: Apuntador;
Aux: Pagina;
409
410 Estructura de datos
begin
seek(F,P);
read (F, Aux) ;
if K > o then
begin
J:=Aux.Ramas[K-l] ;
seek(F,J) ;
read ( F , Aux) ;
if Aux.Cuenta > Min then
Moverderecha(P,K,F)
else
Combina(P,K,F)
end
else begin
seek(F,P);
read (F , Aux) ;
end;
j:= Aux.Ramas[l];
seek(F,J);
read ( F , Aux) ;
if Aux.Cuenta > Min then
Moverizquierda(P,l,F)
else
Combina(P,l,F)
end
procedure Quitar(P:Apuntador; K: Posicion; var F: Archivo);
var
i: Apuntador;
Pg: Pagina;
begin
seek(F,P);
read(F,Pg) ;
for i:=k+l to Pg.Cuenta do
begin
Pg.Claves [i-l]:= Pg.Claves [i];
Pg.Ramas[i-l]:= Pg.Ramas[i]
end;
Pg.Cuenta:= Pg.Cuenta-l;
seek(F,P);
write(F,Pg)
end;
procedure Sucesor(P:Apuntador; K: Posicion; var F: Archivo);
var
D: Tipoclave;
Q: Apuntador;
Aux,Pg:Pagina;
begin
seek(F,P);
read(F,Pg) ;
Q:= Pg.Ramas[k];
seek (F, Q) ;
read (F , Aux) ;


i
while Aux.Ramas[O] <> vaci o do
begin
seek(F,Aux.Ramas[O ]) ;
read(F,Aux)
end;
D:=Aux.Claves[l] ;
Pg.Claves[K]
seek(F,P);
write(F,Pg)
end;
' - D' . - ,
rboles 8 411
procedure Moverderecha (P:Apuntador ; K: posicion; var F:Archivo);
var
j:Apuntador;
Aux,Auxiz,Auxdr:Pagina;
begin
seek(F,P);
read(F,Aux) ;
seek(F,Aux.Ramas[k-1]) ;
read(F,Auxiz) ;
seek(F,Aux.Ramas[k]) ;
read(F,Auxdr) ;
for J: =Auxdr.Cuenta downto 1 do
begin
Auxdr. Claves [j + 1] : =Auxdr. Claves [j] ;
Auxdr.Ramas[j+l] :=Auxdr.Ramas[j]
end;
Auxdr.Ramas[l] :=Auxdr.Ramas [O ] ;
Auxdr.Cuenta:=Auxdr.Cuenta+1;
Auxdr.Claves[l] :=Aux.Claves[K];
Aux.Cl aves[k] : =Auxiz .Claves[Auxiz .Cuenta];
Auxdr.Ramas[O] :=Auxiz.Ramas[Auxiz.Cuenta];
Auxiz.Cuenta:=Auxiz.Cuenta-l;
seek(F,P);
write (F , Aux) ;
seek(F,Aux.Ramas[k-1]) ;
wri te( F,Auxiz) ;
seek(F,Aux.Ramas[k]) ;
write(F,Auxdr)
end;
procedure Moverizquierda(P:Apuntador; K: Posicion; var F: Archivo);
var
Aux,Auxiz,Auxdr: Pagina;
J : Posicion;
begin
seek(F,P);
read(F,Aux) ;
seek(F,Aux.Ramas[K- 1]) ;
read(F,Auxiz) ;
seek(F,Aux.Ramas[K]) ;
read(F,Auxdr) ;
Auxiz.Cuenta:=Auxiz.Cuenta+1;
Auxiz.Cl aves[Auxiz.Cuenta] :=Aux.Claves[K];

,

i


412 Estructura de datos
Auxiz.Ramas[Auxiz.Cuenta) : =Auxdr.Ramas[O);
Auxdr.Ramas[O) : =Auxdr.Rama s [l);
Aux.Claves[K):= Auxdr.Cl ave s [l);
Auxdr.Cuenta:=Auxdr. Cuenta-l;
for j:=l to Auxdr. Cuenta do
begin
Auxdr. Claves [j) : =Auxdr. Claves [j +1) ;
Auxdr.Ramas[j) :=Auxdr.Ramas[j+l]
end;
seek ( F,P);
wr i te ( F , A ux) ;
seek(F,Aux.Ramas[k-l ] ) ;
wr i te(F,Auxiz) ;
seek(F,Aux.Ramas[k) ;
write(F,Auxdr )
end;
procedure Combina(P:Apuntador; K: Posicion; var F:Archivo);
var
Dc ho, Izqdo:Apuntado r;
j: Posicion;
Aux,Auxiz,Auxdo :Pagina;
begin
seek(F,P) ;
read(F,Aux) ;
Dcho:=Aux.Ramas[k) ;
Izqdo:=Aux.Ramas[k-l) ;
seek ( F,Dcho) ;
read(F,Auxdo) ;
seek(F,Izqdo) ;
read(F,Auxiz) ;
Auxiz.Cuenta:=Auxiz.Cuenta+l;
Auxiz.Claves[Auxiz.Cuenta] :=Aux.Claves[k];
Auxiz.Ramas[Auxiz. Cuenta] :=Auxdo.Ramas[O];
for j:=l to Auxdo .Cuenta do
begin
Auxiz.Cuenta:= Auxiz.Cuenta+l;
Auxiz.Claves[Auxiz.Cuenta) :=Auxdo.Claves[j ) ;
Auxiz.Ramas[Auxiz. Cuenta) :=Auxdo.Ramas[j)
end;
for j:= K to Aux.Cuenta - l do
begin
Aux. Claves [j] : =Aux. Claves [j +1] ;
Aux.Ramas[j] :=Aux.Ramas[j+l]
end;
Aux.Cuenta:=Aux.Cuenta-l ;
seek(F,P);
write (F, Aux) ;
seek (F, 1 zqdo) ;
write(F,Auxiz) ;
liberar(Dcho,Pila)
end;
begin
end.

,
','

;(
.. .

. ~
; ~
,


,
!
I

~
)
j
,
1
,
..
1
,




,
,


Programa de gestin de un rbol B
en memoria externa
program Arbol_b;
uses crt, ArbolB,Pilapun;
const
B= 999;
var
F:Archivo;
Fh:Flibre;
Apun,R,D:Apuntador;
Re, L, Cl: integer;
Pos:Pos i c i o n;
Encon t rado:boolean;
Res:char;
begin
R:=vacio;
c lrscr;
Ini c ializa (F, Fh, R) ;
randomize;
writeln ('Elementos presentes');
Re correr(R,F) ;
repeat
writel n ;
writeln('l. Aadir claves');
writeln(' 2 . Eliminar Clave ');
writeln('3. SALIR');
repeat
Readln(Re)
until Re

ln [1 .. 3];
if Re= 1 then
begin
for L:=l to 2 do
begin
Cl: = random (B) ;
Buscar(Cl,R,Enco ntrado,Pos,D,F) ;
if not Encontrado then
Inserta( Cl,R,F)
end;
writeln;
Recorrer(R,F) ;
end;
if Re= 2 then
begin
writeln('Clave a e liminar');
readln(Cl) ;
Eliminar(Cl,R,F) ;
Recorrer(R,F )
end
until (Re = 3);
Fin(Fh,F,R);
repeat until keypressed
end.

rboles B 413

,
1
.

I
i


414 Estructura de datos
RESUMEN
Un rbol-B es una estructura de datos que se puede utilizar para implementar una tabla que reside
en memoria externa, tal como un disco. Los rboles B se denominan tambin rboles 2-3 y son
una clase de rboles no binarios sino ternarios, que obligan a que todas las hojas se encuentren al
mismo nivel.
Un rbol 2-3 permite que el nmero de hijos de un nodo interno varen entre dos y tres. Un
rbol2-3 es un rbol en el que cada nodo interno (no hoja) tiene dos o tres hijos y todas las hojas
estn al mismo nivel. Una definicin recursiva de un rbol 2-3 es: T es un rbol 2-3 de altura h si:
l. T est vaco (un rbol 2-3 de altura O).
o alternativamente:
2. T es de la forma
r
donde r es un nodo y TI Y T o son los dos rboles 2-3, cada uno de altura h-l. En este
caso, TI se llama subrbol izquierdo y Tose llama subrbol derecho.
O bien,
3. T es de la forma
donde r es un nodo y T" Te, T
D
son rboles 2-3, cada uno de altura h-l. En este caso, TI
se llama subrbol izquierdo, Te se llama subrbol central y Tose llama subrbol derecho.
Un rbol 2-3 no es necesariamente binario, pero est siempre equilibrado:
50 90
120 150
30 40 100 100 120 150 175
En un rbol 2-3, los nodos internos pueden tener dos o tres hijos, permitiendo que el nmero
de hijos vare; los algoritmos de insercin y supresin pueden mantener fcilmente el equilibrio
del rbol.

,
!
f
,
. . . .-
rboles B 415
EJERCICIOS
12.1. Dada la secuencia de claves enteras: 190,57,89,90,121,170,35,48,91,22,126,132
Y 80, dibuja el rbol B de orden 5 cuya raz es R, que se corresponde con dichas claves.
12.2. En el rbol R del problema 1, elimina la clave 91 y dibuja el rbol resultante. Vuelve a
eliminar, ahora, la clave 48. Dibuja el rbol resultante, ha habido reduccin en el nme-
ro de nodos?
12.3.
12.4.
12.5.
12.6.
12.7.
12.8.
12.9.
12.10.
12.11.
12.12.
Modifique la rutina de insercin de un rbol B de orden m para que si se intenta aadir
una clave a un nodo que ya est lleno, se efecte una bsqueda de un hermano no lleno
antes de partir el nodo.
En un rbol B de orden 5 se insertan las claves 1, 2, 3, ... n. Qu claves originan la
divisin de un nodo? Qu claves hacen que la altura del rbol crezca?
En el rbol B de orden 5 del ejercicio 12.4, las claves se eliminan en el mismo orden de
creacin. Qu claves hacen que los nodos se queden con un nmero de claves menor
que el mnimo y den lugar a la unin de dos nodos? Qu claves hacen que la altura del
rbol disminuya?
Prevemos tener un archivo de un milln de registros, cada registro ocupar 50 bytes de
memoria. Los bloques de memoria son de 1.000 bytes de longitud y adems hay un pun-
tero por cada bloque que ocupa 4 bytes de memoria. Disear una organizacin con rbo-
les B para este archivo.
El procedimiento de bsqueda de una clave se ha realizado con una llamada recursiva al
final del procedimiento. Volver a escribir el procedimiento eliminando la llamada recursiva.
Un rbol B* es un rbol B en el que cada nodo est, al menos, lleno en las dos terceras
partes (en vez de la mitad), menos quizs el nodo raz. La insercin de nuevas claves en
el rbol B* supone que si el nodo que le corresponde est lleno mueve las claves a los
nodos hermanos (de manera similar a como se mueven en la eliminacin cuando hay que
restaurar el nmero de claves de un nodo). Con 10 cual se pospone la divisin del nodo
hasta que los dos nodos hermanos estn completamente llenos. Entonces, stos pueden
dividirse en tres nodos, cada uno de los cuales estar lleno en sus dos terceras partes.
Especifique los cambios que necesita el algoritmo de insercin de una clave en un rbol
B para aplicarlo a un rbol B*.
Dado un rbol B* segn est definido en 12.8, especificar los cambios necesarios que
necesita el algoritmo de eliminacin de una clave en un rbol B para aplicarlo a un
rbol B*.
Dada la secuencia de claves enteras del ejercicio 12.1: 190,57,89,90,121,170,35,48,
91, 22 , 126, 132 Y 80, dibuja el rbol B* de orden 5 cuya raz es R, que se corresponde
con dichas claves.
Con las claves del rbol B de orden 5 del ejercicio 12.4 dibuja un rbol B* de orden 5.
En el rbol B * de orden 5 del ejercicio 12.11, las claves se eliminan en el mismo orden
de creacin: 1, 2, 3, 4 ... n. Qu claves hacen que los nodos se queden con un nmero
de claves menor que el mnimo y den lugar a la unin de dos nodos? Qu claves hacen
que la altura del rbol disminuya?
PROBLEMAS
12.1. Dada la secuencia de claves enteras: 190, 57, 89, 90, 121, 170, 35, 48, 91, 22, 126, 132 Y
80, dibuja el rbol B de orden 5 cuya raz es R, que se corresponde con dichas claves.
Oo,
I

,
I
,

i
,
!
,
,
,
i

,

I
,
,
,

,
,

,
,
,
,
,
,


,
I
i

416 Estructura de datos


12.2. En el rbol R del problema 12.1 elimina la clave 01 y dibuja el rbol resultante. Vuelve a
eliminar ahora la clave 48. Dibuja el rbol resultante, ha habido reduccin en el nmero
de nodos?
12.3. Cada uno de los centros de enseanza del Estado consta de una biblioteca escolar. Cada
centro de enseanza est asociado con nmero de orden (valor entero), los centros de cada
provincia tienen nmeros consecutivos y en el rango de las unidades de 1.000. (As, a
Madrid le corresponde del 1 al 1.000; a Toledo, del 1.00 l al 2.000 ... )
Escribir un programa que permita gestionar la infolluacin indicada, formando una estruc-
tura en memoria de rbol B con un mximo de 6 claves por pgina. La clave de bsqueda
del rbol B es el nmero de orden del centro> adems tiene asociado el nombre del centro.
El programa debe permitir aadir centros, eliminar, buscar la existencia de un centro por la
clave y listar los centros existentes.
12.4. En el problema 12.3 cuando se termina la ejecucin se pierde toda la informacin. Pues
bien, modificar el programa 1 para que al terminar la informacin se grabe la estructura en
un archivo de nombre centros.txt.
Escribir un programa que pellllita leer el archivo centros.txt para generar a partir de l la
estructura de rbol B. La estructura puede experimentar modificaciones nuevos centros,
eliminacin de alguno existente , por lo que al terminar la ejecucin debe de escribirse
de nuevo el rbol en el archivo.
12.5. Se quiere dar ms contenido a la informacin tratada en el problema 12.3. Ya se ha especi-
ficado que la clave de bsqueda del rbol 8 es el nmero de orden del centro de ensean-
za. Adems, cada clave tiene que llevar asociada la raz de un rbol binario de bsqueda
que representa a los ttulos de la biblioteca del centro. El rbol de bsqueda biblioteca
tiene como campo clave el ttulo del libro (tiene ms campos como autor. .. ). Escribir un
programa que partiendo de la informacin guardada en el archivo centros.txt cree un nue-
vo rbol 8 con los centros y el rbol binario de ttulos de la biblioteca de cada centro.
12.6. A la estructura ya creada del problema 12.3, aadir las operaciones que responden a estos
requerimientos:
Dada una provincia cuyo rango de centros es conocido, por ejemplo de 3.001 a 3.780,
eliminar en todos sus centros escolares los libros que estn repetidos en cada centro, y
que informe del total de libros liberados.
Dado un centro n, en su biblioteca se desea que de ciertos libros haya m ejemplares
(por ejemplo, 5.)
,
CAPITULO
. ,
resentaclOn

O eraCIOneS
....... , .1" ,.,' " .. . " "', ..
,'.' . , .. ..
.... ,' ,' ," ',.
, "
CONTE
13.1. Grafos y aplicaciones.
13.2. Conceptos y definiciones.
13.3. Representacin de los grafos.
13.4. TAO grafo.
13.5. Recorrido de un grafo.
13.6. Componentes conexas de un grafo.
13.7. Componentes fuertemente conexas de un grafo.
13.8. Matriz de caminos.
13.9. Puntos de articulacin de un grafo.
RESUMEN.
EJERCICIOS.
PROBLEMAS.
Este captulo introduce al lector a conceptos matemticos importantes
denominados grafos que tienen aplicaciones en campos tan diversos
como sociologa, qumica, geografa, ingeniera elctrica e indus-
trial, etc. Los grafos se estudian como estructuras de datos o tipos abs-
tractos de datos. Este captulo estudia los algoritmos ms importantes
para procesar grafos. Tambin representa operaciones importantes y
algoritmos de grafos que son significativos en informtica.
13.1. GRAFOS Y APLICACIONES
Con los rboles binarios se han representado relaciones entre objetos en las que existe
una jerarqua. Con frecuencia, es necesario representar relaciones arbitrarias entre obje-
417
i

418 Estructura de datos
tos de datos. Los grafos se clasifican en dirigidos y no dirigidos y son modelos naturales
de tales relaciones. As, los grafos se usan para representar redes de alcantarillado, redes
de comunicaciones, circuitos elctricos, etc. Una vez modelado el problema mediante
un grafo se pueden hacer estudios sobre diversas propiedades. Para ello se utilizan algo-
ritmos concretos que resuelvan ciertos problemas.
La teora de grafos ha sido aplicada en el estudio de problemas que surgen en reas
diversas de las ciencias, como la qumica, la ingeniera elctrica o la investigacin ope-
rativa. El primer paso siempre ser representar el problema como un grafo. En esta re-
presentacin cada elemento, cada objeto del problema, forma un nodo. La relacin, co-
municacin o conexin entre los nodos da lugar a una arista, que puede ser dirigida o
bidireccional (no dirigida). En la Figura 13.1 aparece una red de comunicaciones.
Impresora

PC1
Servidor
PC2
Figura 13.1. Un grafo como red de comunicaciones.
13.2. CONCEPTOS Y DEFINICIONES
Un grafo consiste en un conjunto de vrtices o nodos V y un conjunto de arcos A. Se
representa con el par G = (V, A).
EJEMPLO 13.1
El conjunto de vrtices V = {l, 4,5,7, 9} Y el conjunto de arcos A = {(1,4), (5,1),
(7,9), (7,5), (4,9), (4,1), (1,5), (9,7), (5,7), (9,4)} forman el grafo no dirigido G = {V, A} .

Grafos. Representacin y operaciones 419


EJEMPLO 13.2
F
H
El conjunto de vrtices V = {C, D, E, F, H} Y el conjunto de arcos A = {(C,D,),
(D,F), (E,H), (H,E), (E,C)} forman el grafo dirigido G = {V, A}.
Un arco o arista est formado por un par de nodos y se escribe (u, v) siendo u, v el par
de nodos. Un grafo es dirigido (digrafo) si los pares de nodos que forman los arcos son
ordenados, se representan u v. El segundo ejemplo es un grafo dirigido.
Un grafo no dirigido es aquel que los arcos estn formados por pares de nodos no
ordenados, no apuntados, se representa u - v. El grafo del primer ejemplo no es dirigido.
Dado el arco (u, v) es un grafo, se dice que los vrtices u y w son adyacentes. Si el
grafo es dirigido, el vrtice u es adyacente a v, y v es adyacente de u. Un arco tiene, a
veces, asociado un factor de peso, en cuyo caso se dice que es un grafo valorado. Pense-
mos, por ejemplo, en un grafo formado por los pueblos que forman una comarca; un par
de pueblos est unido o no por un camino vecinal y un factor de peso que es la distancia
en kilmetros:
7
Lupiana ------------- Horche
5
15
6
Centenera -----------
Atanzn
12
7
Valfermoso
forman un grafo valorado no dirigido.
13.2.1. Grado de entrada, grado de salida
El grado es una cualidad que se refiere a los nodos de un grafo. En un grafo no dirigido
el grado de un nodo v, grado(v), es el nmero de aristas que contiene a v. En un grafo
dirigido se distingue entre grado de entrada y grado de salida; grado de entrada de un
nodo v, gradent(v), es el nmero de arcos que llegan a v, grado de salida de v, gradsal(v),
es el nmero de arcos que salen de v. A veces no se sabe distinguir entre arco y arista, la
diferencia est en qu aristas son arcos hacia los dos sentidos.
Por ejemplo, grado(Lupiana) = 3. Es el grafo dirigido del ejemplo 13.2,
gradent(D) = l Y el gradsal(D) = l.

420 Estructura de datos
13.2.2. Camino
Un camino P en grafo G de longitud n desde un vrtice Va a V
n
es la secuencia de n + 1
, .
vertlces:
tal que (v, V+I) E A(arcos) para O $; i $; n. La longitud del camino es el nmero de arcos
que lo forma.
EJE LO 13.3
PI = (4, 6, 9, 7) es un camino de longitud 3.
En algunos grafos se dan arcos desde un vrtice a s mismo (v, v), el camino v - v se
denomina bucle. No es frecuente encontrarse con grafos que tengan bucles.
Un camino P = (va, VI, V2' ... , v
n
) es simple si todos los nodos que forman el camino
son distintos, pudiendo ser iguales Va, V
n
(los extremos del camino). En el ejemplo ante-
rior PIes un camino simple.
Un ciclo es un camino simple cerrado, Va = V
n
de longitud 2, en definitiva compues-
to al menos por 3 nodos.
EJE LO 13.4
o E
Los vrtices (A, E, B, F, A) en este grafo dirigido forman un ciclo de longitud 4. Un
ciclo de longitud k se denomina k-ciclo. En el ejemplo 13.4 tenemos un 4-ciclo.
Un grafo no dirigido G es conexo si existe un camino entre cualquier par de nodos
que forman el grafo. En el caso de ser un grafo dirigido podemos distinguir entre fuerte-
mente conexo y conexo. Un grafo dirigido es fuertemente conexo si existe un camino
entre cualquier par de nodos que forman el grafo; un grafo dirigido es conexo si existe
una cadena que une cualquier par de vrtices. Un grafo completo es aquel que tiene un
arco para cualquier par de vrtices.
---- ----- - - _.- ----
Grafos. Representacin y operaciones 421
EJEMPLO 13.5
Grafo conexo Grafo fuertemente conexo
Grafo dirigido conexo
,
13.3. REPRESENTACION DE LOS GRAFOS
Al pensar en los tipos de datos para representar un grafo en memoria, se debe tener en
cuenta que se debe representar un nmero (finito) de vrtices y de arcos que unen dos
vrtices. Se puede elegir una representacin secuencial, mediante arrays; o bien una re-
presentacin dinmica, mediante una estructura multienlazada. La representacin me-
diante arrays se conoce como matriz de adyacencia, la representacin dinmica se deno-
mina lista de adyacencia. La eleccin de una manera u otra depender de las operaciones
que se apliquen sobre los vrtices y arcos.
13.3.1. Matriz de adyacencia
Sea G = (V, A) un grafo de n nodos, suponemos que los nodos V= {VI, V2, ... , v
n
} estn
ordenados y podemos representarlos por sus ordinales {l, 2, ... , n}. La representacin de
los arcos se hace con una matriz A de n x n elementos aij definida:
a
Ij
1 si hay un arco (v, v)
o si no hay arco (Vi' V)
la matriz se denomina matriz de adyacencia. En ocasiones la matriz de adyacencia es
una matriz boolean en la que el elemento aij es verdadero (true) si existe arco (Vi' V) Y
falso (fa/se) en caso contrario.
i

!
!
,
,


,
,
,
,
I
,
,
422 Estructura de datos
EJEMPLO 13.6
Sea el grafo dirigido de la figura siguiente
\.
Supongamos que el orden de los vrtices es el siguiente: {D, F, K, L, R}, Y por tanto
la matriz de adyacencia:
O 1
1 O
A= O O
O 1
1 O
EJEMPLO 13.7
l
O
O
l
O
o
O
O
O
O
o
O
O
O
O
Ahora el grafo de la figura es no dirigido.
La matriz de adyacencia:
O 1
1 O
A= O 1
1 O
1 O
O
1
O
1
1
1
O
l
O
O
1
O
l
O
O
2
Podemos observar qu es una matriz simtrica. En los grafos no dirigidos la matriz
de adyacencia siempre ser simtrica, ya que cada arco no dirigido (Vi' v) se correspon-
de con los arcos dirigidos (Vi' V), (V
j
, vJ
,
."
,
Grafos. Representacin y operaciones 423
Los grafos con factor de peso, grafos valorados, pueden representarse de tal forma
que si existe arco, el elemento aj es el factor de peso; la no existencia de arco supone
que aij es O o 00 (esto slo si el factor de peso no puede ser O). A esta matriz se la deno-
mina matriz valorada.

EJEMPLO 13.8
El grafo valorado de la figura es un grafo dirigido con factor de peso
Alicante
4
Barcelona
1
3
5 3 6 2
Reus
Cartagena Murcia
Si suponemos los vrtices en el orden V = {Alicante, Barcelona, Cartagena, Murcia,
Reus} la matriz de pesos P:
O 4 5 5 O
O O 3 6 3
P= 3 O O O O
O 2 O O O
O 1 O O O
Representacin en Pascal
Al ser una representacin esttica debe de estar previsto el mximo de nodos al que
puede llegar el grafo. Los nodos o vrtices tienen un identificador, los cuales se guardan
en un vector de cadenas. El tipo arco podramos representarlo con un registro con un
campo de tipo boolean, tomar el valor verdadero (true) si (v, v) es una arista, y en caso
necesario, falso (fa/se) otro campo de tipo numrico, que represente el factor de peso. La .
matriz de adyacencia que se representa es de tipo entero, tomando los valores de O al,
segn haya arco o no entre un par de vrtices.
const
Maxvert=20;
type
Indicevert = 1 .. Maxvert;


424 Estructura de datos
Ve r ti ce = s tr ing ;
Ve rti ces =array[Ind i c evert , Indi cevert ) of 0 .. 1
Gr a fo = record
N : Ind i c e ve r t ;
V: Ve r tices ;
A: Ma t Ad cia
end;
var
G: Gr afo
En el tipo Grafo est definido el campo N (opcional) para tener contabilizados el
nmero de vrtices, no pudiendo superar el mximo establecido. La matriz G es una
variable de tipo G r a f o. A es la matriz de adyacencia. En el caso de que el grafo sea con
factor de peso y ste sea de tipo numrico, puede asociarse directamente a la matriz, o
bien, definir el tipo arco:
type

Ar co - record
Ad t e : b oo lea n;
Pes o : rea l
end;
Mat Adcia = array [I ndicever t, I n diceve r t ) o f Ar co ;
13.3.2. Listas de adyacencia
La representacin de un grafo con matriz de adyacencia puede resultar poco eficiente en
algunos casos. As, cuando el nmero de vrtices vara a lo largo del proceso, dndose el
caso de que el nmero de ellos sea mayor que el previsto. Tambin cuando el grafo es
disperso, es decir, tiene pocos arcos, y por tanto la matriz de adyacencia tiene muchos
ceros (matriz sparce), resulta poco eficiente la matriz de adyacencia ya que el espacio
que ocupa es el mismo que si el grafo tuviera muchos arcos. Cuando se dan estas inefi-
ciencias se representa un grafo mediante listas enlazadas que se denominan listas de
adyacencia.
Las listas de adyacencia son una estructura multienlazada formada por una lista
directorio cuyos nodos representan los vrtices del grafo y del que adems emergen
una lista enlazada cuyos nodos, a su vez, representan los arcos con vrtice origen el
del nodo de la lista directorio. Con la figura siguiente nos acercamos a esta represen-
tacin de un grafo.
Grafos. Representacin y operaciones 425
La representacin de este grafo dirigido mediante listas de adyacencia:
1 3
2
3
4
5 1 2 4
Representacin en Pascal
Cada nodo de la lista directorio tiene que guardar el vrtice que representa, la direccin
de acceso a la lista de adyacencia (arcos que salen de dicho vrtice) y adems la direc-
cin del nodo siguiente de la lista directorio. Grficamente:
Vrtice Lista Adcia Sgte
Cada nodo de la lista de adyacencia de un vrtice del grafo almacena la direccin del
vrtice (en la lista directorio) con el que forma un arco, en caso de ser un grafo valorado
tambin el factor de peso, y como en todas las listas la direccin del nodo siguiente.
Grficamente:
Los tipos de datos:
type
PtrDir ANodoDir;
PtrAdy ANodoLy;
NodoDir record
Dir-Vrtice <Peso>
Vert : string; {identificador del vrtice}
Lady: PtrAdy;
Sgte : PtrDir
end;
Sgte





426 Estructura de datos
NodoLy = record
Pt r V: Pt rDi r ;
Pe s o : r e a l; {campo fa c tor de pe s o , e s op ciona l }
Sgte : Pt rAdy
end;
var
G : PtrDi r;

Con la variable puntero G se accede a la lista directorio, a partir de la cual se puede


acceder a las listas de adyacencia.
13.4. TAO GRAFO
Los grafos, al igual que las pilas, colas ... son tipos abstractos de datos. Ya hemos esta-
blecido los datos y su representacin, ahora definimos las operaciones bsicas sobre
esos datos y su realizacin que ser dependiente de la representacin de los datos.
La operacin unin (X, Y) aade el arco (X, Y) al grafo. En caso de ser un grafo
valorado se define la operacin unin-peso (X, Y, W) que aade el arco (X, Y) cuyo
factor de peso es W.
Operacin borr _arco (X, Y) elimina del grafo el arco (X, Y).
Operacin adyacente (X, Y), funcin lgica que debe devolver true si forman
un arco los vrtices (X, Y).
Operacin nuevo_vrtice (X) aade el vrtice X al grafo G.
Operacin borra_vrtice (X) elimina del grafo G el vrtice X.
Estas operaciones son el ncleo a partir del cual se construye el grafo. En la repre-
sentacin con listas encadenadas se hace uso de las operaciones propias de una lista
enlazada.
13.4.1. Realizacin con matriz de adyacencia
En esta realizacin los vrtices estn representados por el ordinal (1..n) dentro del con-
junto de vrtices.
Operacin unin
procedure uni on (var G : Gra fo ; Vl, v2 : Indiceve rt);
begin
G.A[ Vl, V2 l : = 1;
end;
Para un grafo valorado
procedure un ion_peso (var G: Grafo ; Vl , V2 : I ndi cever t , W: r eal) ;
begin
!
!
,



G.A[V1, V2] .Adye := true;
G.A[V1,V2] .Peso := W
end;
La operacin que elimina un arco
Grafos. Representacin y operaciones 427
procedure borr_arco (var G:Grafo; V1, V2: Indicevert)
begin
G.A[V1,V2] := O;
end;
La operacin adyacente (X, Y)
function adyacente (G:Grafo; V1,V2:Indicevert): boolean;
begin
adyacente := G.A[V1,V2] = 1;
end;
La operacin nuevo-vrtice (X)
procedure Nuevo_vertice (var G:Grafo; X:string);
begin
with G do
begin
if N<=Maxvert
begin
N := N+1;
V[N]
end
.- X
. - ,
then
else {Error: no es posible nuevos nodos}
end
end;
Operacin borra_vrtice (X) elimina del grafo G el vrtice x.
La operacin de eliminar un vrtice del grafo no slo supone suprimirlo de la lista de
vrtices, sino que adems se debe ajustar la matriz de adyacencia, ya que el ndice de los
vrtices posteriores al eliminado debe quedar decrementado en l.
procedure borra_vertice(var G:Grafo; X:string);
var
I:Indicevert;
P:integer;
begin
P : = Ordinal (G, X) ;
with G do
begin
if P in [1 .. N] then
begin
{Eliminacin de vrtice X}
for 1 := P to N-1 do
V[I] := V[I+1];
{Ajuste de matriz de adyacencia}
{Desplaza columnas}
428 Estructura de datos
for C := P to N-1 do
for 1 := 1 to N do
A[I,C] := A[I,C+1];
{Desplaza filas}
for 1 := P to N-1 do
for C := 1 to N do
A[I,C] := A[I+1,C]
{Se reduce el nmero de vrtices}
N := N-1
end
el se {Vrtice no existe en el grafo}
end
end;
La operacin Ordinal (es una operacin auxiliar).
function Ordinal(G:Grafo; X:string): integer;
var
1 : 1ndicevert
Rd : integer;
begin
Rd:=-l; 1:=0;
while (I<G.N) and (Rd - -1) do
begin
1 : = 1+1
if G.V[I] - X then
Rd := 1
else
1 : = 1+1
end;
Ordinal := Rd
end;
13.4.2. Realizacin con listas de adyacencia
Las operaciones bsicas con listas se implementan con variables puntero y variables
dinmicas. Algunas operaciones son similares a las realizadas con el TDA lista, a pesar
de lo cual son realizadas. As, la operacin auxiliar para crear un vrtice.
function Crearvt (Vt: string) : PtrDir;
var
V:PtrDir;
begin
new(V) ;
VA.Vert
VA.Lady
Crearvt
end;
-
-
-
-
-
-
Vt;
nil;
V
Operacin unin.
VA.Sgte := nil;
Dado el grafo y dos vrtices que forman un arco se aade el arco en la correspon-
diente lista de adyacencia. La realizacin de unin_peso slo presenta la diferencia de
asignar el factor de peso al crear el nodo de la lista de adyacencia.
Grafos. Representacin y operaciones 429
procedure uni o n (var G:PtrDir ; VI, V2 :st r ing);
var
P,Q : PtrDir;
begin
P := Direc cion( G,VI ) ;
Q := Direccion(G,V2);
if (P<>nil) and (Q<>n il ) then
with pA do
if Lady = nil then {l i s t a de adyacencia est vaca}
Lady := CrearLy(Q)
el Be
Ultimo(Lady) A. Sgte : = CrearLy(Q)
end;
Han surgido operaciones auxiliares, como Direccin y Ultimo. La primera
operacin devuelve un puntero al nodo de la lista directorio donde se encuentra un vr-
tice; la segunda operacin devuelve un puntero al ltimo nodo de la lista. Los cdigos de
ambas funciones son:
function Direccion(G: PtrDir; v : string): PtrDir;
var
P,D: PtrDir;
begin
P:= n il; D := G;
while (P=n il) and (D<>n i l ) do
if DA. Ve rt = V then
P : = D
elBe D := DA . Sgte ;
Direcc ion := P
end;
function Ultimo(L: PtrAdy): PtrAdy;
begin
if L<>nil then
while LA . Sg te<>nil do
L
.-
. -
Ultimo
end;
LA. Sg te;
. - L
. -
Operacin elimina arco: Una vez encontrada la lista de adyacencia se procede a
eliminar el nodo que representa el arco.
procedure borr_arco(var G:PtrDir; VI,V2:st ring) ;
var
P , Q: Pt rDir;
R,W: Ptrady;
Sw: boo l ean ;
begin
P : = Direcc i o n (G , VI) ;
Q : = Direcc i o n( G, V2) ;
if (P<>nil ) and (Q<>n i l ) then
begin
R := PA . Lady ; W := nil; Sw : = f a lse;
while (R<>n i l) and not Sw do
if RA.PtrV = Q then
430 Estructura de datos
begin
if W = nil then
PA.Lady := RA.Sgte
elBe
WA.Sgte := RA.Sgte;
dispose (R) ;
Sw := true
end
elBe begin
W : = R;
R := RA.Sgte
end
end;
end;
Operacin Adyacente.
function Adyacente(G: PtrDir; Vl,V2: string) :boolean;
var
P,Q: PtrDir;
R,W: Ptradv;
Sw: boolean;
begin
P := Direccion(G,Vl),
Q := Direccion(G,V2);
if(P<>nil)and(Q<>nil) then
begin
{Proceso de bsqueda}
R := PA.Lady; Sw := false;
while(R<>nil) and not Sw do
begin
Sw := RA.PtrV = Q;
if not Sw then R := RA.Sgte
end;
Adyacente := Sw
end
elBe Adyacente := false
end;
Operacin Nuevo_vertice (X).
Aade un vrtice X del grafo a la lista directorio. Siempre se aade como ltimo
nodo.
procedure Nuevo_vertice(var G: PtrDir; x: string);
begin