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 ST o LOUIS TOKIO. TORONTO
,

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 Ma ster 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

...,-'..
,

..

.
,


Prlogo .................................................................................................................... . XXI

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 .................................................. .. 3
1.1. IAbstraccin; ...................................................................................... . 4
1.2. Resolucin de problemas y programacin ..................................... . 4
l.3. Herramientas para la resolucin de problemas .............................. .
1.3.1. Diseo descendente ........................................................... . 5
1.3.2. Abstraccin procedimental ............................................... . 6
1.3.3. i Abstraccin de datos ......................................................... . 7
l.3.4. Ocultacin de la informacin .......................................... .. 7
l.3.5. I Programacin orientada a objetos ................................... .. 7
1.4. Factores en la calidad del software ............................................... .. 8
l.5. El ciclo de vida del software ......................................................... .. 9
1.5.1. Anlisis .............................................................................. . lo:"""'"
1.5.2. Diseo ................................................................................ . 11
1.5.3. Implementacin (codificacin) ........................................ .. 12
. .. Pmebas e In
154 ' tegraclon " ........................................................ . 13
1.5.5. Verificacin ....................................................................... . 13
1.5.6. Mantenimiento .................................................................. . 14
l.5.7. La obsolescencia: programas obsoletos .......................... . 15
l.5.8. Iteracin y evolucin del software ................................... . 15
1.6. Mtodos formales de verificacin de programas ........................... . 16
1.6.1. Aserciones (asertos) ......................................................... . 16
1.6.2. Precondiciones y postcondiciones ................................... . 17
l.6.3. Reglas para prueba de programas .................................... . 17
l.6.4. Invariantes de bucles ......................................................... . 19
l.6.5. Etapas a establecer la exactitud (correccin) de un pro-
grama ................................................................................. . 22
l. 7. Principios de diseo de sistemas de software ................................ . 23
1.7.1. Modularidad mediante diseo descendente ..................... . 23
1.7.2. Abstraccin y encapsulamiento ...................................... .. 24
1.7.3. Modificabilidad ......................................... .............. ......... .. 25

"
VII

viii Estructura de datos

1.7.4. Comprensibilidad y fiabilidad ......................................... . 26


1.7.5. Interfaces de usuario ........................................................ . 26
1. 7 .6. Programacin segura contra fallos .................................. . 26
1.7.7. Facilidad de uso ............................................................... . 27
1.7.8. Eficiencia .......................................................................... . 27
1.7.9. Estilo de programacin, documentacin y depuracin ... 28
1.8. Estilo de programacin ............................... o., 28
1.8.1. Modularizar un programa en subprogramas ................. .. 29
1.8.2. Evitar variables globales en subprogramas .................... . 29
1.8.3. Usar nombres significativos para identificadores .......... . 30
1.8.4. Definir constantes con nombres ...................................... . 31
1.8.5. Evitar el uso de got o ..................................................... . 31
1.8.6. Uso adecuado de parmetros valor/variable .................. .. 31
1.8.7. U so adecuado de funciones ............................................ .. 32
1.8.8. Tratamiento de errores ..................................................... . 32
1.8.9. Legibilidad ~ ...................................................................... . 33
1.9. La documentacin ................................................................. ~ .......... . 35
1.9.1. Manual del usuario ........................................................... . 35
1.9.2. Manual de mantenimiento (documentacin para progra-
madores) ........................................................................... . 36
1.9.3. Documentacin interna .................................................... . 37
1.9.4. Documentacin externa .................................................. .. 37
1.9.5. Documentacin del programa ........................................ .. 37
l. 10. Depuracin .................................... oo 38
1.1 0.1. Localizacin y reparacin de errores .............................. . 39
l.l 0.2. Los equipos de programacin ........................................ .. 41
1.11. . Diseo de algoritmos ....................................................................... . 42
1.12. Pruebas (testing) .............................................................................. . 42
1.12.1. Errores de sintaxis (de compilacin) .............................. . 44
l.l2.2. Errores en tiempo de ejecucin ...................................... .. 45
1.12.3. Errores lgicos ................................................................. . 45
1.12.4. El depurador ..................................................................... . 46
1.13. Eficiencia ......................................................................................... . 46
l.l3.1. Eficiencia versus legibilidad (claridad) .......................... . 49
1.14. Transportabilidad ............................................................................. . 49
, Resumen ........................................................................................................ . 49
, ..
,, E]erCIClos ...................................................................................................... . 50
Problemas ...................................................................................................... . 51
.
,

Captulo 2. Construccin de grandes programas: mdulos versus uni-


dades .................. ......... .................. ........................ ..... ....................... 53
2. l. Concepto de unidad.... ............. ................... ...................................... 54
2.2. Estructura de una unidad.................................................................. 54
,

Contenido ix
.
2.2.1. Cabecera de la unidad ....................................................... . 55
2.2.2. Seccin de interfaz ............................................................ . 55
2.2.3. Seccin de implementacin .............................................. . 56
2.2.4. Seccin de iniciacin (inicializacin) ............................. . 57
2.2.5. Ventajas de las unidades ................................................... . 57
2.3. Creacin de unidades ...................................................................... . 57
2.3.1. Construccin de grandes programas ................................ . 61
2.3.2. Uso de unidades ................................................................ . 61
2.3.3. Declaraciones/infonnacin pblica y privada ................. . 62
2.3.4. Clusula uses en la seccin de implementacin .......... . 63
2.4. Utilizacin de unidad estndar ....................................................... . 65
2.4.1. Unidad System ................................................................ 66
2.4.2. Unidad Crt ....................................................................... . 66
2.4.3. Unidad DOS ....................................................................... . 67
2.4.4. Unidad Printer ............................................................. . 68
2.4.5. Unidad Graph ................................................................... 68
2.5. Situacin de las unidades en sus discos: dnde busca Turbo Bor-
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 ............................................................................ .

74
2.8.1. Los archivos de inclusin o incluidos (include) ............. . 74
2.8.2. Los solapamientos (overlays) ................................ :.......... . 75
2.8.3. La unidad OverIay (generacin de solapamientos) ......... . 76
2.8.4. Encadenamiento de archivos compilados ........................ . 79
Resumen .............................................................,......................................... . 79
..

E1erClClOS .................................................................................................... . 79
Referencias bibliogrficas ......................................................................... . 82

r
Captul 3.,
I 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 .......................................... .
X Estructura de datos

3.3.
,.'.NI odularldad
. .
..................................................................................... . 89
3.3.1. La estructura de un mdulo ............................................. . 90
3.3.2. Reglas de modularizacin ............................................... . 91
3.4. Diseo de mdulos .......................................................................... . 94
3.4.1. Acoplamiento de mdulos .............................................. .. 94
3.4.2. Cohesin de mdulos ..................................................... .. 95
3.5. Tipos de datos ........................................ o 96
3.6. Abstraccin en lenguajes de programacin ................................... . 97
3.6.1. Abstracciones de control ................................................. . 97
3.6.2. Abstracciones de datos ................................................... .. 98
3.7. Tipos abstractos de datos (TAD) .................................................... . 99
3.7.1. Ventajas de los tipos abstractos de datos ........................ . 101
3.7.2. Implementacin de los TAD .......................................... .. 101
3.8. Tipos abstractos de datos en Turbo Borland Pascal ...................... . 102
3.8.1. Aplicacin del tipo abstracto de dato pila ..................... . 104
3 ..
9 . , b'
Orlentaclon a o ~etos ...................................................................... . 105
3.9.1. Abstraccin ...................................................................... . 107
. 3.9.2. Encapsulacin .................................................................. . 107
3.9.3. Modularidad ..................................................................... . 107
3.9.4. Jerarqua .................................................. ......................... . 108
3.9.5. Polimorfismo .................................................................... . 108
3.9.6. Otras propiedades ............................................................ . 109
3.10. Reutilizacin de software ............................................................... .. 110
3.11. Lenguajes de programacin orientados a objetos .......................... . 111
3.11.1. Clasificacin de los lenguajes orientados a objetos ...... . 112
3.12. Desarrollo tradicional frente a desarrollo orientado a objetos .... .. 116
3.13. Beneficios de las tecnologas de objetos ....................................... .. 118
Resumen ........................................................................................................ . 120
..
EjerCIClOS ...................................................................................................... . 120

PARTE 11. FUNDAMENTOS BSICOS DE ESTRUCTURAS DE DATOS


Y TIPOS ABSTRACTOS DE DATOS

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 130
4.3.1. Procedimiento New ........................................................... . 130
. 4.3.2. Variables de puntero con registros ................................... . 134
!,
4.3.3. Iniciacin y asignacin de punteros ................................. . 135
i

Contenido xi

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

143
4.5.2. Mtodos de asignacin y liberacin de memoria ............ . 145
4.5.3. New y Dispose ............................................................... 145
4.5.4. Mark y Release ........................................................... . 146
4.5.5. GetMem y FreeMem ...................................................... . 146
4.5.6. MemAvail y MaxAvail ............................................... . 147
Resumen ..................................................................................................'... . 148
..
EJerCICIOS ................................................................................ 149
Problemas ................................................................................................... .

152

Captulo 5. IListas -enlazadas: el TAD lista enlazada ...................................... 153


5.1. Especificacin formal del tipo abstracto de datos lista ................. . 153
5.2. Implementacin del TAD lista con estructuras estticas .............. . 156
5.3. Implementacin del TAD lista mediante variables dinmicas ...... . 159
5.4. Iniciar una lista enlazada ................................................................ . 162
5.5. Bsqueda en listas enlazadas .......................................................... . 162
5.6. Operaciones de direccin: siguiente, anterior, ltimo ................... . 163
5.7. Insercin de un elemento en una lista ............................................ . 164
5.8. Supresin de un elemento de una lista ........................................... . 166
5.9. Recorrido de una lista ..................................................................... . 168
5.10. Lista ordenada ................................................................................. . 168
5.10.1. Implementacin de una lista ordenada ............................ . 168
5.10.2. Bsqueda en lista ordenada .............................................. . 170
Resumen ........................................................................................................ . 175
..
EJerclclos ...................................................................................................... . 176
Problemas ...................................................................................................... . 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 es d'
rla .
lnamlcas ............................................................................. . 180

6.2.1. Creacin de nodos en la lista ........................................... . 181
1
6.2.2. Eliminacin de nodo ......................................................... . 184
6.3. Una aplicacin resuelta con listas doblemente enlaZadas ............. . 186
6.4. Implementacin de una lista circular mediante variables dinmicas ... . 195
t

xii Estructura de datos

6.5. Implementacin de una lista circular mediante variables dinmicas ... . 196
6.6. Implementacin de listas circulares con doble enlace .................. . 200
Resumen .............................................................. o 203
..
EJerclclos .................................................................................................... . 204
Problemas ................................................................................................... . 204
Captulo 7. IPilas: el TAD pi 1 a ......................................................................... 207
7.1. Especificacin formal del tipo abstracto de datos pila ................. . 207
7.2. Implementacin del TAD pila con arrays .................................. . 208
7.3. Implementacin del TAD pi 1 a mediante variables dinmicas ... . 211
7.4. Evaluacin de expresiones aritmticas mediante pilas ................. . 215
7.4.1. Notaciones Prefija (Polaca) y Postfija (Polaca inversa) .. 215
7.4.2. Algoritmo para evaluaciones de una expresin aritmtica .... 216
7.5. Aplicacin prctica de la evaluacin de una expresin aritmtica 218

7.5.1. Unidad Pilaop ................................................................ . 218
7.5.2. Unidad ExpPost (transformacin a postfija) ............... . 220
7.5.3. Evaluacin de la expresin en postfij a ............................ . 222
Resumen ...................... a 224
..
EJerclclos .................................................................................................... . 225
Problemas ................................................................................................... . 225

Captulo 8. fColas y colas de prioridades: el TAD cola .................................. 227


8.1. Especificacin formal del tipo abstracto de datos cola ................. . 228
8.2. Implementacin del TAD cola con arrays lineales ........................ . 229
8.3. Implementacin del TAD cola con arrays circulares .................... . 231
8.4. Implementacin del TAD cola con listas enlazadas ...................... . 235
8.5. Implementacin del TAD cola con listas circulares ...................... . 237
8.6. Bicolas .............................................................................................. . 239
8.7. Colas de prioridades ........................................................................ . 244
8.8. Implementacin de colas de prioridades ....................................... .. 245
8.8.1. Implementacin mediante una nica lista ....................... . 245
8.8.2. Implementacin mediante una lista de n colas ................ . 246
8.9. Implementacin de un problema con colas de prioridades ........... . 247
Resumen ..................................................................................................... . 256
..
EJerclclos .................................................................................................... . 257
Pro b 1emas ................................................................................................... . 258
.

.
,.


PARTE UI. ESTRUCTURAS DE DATOS AVANZADAS !
1,
Captul 9 Recursividad: algoritmos recursivos .......................................... . 263 !
.~
.
j

9.1. Recursividad .................................................................................... . 263 .

!

i
j.

9.2. Cundo no utilizar la recursividad ................................................. . 264


. J
9.2.1. Eliminacin de la recursividad ......................................... . 266 1,
,1.

" -,


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., 281
9.5.2. Problema de las ocho reinas ............................................ .. 286
9.5.3. Solucin no recursiva al problema de las ocho reinas .... . 288
9.5.4. Problema de la mochila .................................................... . 290
9.5.5. Problema del laberinto ..................................................... .. 293
9.5.6. Generacin de permutaciones de n elementos ................ . 296
9.6. Problema de la seleccin ptima .................................................... . 297
9.6.1. El viajante de comercio ................................................... .. 298
9.7. Problema de los matrimonios estables .......................................... .. 298
Resumen ...................................................................................................... . 306
..
E~erclclos .................................................................................................... . 306
Problemas .................................................................................................... . 308

,
Captulo 10. I Arboles binarios ....... ................................................................... . 311
10.1. Concepto
, de rbol ......................................................................... . 312
10.2. Arboles binarios ............................................................................ . 314
10.2.1. Terminologa .................... ~ ............................................. . 315
10.2.2. Nivel
, de un nodo y altura de un rbol .......................... . 316
10.2.3. Arboles binario, lleno y completo ................................ . 318
10.2.4.
, Recorrido de un rbol binario ....................................... . 320

10.3. Arboles de expresin .................................................................... . 320

10.4. Construccin de un rbol binario ................................................ .. 322



10.5. Recorrido de un rbol ................................................................... . 324
10.5.1. Recorrido en orden ..................................................... . 325
10.5.2. Recorrido preorden ................................................. .. 326
10.5.3. Recorrido postorden ................................................ . 326
10.5.4. Implementacin de los algoritmos de recorrido .......... . 328
10.6. Aplicacin de rboles binarios: evaluacin de expresiones ....... . 329

10.6.1. Notacin
, postfija: notacin polaca .............................. .. 329
10.6.2. Arbol de expresin ........................................................ . 330
10.6.3. Transformacin de expresin infija a postfija ............. . 331
, 10.6.4. Creacin de un rbol a partir de la expresin en post-
fija ................................................................................... . 331
10.6.5. Evaluacin de la expresin en postfija ......................... . 332
10.6.6. Codificacin del programa de evaluacin .................... . 334
j


xiv Estructura de datos

,
10.7. Arbol binario de bsqueda .......................................................... .. 334
10.7.1 Creacin de un rbol binario ........................................ . 336
10.8. Operaciones en rboles binarios de bsqueda ............................. . 340
10.8.1. Bsqueda ........................................................................ . 341
10.8.2. Insercin ......................................................................... . 341
1O. 8"3 . ,
El lffilnaClon .................................................................... . 342
10.8.4. Recorrido de un rbol ................................................... . 344
10.8.5. Determinacin de la altura de un rbol ........................ . 345
Resumen ..................................................................................................... . 346
..
E~erclclos .................................................................................................... . 347
Problemas .................................................................................................... . 349
Referencias bibliogrficas ......................................................................... . 350
,

,
Captulo 11. Arboles equilibrados ........................................ ..................... ....... 353

11.1. Eficiencia de la bsqueda en un rbol binario ............................ . 353


11.2. rbol binario equilibrado (AVL) ................................................. . 354
11.3. Creacin de un rbol equilibrado de N claves ............................. . 355
11.4. Insercin en rboles equilibrados: rotaciones ............................. . 356
11.4.1. Insercin de un nuevo nodo ............... .......................... .. 357
11.4.2. Proceso a seguir: rotaciones ......................................... . 357
11.4.3. Formacin de un rbol equilibrado ............................. .. 360
11. 4.4. Procedimiento de insercin con balanceo .................... . 363
11.5. Eliminacin de un nodo en un rbol equilibrado ........................ . 366
11.6. Manipulacin de un rbol equilibrado ........................................ .. 372
Resumen ..................................................................................................... . 376
..
EJerclclos .................................................................................................... . 377
Problemas ................................................................................................... . 377

,
Captulo 12. Arboles B ....................................................................................... 379

12.1. Definicn de .
un rbol B .............................................................. . 379
12.2. Representacin de un rbol B de orden m ................................... . 380
12.3. Proceso de creacin en un rbol B ............................................... .

381
12.4. Bsqueda de una clave en un rbol B .......................................... . 384
12.5. Algoritmo de insercin en un rbol B de orden m ................... ... . 385
12.6. Recorrido en un rbol B de orden m ... ................ ........................ .. 389
12.7. Eliminacin de una clave en un rbol B de orden m .................. . 390
12.8. TAO rbol B de orden m .......... .................................................... . 397
12.9. Realizacin de un rbol B en memoria externa .......................... . 400
Resumen ........................... , ......................................................................... . 414

EJerCICIos .................................................................................................... . 415
Problemas ................................................................................................... . 415
Contenido xv

Captulo 13. Grafos. Representacin y operaciones ..................................... . 417


13.1. Grafos y aplicaciones .................................................................... . 417
13.2. Conceptos y definiciones .............................................................. . 418
13.2.1. Grado de entrada, grado de salida ................................ . 419
13.2.2. Camino ........................................................................... . 420
13.3. Representacin de los grafos ........................................................ . 421
13.3.1. Matriz de adyacencia .................................................... . 421
13.3.2. Listas de adyacencia ...................................................... . 424
13.4. TAO grafo ...................................................................................... . 426
13.4.1. Realizacin con matriz de adyacencia ........................ .. 426
13.4.2. Realizacin con listas de adyacencia .......................... .. 428
13.5. Recorrido de un grafo ................................................................... . 431
13.5.1. Recorrido en anchura .................................................... . 431
13.5.2. Realizacin del recorrido en anchura .......................... .. 433
13.5.3. Recorrido en profundidad ............................................ .. 434
13.5.4. Recorrido en profundidad de un grafo ........................ .. 435
13.5.5. Realizacin del recorrido en profundidad .................... . 435
13.6. Componentes conexas de un grafo .............................................. . 437
13.7. Componentes fuertemente conexas de un grafo dirigido .......... .. 439
13.8. Matriz de caminos. Cierre transitivo ............................................ . 442
13.9. Puntos de articulacin de un grafo .............................................. . 446
Resumen ..................................................................................................... . 450
.. 451
EjerCIClos .................................................................................................... .
Problemas ........................... ~ .......................... ............................................. . 453

Captulo 4) ..
Algoritmos fundamentales con grafos ...................................... . 455
......
14.1. Ordenacin topolgica .................................................................. . 456
14.2. Matriz de caminos: algoritmo de Warshall .................................. . 459
14.3. Problema de los caminos ms cortos con un solo origen: algorit-
mo de Dijkstra ............................................................................... . 461
14.3.1. Algoritmo de la longitud del camino ms corto .......... . 462
14.4. Problema de los caminos ms cortos entre todos los pares de vr-
tices: algoritmo de Floyd .............................................................. . 467
14.4.1. Recuperacin de caminos ............................................ .. 469
14.5. Concepto del flujo ......................................................................... . 470
14.5.1. Planteamiento del problema ........................................ .. 471
, ,.
14.5.2. F ormu laClon matematlca ............................................... . 472
14.5.3. Algoritmo del aumento del flujo: algoritmo de Ford y
Fulkerson ....................................................................... . 472
14.5.4. Ejemplo de mejora de flujo .......................................... . 474
14.5.5. Esquema del algoritmo de aumento de flujo .............. .. 476
14.5.6. Tipos de datos y pseudocdigo .................................... . 478
14.5.7. Codificacin del algoritmo de flujo mximo: Ford-Fu1kerson . 479


XVI Estructura de datos

14.6. Problema del rbol de expansin de coste mnimo ..................... . 483


14.6.1. Definiciones
, ................................................................... . 483
14.6.2. Arboles de expansin de coste mnimo ...................... .. 483
14.7. Algoritmo de Prim , y Kruskal ...................................................... .. 484
14.8. Codificacin. Arbol de expansin de coste mnimo .................. .. 488
Resumen ..................................................................................................... . 493
..
EjerCIClos .................................................................................................... . 493
Problemas ...... o 496

PARTE IV. ARCHIVOS Y ORDENACiN


Captulo 15. Ordenacin, bsqueda y mezcla ................................................ 501


15.1. Introduccin .................................................................................. . 502
15.2. Ordenacin .................................................................................... . 502
15.3. Ordenacin por burbuja ................................................................ . 503
15.3.1. A na'l'lSIS . ....................................................................

503
15.3.2. Procedimientos de ordenacin .................................. .. 507
15.3.3. Algoritmo de burbuja mejorado (refinamiento) ........ . 507
15.3.4. Programacin completa de ordenacin por burbuja .. 508
15.3.5. Anlisis de la ordenacin por burbuja ...................... .. 509
15.4. , 1 "
Or denaClon por se eCC10n ............................................................. . 510
, . .,

15.5. O r d enaClon por InserClon ............................................................. . 512


15.5.1. Algoritmo de insercin binaria .................................. . 514
15.5.2. Comparacin de ordenaciones cuadrticas ................ . 514
15.6. Ordenacin Shell ........................................................................... . 514
15.7. Ordenacin rpida (quicksort) ...................................................... . 517
15.7.1. Anlisis de la ordenacin rpida ................................ . 522
15.8. Ordenacin por mezcla (mergesort) ............................................ . 522
15.9. Mtodo de ordenacin por montculos (heapsort) ...................... . 525
15.9.1. Montculo ....................................................................... . 525
15.9.2. Procedimiento empuja .................................................. .. 528
15.9.3. Montculo inicial .0 529
15.10. Mtodo de ordenacin binsort .................................................... .. 529
15.11. Mtodo de ordenacin radix-sort.. ............ .................................. .. 533 .
15.12. Bsqueda lineal ............................................................................. . 536

15.12.1. Anlisis ........................................................................ . 536


15.12.2. Eficiencia de la bsqueda lineal ................................ .. 539
15.13. Bsqueda binaria ........................................................................... . 540


15.13.1. Eficiencia de la bsqueda binaria .............................. . 542

15.14. '
B usque da b"lnarla recursIva . ........................................................... . 544


'

15.14.1. Funcin bsqueda ...................................................... .. 544 ,,

15.14.2. Procedimiento BusquedaBin ................................ .. 545
!
.~



Contenido xvii

15.15. Mezcla ............................................................................................ . 546


Resumen ........................................................................................................ . 548
..
EJerclclos ...................................................................................................... . 548
Pro b1emas ................................................................ " .................................... . 549
'"
.

Captulo 16. Anlisis de algoritmos ................................................................. 553


16.1. Medida de la eficiencia de algoritmos ........................................ .. 553
16.1.1. Anlisis del orden de magnitud .................................... . 554
16.1.2. Consideraciones de eficiencia ...................................... . 555
16.1.3. Anlisis de rendimiento ................................................ . 555
16 . 1.. d ' . ,
4 Tlempo e eJeCUClon ..................................................... . 555
16.2. Notacin O-grande ....................................................................... . 556
16.2.1. Descripcin de tiempos de ejecucin ............................ . 557
16.2.2. Definicin conceptual ................................................... .. 557
16.2.3. Funciones
,
tipo monomio .............................................. .. 558
16.2.4. Ordenes, de funciones polinmicas ............................... . 559
16.2.5. Ordenes exponenciales y logartmicas .......................... . 559
16.2.6. Bases de logaritmos distintas ....................................... .. 560
16.2.7. Inconvenientes de la notacin O-grande .. .................... . 562
16.3; La eficiencia de los algoritmos de bsqueda .............................. .. 563
16.3.1. Bsqueda secuencial .................................................... .. 563
16.3.2. Bsqueda binaria ........................................................... . 564
16.4. Anlisis de algoritmos de ordenacin ......................................... .. 565
16.4.1. Anlisis de la ordenacin por seleccin ....................... . 565
16.4.2. Anlisis de la ordenacin por burbuja ........................ .. 566
16.4.3. Anlisis de la ordenacin por insercin ....................... . 567
16.4.4. Ordenacin por mezcla ................................................. . 568
16.4.5. Ordenacin rpida ......................................................... . 569
16.4.6. Anlisis del mtodo Radix Sort ................................... .. 570
16.5. Tablas comparativas de tiempos .................................................. .. 571
Resumen ..................................................................................................... . 572
..
EJerCICIOS .................................................................................................... . 573
Problemas ................................................................................................... . 577
Referencias bibliogrficas ......................................................................... . 579

Captulo 17. Archivos (ficheros). Fundamentos tericos ............................. . 581


17.1. Nocin de archivo. Estructura jerrquica .................................... . 581
17.1.1. Campos .......................................................................... . 582
17.] .2. Registros ........................................................................ . 583
17.2. Conceptos, definiciones y terminologa ...................................... . 584

17.3. Organizacin de archivos ............................................................ .. 587


17.3.1. Organizacin secuencial ............................................... . 588
17.3.2. Organizacin directa .................................................... .. 589

XVIII Estructura de datos

17.4. Operaciones sobre archivos ......................................................... .. 589


17.4.1. Creacin de un archivo ................................................. . 590
17.4.2. Consulta de un archivo .................................................. . 590
17.4.3. Actualizacin de un archivo ......................................... . 591
17.4.4. Clasificacin de un archivo ........................................... . 592
17.4.5. Reorganizacin de un archivo ..................................... .. 592
17.4.6. Destruccin de un archivo ............................................ . 592
17 .4 .. . , ti ., d h
7 R eumon, USlOn e un arc IVO ..................................... .. 592
17.4.8. Rotura/estallido de un archivo ...................................... . 593
17.5. Gestin de archivos ....................................................................... . 593
17.6. Mantenimiento de archivos .......................................................... . 594
17.6.1. Altas ............................................................................... . 595
17.6.2. Bajas ....................... ~ .............................. ......................... . 595
17.6.3. Modificaciones .............................................................. . 596
17.6.4. Consulta ......................................................................... . 596
17.6.5. Operaciones sobre registros .......................................... . 596
17.7. Procesamiento de archivos. Problemas resueltos ........................ . 596
Resumen ..................................................................................................... . 613
..
EJerClClOS .................................................................................................... . 614
Problemas ................................................................................................... . 615

Captulo 18. Tratamiento de archivos de datos ............................................ .. 617


18.1. Archivos de texto .......................................................................... . 617
18.2. Cmo aumentar la velocidad de acceso a archivos ..................... . 622
18.2.1. Archivos con funcin de direccionamiento hash ........ . 622
18.2.2. Funciones hash .............................................................. . 623
18.2.3. Resolucin de colisiones ............................................... . 625
18.2.4. Realizacin con encadenamiento ................................. . 636
18.3. Archivos indexados ....................................................................... . 645
18.3.1. Archivo indexado de una fonoteca ............................... . 645
18.3.2. Programa de manipulacin de archivos indexados ..... . 650
Resumen ..................................................................................................... . 652
..
EJerclclos .................................................................................................... . 653
Problemas ................................................................................................... . 653

Captulo 19. Ordenacin externa .................................................................... . 655


19.1. Ordenacin externa. Mtodos de ordenacin .............................. . 655
19.2. Mtodo de mezcla directa (mezcla simple) ................................. . 656
19.2.1. Codificacin ................................................................... . 657
19.3. Mtodo de mezcla equilibrada mltiple ...................................... . 661
19.3.1. Tipos de datos ................................................................ . 661
19.3.2. Cambio de finalidad de archivo .................................... . 662
19.3.3. Control del nmero de tramos ...................................... . 662
19.3.4. Codificacin ................................................................... . 663
,

., ,._ - - - -- -- - - - - -- - - - -- - - - - - _..... . ,,'

Contenido xix

19.4. Mtodo polifsico de ordenacin externa.. .................................. . 667


19.4.1. Ejemplo con tres archivos ............................................ .. 667
19.4.2. Ejemplo con cuatro archivos ........................................ . 669
19.4.3. Distribucin inicial de tramos ...................................... . 670
19.4.4. Mezcla polifsica versus mezcla mltiple ................... . 671
19.4.5. Algoritmo de mezcla ..................................................... . 671
19.4.6. Codificacin ................................................................... . 672
Resumen ........................................................................................... 0
, 678

..
EJerclclos .................................................................................................... . 678
Problemas ................................................................................................... . 679
Referencias bibliogrficas ......................................................................... . 679

PARTE V. PROGRAMACIN ORIENTADA A OBJETOS

Captulo 20. Objetos: Conceptos fundamentales y programacin orien-


tada a objetos ............................................................................... . 683
20.1. La estructura de los objetos: sintaxis ........................................... . 684
20.1.1. Encapsulamiento ............................................................ . 691
20.2. Secciones pblica y privada ........................................................ .. 691
20.2.1. Declaracin de una base ............................................... . 692
20.2.2. Declaracin de un objeto .............................................. . 693
20.2.3. Implementacin de los mtodos .................................. .. 693
20.3. Definicin de objetos mediante unidades .................................... . 694
20.3.l. Uso de un tipo objeto .................................................... . 695
20.4. La herencia .................................................................................... . 696
20.4.l. La herencia con inher i t ed ..................................... . 702
20.5. Los mtodos ........................... o 705
20.6. Objetos dinmicos ......................................................................... . 705
20.6.l. Asignacin de objetos dinmicos ................................. . 705
20.6.2. Liberacin de memoria y destructores ......................... . 707
20.6.3. La clusula S e 1 f .......................................................... . 709
20.7. Polimorfismo ................................................................................. . 714
20.7.l. Constructores y destructores en objetos dinmicos .... . 717
20.7.2. Anulacin de mtodos heredados ................................. . 718
20.8. Constructores y destructores ........................................................ . 721
20.9. Los procedimientos New y Dispose en POO .............................. . 724
20.10. Mejoras en programacin orientada a objetos ............................ . 725
20.10.1. La ocultacin mediante public y private ................... . 726
Resumen ........................................................................................................ . 727
,. d "
Errores tlplCOS e programaclon .................................................................. . 729
, "
EJerCICIOS ....................................................................................................... . 730
Problemas ...................................................................................................... . 730
Referencias bibliogrficas ............................................................................ . 730
XX Estructura de datos

Apndices
Apndice A. Vademcum de Matemticas para la resolucin de algoritmos
, .
numerlCOS . o ' , oo 733
Apendice B. Unidades estndar de Turbo Borland Pascal 7 ............................ . 739
B.I. Las unidades estndar ........................................................ . 740
B.2. La unidad Systern ............................................................ . 740

B.3. La unidad Printer ........................................................ .. 741
8.4. La unidad DOS ................................................................... . 742
B.5. Procedimientos y funciones de la unidad DOS ................ . 744
B.6. La unidad Crt ................................................................... . 753

B.7. La unidad Str i ngs: funciones ...................................... .. 760


,
Resumen oo oo 764
Apndice C. El editor de Turbo Pascal 7.0 ...................................................... .. 765
Apndice D. El entorno integrado de desarrollo de Turbo Pascal 7.0 ............ .. 769
Apndice E. Depuracin de sus programas en Turbo Pascal .......................... .. 783
Apndice F. Mensajes y cdigos de error ........................................................ .. 797
Apndice G. Gua de referencia Turbo Borland Pascal .................................... . 805
,
Apndice H. Gua del usuario ISO/ANSI Pascal Estndar .............................. . 829
Indice ..................................................................................................................... o oo. 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
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
a
y M. 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-
a
soras M. 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



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

I
PARTE

,
I
,

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

-,

1
,
CAPITULO

. , . .,
n enlerla eso are: Intro ucclon
, .,
a 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 I
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 I

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
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 F2 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

Obtener el
Leer las notas Ordenar
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

I
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 .

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.

Carrasco, Hellman y Verof: Data structures and problem solving with Turbo Pascal, The Benjamingl
I

Cummings Publishing, 1993, pg. 210 .

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 rde nar (A, n)


(Ordena un a li sta en orden asce nd e nte
precondi cin : A e s u n array de N ente r 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 d ,<,ts~osen 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.

2Para 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


r
,

, 14 Estructura de datos
I
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,

,
l

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.

,
;

I Mantenimiento Especificaciones
i,

Evolucin Diseo

Produccin Verificacin

Pruebas Codificacin

!,

Figura 1.4. Etapas del ciclo de vida del software cuyo ncleo aglutinador
es la documentacin.
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 fragm ento de programa contiene una secuencia de sentencias de asigna-
cin, seguidas por un aserto:

A

-- 10 ; ( as e r t o : A e s lO )
x
-- A ,' {as er t o : X es lO }
y -
- x + A; {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 1 0 . 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 co n s tan te} )
despus que se ejecuta el segmento de programa.

Este trmino se suele traducir tambin por afirmaciones o declaraciones. El trmino aserto est ms
4

extendido en la jerga informtica, y al igual que aserto , estn los dos trminos admitidos por el DRA E.


!
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
I si Min <= Max es verdadero; en caso contrario
I
i 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
I, siempre que Min < = Max sea verdadero.
,
Las precondiciones y postcondiciones son ms que un mtodo para resumir acciones de
I 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


I 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


I
I
!
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,
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) {= condiciones l gicas que son


verdaderas antes de que P se eje cut e }
(postcondicin) {= condiciones lg ica s que son ve rdaderas
despus de que P se e j ec ute}

EJE LO 1.3
I
,
ElprocedimientoOrdenarSele cc ion (A, m, n) ordena a los elementosdelarray.
A [m . . n] en orden descendente. El modelo correspondiente puede escribirse as:

{m ~ n} {preco ndicin: A ha de t e n e r al menos 1 ele me n to}


Ordena rSe l ecci on (A , m, nl {programa de or denacin 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;
{preco ndicin : m < n}
{pos tcondicin : devuelv e posic in eleme nto mayor en A[m .. n]}
var i, j : In t eger ;

begin

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

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

PROBLEMA 1.2

Ordenar por el mtodo seleccin con precondiciones y postcondiciones:


procedure Ord e nar Se l eccion ( var A:L is t a; m, n : I n t ege rl;
{prec o ndicin : m ~ n }
(postcond i 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

{aser c i n n>= 1 } {p r e con d ici n }


su ma : = 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 stcond i c i n}

Una invariante del bucle puede ser:


{invariante: i <= n y S u ma 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}
{prec o ndicin : n > = 1}
Suma := O;
1, - ,
. - 1
while i <= n do
{ in variante : i <= n +1 y Suma es 1+2+ ... i - 1}
begin
,
Suma : Suma + l ;
,
1 . -- i+1
.

end;
{p o stco ndicin : 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: InIClaClOn,
condicin de repeticin y cuerpo del bucle.

EJEMPLO 1.6
Si la variante de un bucle es:
{invariante: i <= n y Suma es la suma de todos los nmeros ledo s del
t eclado}

Se puede deducir que:


S uma := 0.0: { ini ciac i n}
l

. -- O',
1 < n {condi cin / prueba del bucle}
Read (Item);
Suma : = Suma + I tem ; {cuerpo del bucle}
i :=i+l

,
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 do <{y , toma l os va lores 0,1, 2 , 3 , .. n - 1}
n
Rea d ( Item);
Su ma : = Su ma + Item ;
i : = i + 1
end;

EJEMPLO 1.7

En los bucles for es p osible 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, p or 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.

{preco nd icin n > = l }


Suma : = o;
for i : = 1 to n do
{i n va ri ante : i < = n +l y Su ma es 1+2+ ... i -l }
Suma : = Suma + i ;
{postcondi ci n : Su ma es 1+ 2 +3 + .. n - l +n }

PROBLEMA 1.3

Escribir un bucle controlado p or centinela que calcule el producto de un conjunto de


datos.

{Ca l cula r el pr oducto de una se rie de d at os }


{preco n dicin : cen tin e l a es con stante }
Pr o ducto := 1 ;
Wr ite ln ( ' Par a t erm in a 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
{invarian t e : Pro duc to es el produ c to d e tod os los valore s l edos en
N mero y n ing u n o era el Ce ntine l a }
begin
Pr oduc t o := P r oducto * Numer o ;
Wri t eLn ( ' I n troduzca nme ro si gu i en te :' ) ;
Rea dL n (Nu mero)
end;
{p ostco ndici n : Pr oducto es e l produc to de todos los n meros l edo s e n
Nu me ro ant e s de l ce n t i n e la }
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;
J

-- 1;

while J < = N do
begin
Suma -- S u ma + A [ j ] ;
--

J suc c (j)
end
{ invar i ante: Suma es l a suma de l o s element os A[l] a A [j- 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
L

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.


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.

i
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 T i poP unt os = array [1 .. 1 00 } of in tege r;


for i := 1 to 1 00 do
proceso d e l os e lementos
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 Num e roD e 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 rang o

6Tremblay, Donrek y Bunt: Infroducfion fo Computer Science. An Algorithmic approach, McGraw-


Hill, 1989, pg. 440.

i,

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

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

- _ .. _...
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

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
I 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,
VariableDeControl,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 No mbreMensajeUsuario Mens a jesDatos Mal

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 NurnDiasSernana = 7,
Const 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.

,' "
" ' "
,
.
'
'

Una funcin no ,.,.,'" ... " nct.dct., SIDO devolver el valor requ.erido. Es decir, una
'"' funcinnUrttll """,'kla'r:l. ,"- -. ' j 'j' :."i';: ':, .,.;':, !: . --,--" - - , _, ::,: ~ " , :', ';,' ", ':: , : r; ::T,' ',,:~,:,::: ", ',.--- - " -
,
. .. .. - . .
- - .
- -

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-
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).
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 be g i n - en d deben estar alineadas:

begin
<sentencia1>
<sen tencia 2>

<s ent encian >


end

i
Sangrado consistente. Sangrar siempre el mismo tipo de construcciones de igual
manera. Algunas propuestas pueden ser:

bucles while/repeat/for

while <condi cin > while <condic i n> do


<sen t encia > begin
<s entencia>
end
,
while <condi cin> do
begin
<senten c ias>
end

Sentencias if-then-else
if <con d i cin > if <condicin > then
then <sen tenc i a1 > <senten cia1>
elee <sen t encia2 > elee
<sentencia2>

if <condicin >
then
<sentencias>
elee
<s entencias>

if <condicin> if <cond1 >


! then begin then <acc i n 1>
<sen t encias> elee if <cond2>
end then <acc i n2 >
elee begin elee <cond2> if

<sentenc ~ as >
end
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 manual de mantenimiento del programa


operadores 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.
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, rad i o de un c irc u lo )
( Calc u l ar Area)
Are a : = 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. I
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:

L,

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 i t 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 <co ndicin >
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 tcnicasestn~r(luesePlWdaiuwlizar, para resolver el.problema.
4. Elegir una estructura de dato~adecuada.
. . " .. ..

5. Dividir el problelll!l 1:11 s\l:bP(Clbl!<lllas Yplic.arel mtodo a ca4a uno~ los subproblemas (di$eo .
. descendente).
. . , ....
. ", '" ~
....
",;:,; ,:'
:":: ". ,. :."., ,, ...

6. Si todo lo anterior falla, comIence de nuevo , .,.


en el paso 1.
.... _--- -- ---'-,,- -
- - , , ;, 1 J.~ .' -:::.,: _,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
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:

P~con~cin: 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
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);

I
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)


ArrayL i sta : Lista[Primero .. Ultimo] of integer
ALGORITMO Buscar el em ento 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 81 1 20 1 60 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 tim o)

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.
Ingeniera de software: introduccin a la metodologa de construccin de grandes programas 49

Ejecucin
Intro d uzca 10 en t ero s en or de n asce nd ente :
2 5 8 12 23 37 45 89 1 12 234
I n tr o du c ir n m e r o a b uscar :
27
el e l e mento 27 n o es t en l a l ista
Bus q ueda1 te rm i n ada e n
10 i t e r ac i o n es
el ele mento 2 7 n o es t en l a lista
Bus qued a2 t ermi nada en
6 i t era cione s

1.13.1. Eficiencia versus leg ibilidad (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.
1
Implementacin (codificacin y depuracin).

If... ,
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 ( In d i ce) ;
Sum a := 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 : integ er ;
Nombre: array [ l .. 10 ] of ch ar;
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 ,x 2 , x 3 )
end
end;

1.3. Cul es el error de la siguiente funcin? Cmo puede resolverse?


function Tang ent e ( x : r eal) :rea l ;
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.
I {invarian t e :
O <= Tota l <= n y N me r o se h a div i d i d o po r 10 veces To ta l }

y sta ser la asercin vlida (postcondicin)

{po stcondicin : 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 ta d o r := 2 ;
while Cont ador < 10 do
begin
Producto : = Producto * Co ntador;
Co ntador : = 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 lista
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:
, .
mo u os versus unl a es
, , - - -- "- - ,- ~" -
--
-
-,
.

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 1
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 I
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
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
1
(interfaz), seccin implementation (implementacin) y seccin initialization (iniciali-
zacin) 1.

Formato J

unit <identi ficado r>; ,


1
interface
1
uses <lista de unidades > ; {opciona l}
,
{decl ara cio ne s pblicas Obje t os exporta dos } ,
implementation
{declarac i o n es privadas}
ii
{defin i cin de proced i mientos y fu n c i ones pbl i cas} I1
begin
{cdigo de inicializ ac i n } {opcional} ,,
i,
end. ,
,

i
Aceptamos el tllnino inicializacin por su extensa difusin en la jerga infollntica, aun a sabiendas
I 1
que dicho trmino no es aceptado por el DRAE y su expresin correcta sera iniciacin. 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 . PAS.


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 Ray o ;
interface
uses DOS , Graph, Crt ; (se utilizan las un i dade s DO S, Gr aph y Crt )
var

a , b, e : int ege r
function Ex po n encia l (a, b : i n t eger) : rea l;
procedure Di v id ir (x, y : integ er ;var cocien t e : i nt eg er) ;


2 El identificador puede tener de uno a ocho caracteres ms un punto y una extensin tal como .PAS .

, 56 Estructura de datos

En la seccin de interface se pueden declarar variables y elementos globales y otras


unidades.

Observaciones
l. La unidad Ray o puede utilizar cualquier 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 Expo n encia l (A, B : i n t eger ) : rea l;
procedure Di v i dir (X , Y : in t eger ; var Cocien t e : in t eger) ;

implementation
function Expon e n c i al (A, B : i nt eg er) : real ;
var
P, I : integer;
begin
P := 1;
for 1 := 1 to B do
P := P * A ;
Expone nc ial .' - P

end;

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


begin
Coc ie nte : = 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.

I
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 nombre de unidad


ha de corresponder Cabecera de la unidad
con nombre de archivo

interface
uses ert; ~ opcional Seccin de interfaz
procedure Frase(Texto : string);

implementation
uses Printer; ~ opcional

var
MiVar : Integer
procedure Frase;
begin Seccin de implementacin
ClrScr;
GotoXY ((80-Length (Texto)) div 2,1)
Write (texto);
end;

begin
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-u ni 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 Co mpile / 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 . TP L.

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 eg er) ;
function Ma x imo (I , J : i ntege r) : i nt eger ;
implementation
procedure I n terca mbio;
var
Aux : integer ;
begin
Aux - I ,
-
1 - J ;
J - Aux
-
end;
function Maximo;
begin
i f I>J
then Ma x imo -- I
else Maximo -- J
end;
end.

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 ('Introdu c i r dos num e r as enter os ' ) ;
ReadLn (X, Y);
In terca mbio (X , y); Wr it eLn (X , " , Y) ;
WriteLn ('e l 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 {sec cin de int erfaz}


procedure Inte rcamb io (var X, Y : integer) ;
{intercambia los va l o re s de X e Y}
function Potenc i a (X : real ; n : i nt eger) : real;
{d ev u e l ve X a l a potencia n -e si ma }

implementation {sec ci n de imp le me nt a cin}


procedure Inter ca mbio (var X, Y : in teger) ;
var
Aux : In teger;
begin
Aux := X;
X := Y;
Y := Aux
end; ( Intercambio )

function Pote ncia (X : real; n : i n te ger) : rea l ;


var
I : integer;
Pr od ucto: real;
begin (Po ten c 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 te rcambio ;
function Po t~nc ia ;

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 in t 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 ObV iej os, no es necesario listar ObV iej 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 Unidad 2 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 Unida d2 ;
interface
uses ObViejos, Obje t 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 Finan c 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 la r a pro cedim ien to pa ra co n ve rt ir ca pit ales}

interface
const
Ta sa = 4. 25 ;
procedure Un o (Cap it al : r ea l) ;
procedure Dos(Cap it al : rea l ) ;
implementation
const
Banda = '*';

function Convers i o n (Cap i ta 1 : rea 1 ) : r ea 1 ;


var
Fa ctorCo nv ers i o n : in te ger;
Ca n tida dP agar : real ;
begin
FactorCo n vers i o n : = 65;
Ca n tida dP agar : = Capi t al * F ac torCon ve rs i on ;
Con vers ion : = Can tid adPag ar
end;

procedure Uno (Cap i ta l : r eal ) ;


begin
Writ e ( 'el in te r s es i gual a .. , ) ,.
WriteL n (Cap i ta l * 4. 2 5)
end;

procedure Do s (Ca pi tal : rea l) ;


begin
WriteLn (' e l inte r s es i gua l a :', Cap it a l * 6) ;
end;
end. {fin de Financ a}

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; 1

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


unlWlUl;;S
!..1_..1_
nece".1;-
.....",,"

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. .
Construccin de grandes programas: mdulos versus unidades 65

unit Vi suali z;

interface
procedure Escrib i r Enpos i cionXY (X,Y :in teger; Me n sa j e :string ) ;
implementation
uses Crt, Error ;
procedure Es crib irE nPo si cionXY (X ,Y:in teger ; Men saje: string);
begin
if (X in [ 1 .. 80 ] ) and (Y in [1 .. 2 5])
then
begin
GotoXY (X , Y, ) ;
Wr it e (Mensaje)
end
else
VerEr r or ( ' Coordenadas XY fue r a de rango ' )
end
end.

El procedimiento VerError visualiza el mensaje' Error Fatal' en la lnea


25 de la pantalla.

unit Error;
interface
procedure VerE r r o r (C adena : string)
implementation
uses Vis ual i z ;
procedure Ver Err or (Cade n 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
' .,~
,"

L
la otra
1 ..

-.c_ .< __ ,.
', :'. .- - .. ..
, >"". . . , .. c
"! " ,

, ,
2.4. UTILlZACION DE UNIDAD ESTANDAR

El archivo T URBO. 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, Pro ceso;
const
Mayor = 1 00 ;
type
Pal abra - string [ 2] ;
var
Ex presion : rea l;

Recordemos que las unidades estndar son:

Syst em Ove rl ay Do s Crt Pr in ter Gr a p h Grap h3 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:
ClrS c r Borra la pantalla.
KeyPressed Detecta la pulsacin de una tecla.
Sou n d Hace sonar el altavoz interno.
wi ndow Define una ventana de texto en la pantalla.

EJEMPLO 2.4
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 : \ P rue bas; C : \ De moU no

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 tie~e 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 'use~T~rbopusC .esta


unidad (ldll)' ~ucesi'vmerite 'en: <' j, , (. ' ' '< ;.; ',
'" , ., _ _ " - -,' _" _ '-l/, ~: _ ;~_,:;';,',,I,:,;,i,;:< .. . -.. -" _--.', .. ,,"' , ,,::" : ,,.,, :" ,- '._ .,' l' ," .. ' . ' ;',', ,,':' ,

1. ' Entre las unid.des residetlte~en la biblioteca TURBO. TPL.


2. En oel directorio actual; "o' 'c o , .o, L, , ; , i , '

3. Los,ditectoris'citads '~n -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 , Pa n talla, Crt ;

el compilador utilizar ahora el procedimiento estndar ClrScr. ,i


,
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 ie za 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.
72 Estructura de datos

, , "
" ._"
-,
-._~-
., - .
--,<----~-----
,',' -' - - , > ,
,
;:.

Un programapuede disponer d.econstantes, definiciones, de tiposy subprogr:amas


preCompillld()s,in~iu)'endo ,tma senteifdaUse~ despu~s dl 'fa ,cbecra de ul1 pro-
" ' _ : .::: ............ .... '.i ' ," ' _: . . . , -" .:' ; t ., -! . OA . . . . ,

grama . .. ,' ' " ':';'"':"' ':':--:'' . . ,'.


,,',,"",">'" . . . . . , ' "" ' ':, "' ,~
- " : . . . ':":",',"':',;:.':" ,': . .:< - <;;:'::; ': :;',:' '" ,:
':- 'f "::'~' r.: :,
.. ,

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,
Wi nd ow, 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 < ide nti 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 co mpi l ada; l a e x te n s i n es .T PU}

interface
uses <li s t a de u ni dades > {op cional}
{dec l a r aciones pb l icas o visibles son opc i o n a l es}
cons t .... .
type ..... .
var ..... .

procedure ... {s l o cabece ra}


function ... {slo cabecera}

implementation
{dec l a r acio n es priva d as : l ocales a l a u n i d a d }
uses <li s t a de unida des >
const ... .
type .... .
var .....

J
,
,
,J

I
I
Construccin de grandes programas: mdulos versus unidades 73

procedure . . . . {cabece r a y c u erpo de l proced im ie n to}


furiction . . . . {cabecera y cue r po de la func i n }
[begin {se l ecc i n de i ni c ia l izacin : opc i onal}


endo {obligatoria , fin de i mp l emen t aci n }

Modelo 1 ,,
,
unit Base ;
,,

interface :
,
uses
Crt ;
procedure Mens aje (Texto : string);
implementation
procedure Mensaj e ;
begin
ClrScr ;
GotoXY ((80 - Leng t h (Texto)) div 2 , 4 ) ;
Wr i te (T ext o )
end;
begin
o o o

endo

Modelo 2
unit Base ;
interface
uses
Crt ;
procedure Me n saje (Te xt o : string );
implementation
procedure Me n saje (T ext o: string ) ;;
begin
Cl rScr ;
GotoXY ((80 - Length (Texto)) div 2 , 4) ;
Write (T ext 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 . .
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

l,
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
,
... ..... .. . .. ,,,,,,' " . ,
...... .......... ,'"
..
i

El uso actual de ls archivos de inclusin se suele reducir a archivos que contienen I,


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,
r
ya que slo partes del programa residen en memoria en un instante dado. f

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
,

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 Mortim e r;
{$ F + }
uses overlay, Dos , Crt, Circu l os , Xmodem, Kermit, Parse r;
( SO Xmodem)
{SO Kermit}
{SO Parse r }

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 ).

MIPR OG . EXE MIPR OG . OVR

Unit Tee; Unit Tee;

Heap Unit Tie; Unit Tie;

Unit Toe; Unit Toe ;

Unit Tum; Unit Tum;

Unit Tea; Unit Tea;


fondo

overlay buffer (debe ser


tan grande como el Unit Tir; Unit Tir;
mayor solapamiento



cima

Unit Tas ; Unit Tas;

Stack
Memoria EMS Almacenamiento
(si existe) en disco (DOS)
Memoria principal
(DOS)

Figura 2.2. Archivos y memorias de solapamiento.

Ejemplo
begin
Ov rI n i t i ' MIP ROG . OVR' )
end;
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 ;
OvrN ot Found - -2;
Ovr No Me mory - -3;
Ovr lo Erro r - -4i
Ov rN o EM SDri ve r - - 5 ;
Ov rNoEMSMemo r y - - 6 ;
var
Ov r Res ult : integer;
,
,
,
2.8.3.2. Procedimientos y funciones de la unidad Overlay
Procedimientos Funciones
Ov r l n it Ovr Ge tBuf
OvrlnitEMS
Ov r Se t Buf
Ov r Cl e a r Buf

OvrClearBuf
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 u nidades utilizadas por esta unidad >
{s e omite si no se uti liza ninguna unidad}
<cabeceras de procedimientos y f u n c i o nes >
<o tras declaraciones >
implementation
<declaraciones compl etas de pro ced imientos y fun cio nes >
begin {no se necesita si n o existen se ntencias de i nicializ ac 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.

n
Desviacin media (DM = ~L
i 1
=
x-x I

donde x =

I es el valor absoluto
n
Media cuadrtica (MC) = #. L xl
1= 1

Media armnica (MA) n-,----,--


= ___
n l
L
. 1
1=
x I

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 b21 b22 b 2m
A= y B=

ami a m2 a mn bml b m2 bmn

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

o. , ,
' .
.' '
Y
, .

, --.-

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 1O 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 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.
CadenaA Proporciona una cadena de letras maysculas arbitrarias.
CadenaA (n) n, nmero de letras.
LagicasA Proporciona un valor lgico aleatorio.
,

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 MNRPQANT true
346 LOIVRSTN false
37l MSPBVTRL true
382 NZJMKSBC 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


!
t
encapsular y aislar la informacin de diseo y ejecucin. En un determinado sentido, las r,
,
;
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- ,t
tos, los mdulos, los tipos abstractos de datos y los objetos. r
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


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 Encapsulacin Persistencia

Herencia Polimorfismo Genericidad

Entidades bsicas

Mensajes Herencia
Objeto
Mtodos 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 ofScientific 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 Algoritmos


Orientados a objetos Clases y objetos
Orientados a lgica Expresado en clculo de predicados
Orientados a reglas 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." ed.~ 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.
Abstraccin de datos: tipos abstractos de datos y objetos 91

Interfaz Primitivas de acceso


Descripcin de propiedades de los datos

Atributos Algoritmos
Seccin
privada
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

Parte
visible

Interfaces
pequeos

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.

Sobre el principio abierto-cerrado y su implementacin en C++ y Eiffel, se puede consultar la biblio-


4

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.
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~ aC:j)pJ i t o...


ap~.. ..
. .
. . . .'. .rad. 0. de
G ..'
C)p ro
ac:. 1."pe",..
i


': : . .. G.,.lIo. d,. ptanteDibilid.d
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


, :. :.:.:.: . .. " .. . . :.
,
. . .

.... G...dode mantenimiento


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

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, concat~nar 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 1

Mtodo 3 Mtodo 3
...

Interfaz pblico

Representacin:
estructura de datos
(variables de instancia)

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 unidad, objeto


Modula-2 mdulo
Ada paquete
C++ clase
Java 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.

unit <nombre unidad > ;


interface
<c lausula uses >
<co nstantes, tipos y variables publicas >
<cabecer as de procedimientos y funciones publicas>
implementation
<clausula uses >
<co nstante s , tipos y variables privadas >
<proced imientos / funciones privadas y cu erpos de
procedimientos / f u n c i o nes publicas>
begin
<se cuencia de sen t e n c ias para inicializacion >
end.

Pila

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 Sacar Meter

Cim a

- , -
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 ipo El eme nt o);
(* Se aade u n 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) :boole~n;


(*devuelve true si S es vaca; false en caso contra rio *)

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 := S.Cima-l
end;
104 Estructura de datos

function p il aVacia (S :ti po) :boo l ea n;


begin
PilaVa cia : = ( 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 P il 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
- 20
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 LeeryA lmacenar Num e ros( var Num Pi la : Pil a.T ip o } ;


var
Aux : p il a.TipoE l emento ;
begin
while not eof do
begin
readln (Aux) ;
Pi l a . Meter(NumPi l a , Aux} ;
end;
end;

procedure VerN um eros( var Nu mP i l a : p il a.T i po} ;


var
Aux : pi la.Ti po Eleme nto;
begin
while not P i l a . Pil avacia(NumP il a} do
Abstraccin de datos: tipos abstractos de datos y objetos 105

begin
Pi l a . Sacar( Nu mP i l a . Au x ) ;
Wr i te Ln( Aux ) ;
end; ( * whi le *)
end; ( * Ve rN umer os * )

begin (* pro gram a pr inc ipal * )


Pil a . Cre ar(S)
LeeryAl mace nar Num e r os( S ) ;
Ve rNum er os(S) ;
Pil a . Des tr u 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.


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.

I
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

Pascal Smalltalk C BASIC


CLU

~ 4
Object Pascal

Ada Objective-C C++ Visual BASIC 3


Actor

Ada-9S Visual BASIC 4


Borland Pascal

. Java
Delphi

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.


Abstraccin de datos: tipos abstractos de datos y objetos 113

FORTRAN I
1957 ALGOL 58
FORTRAN 11 COMTRAN
1958
1959 LlSP LGOL60 COBOL
1960 LlSP
1961

1962 BASIC // CPL
1963
1964 SIMULA I
1965
1966 ALGOL-W
1967 SIMULA 67 ALGOL I

1968
1969
Pascal B
1970
1971 Prolog
1972
1973
1974
1975
1976
1977 FORTRAN 77

1978
1979
Smalltalk 80
1980
1981

1982
1983
1984
1985
1986
1987
1988 Common
Object-P LlSP
1989
Oberon ANSIC++
1990
1991
Ada-90
Modula-3
Quick
90
EiHel
Basic
1992
1993 Prolog++

1994 Object-COBOl
Visual BASle
1995 (00 COBOL)
Ada-9S - - - _;-______
Delphi

Java

Figura 3.9. Genealoga de los lenguajes de objetos segn Sebesta 9.

9Esta 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:
Abstraccin de datos: tipos abstractos de datos y objetos 121

Borrar: Eliminar todos los nmeros de la pila.


Copiar: Hace una copia de la pila actual.
Meter: Aadir un nuevo elemento en la cima de la pila.
Sacar: Quitar un elemento de la pila.
Longitud: Devuelve un nmero natural igual al nmero de objetos de la pila.
Llena: Devuelve verdadero si la pila est llena (no existe espacio libre en la pila).
Vaca: Devuelve verdadero si la pila est vaca y falso en caso contrario.
Igual: 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
" ' ,
, .,- .:.-._;_, .'_ _ _
-- - -- f
_M
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 (direccin)

2014 (valor) 2587 (valor)


un puntero una var dinmica


p 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.
, ,.,..

.. .. .. .. conti~~ela
...

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 : Aidentific ad or -tip o

var
Ptr: ATip oElement 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:

Por ejemplo, la variable P contiene 0591 64 que es la direccin de memoria donde est
la variable entera apuntada 345.

059164 345

P est en la variable entera en la


direccin 034405 direccin 059164 pA

Un puntero apunta hacia (a) otra variable cuando contiene la direccin de esa va-
riable.
Estructuras de datos dinmicas: punteros 129

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 . .---_ . ,
. -..
. n oinbre-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 real
Pu n t er o Real = AR e a l;
A
var
A, B : Punte r oRea l ; B

1. type
--- ."
real

Tipo_Pu n tero = Ai n teger ;


var
P: Tipo_Pun t ero ;

2. var
P : Al nteg e r;

3. type cad4 0 = s tr ing [ 40 1; declara tres variables puntero:


var ptr : Aca d40 ; p t r apunta a valores cadena
ql , q2: Ar ea l; ql, q2 apuntan a valores reales
4. type
Punt e r oRe a l = ARe a l ; puntero a reales
var
P: Pun teroReal ; Pes una variable puntero de tipo
R : Real; Punter o Real
type
PunteroEn t = Ai nt ege r ;
130 Estructura de datos

5. var
Pr imero : ~ Rea l;
S i g o Pun tero En t ;

4.3. OPERACIONES CON VARIABLES PUNTERO:


LOS PROCEDIMIENTOS NEW Y DISPOSE

Los punteros se crean con las declaraciones citadas:

type
Punter o Rea l = ~ 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) N e w 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.

P~ : = 1 000 el valor de p ~ es 1000


P~ : = 3 * P ~ + 500 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 La llamada a N ew A.

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 se utiliza para referenciar a la celda de memoria apuntada por la va-
A

riable puntero P. El smbolo (circunflejo) se denomina operador de indireccin o de


A

desreferencia.
La sentencia de asignacin

almacena el valor real 25.0 en la posicin (celda) de memoria apuntada por P.

25.0

Como P A se considera una variable, podr ser visualizado su valor


Wr i t e (PA : 10 : 2 ) ; visualiza el valor 25.0
132 Estructura de datos

Atencin
P:= 25 .0; asignacin no vlida
Write (P : I0 : 2) ; 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 .," , L~direc.cip~ ,~~~ IW~lpj,qp: de memoria ~e;lllpla~eNt . cm~; se crea una luira-
" "'b'l:'='d" ... :."." . .. . ':' . . -::''':' ,:' 1)/'\""""':' "" ",:"':< ..,'::' ',' '_,",- ',' .. . . , ,,I""":f;!- ,.", ';' :, .,. , ... . <

. e . lnanuca J: ,....." ..<,',.:".,-...,',.ij;';>."


<.

,. > ,, ,' ,' ," ." , , .. '" ,' , '


',," , ;' !.'. . '"'..>i: . .?:.';::::',::. ' - , _ , " ' ;, ,- , . " \ '<':"1..', ,' ,':
,,:: _" ,,' '~ "

'r i'.!;.- ;'",:"if: : : ' , \ - " :' - :r'~'n:,',i ' ; ' :~ l~<:;:::' '>,';:"">!: : "- '(-' . ,~.. j"~; :; " ~' , j'-:, "f> , , . ".
.
"r-----.. . . -- :. .::~'1::~"". ". ,
'
"

i, ':!,~':';_
.- ! , ~, ..
,"
.
'- ,
! ,

,
'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 despus del nombre de la variable puntero. Por ejemplo,
A

new (Ptr) ;
Ptr ~ : = 'M ckenna ';

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 Mckenna en esa celda de memoria. Un I I

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) ;
pt rA := ' McK e n na ';

se puede dibujar a nivel de direcciones de memoria, como se muestra a la izquierda,


con el diagrama ms sencillo de la derecha.

Dir ec c i n 10 1 5 Direccin 1256

1 2 56 McK enna Mc Ke nn a

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. P t r1 : Ac ha r;
2. Pt r2 : Ain t eger ;
begin
3. Ne w (Ptr 1) ;
4. P tr l " : = ' B';
5. Ne w (Ptr 2);
6. P t r 2A := 86 ;

LO 4.5
Deducir la salida del siguiente programa.
program Pun te r o ;
type
Ptrin t = Ai nt e ger;
var
l , J : Pt rint ;
N : in t e g er ;
begin
Ne w ( l) ;
N ew (J) ;
N: = 5;
l A .-
. - N ,'
Wri t e Ln ( l A) ;
. - l ',
J .-
J A .. -
- - 7 ,'
Wri teLn
end.
134 Estructura de datos

EJEMPLO 4.6
Qu se imprime tras ejecutar el siguiente programa?

program Prueba S i mp l e ;
var p, q : Ainteger;
x, y : int ege r;
begin
ne w (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:


P

x 6 5

y 5 8

4.3.2. Variables de puntero con registros


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;
Estructuras de datos dinmicas: punteros 135

Pu n tEstu = A Estud i a nt e;
var
P I , P2 : PuntEs t u ;
begin
N ew (P 1 ) ;
P l A. Eda d -- l ',
A
P I .L etr a .-
- 'A" ,
WriteLn (PlA.Edad , Pl A. Letra) ;
New (P2) ;
A
P2 .E dad = 2,
P2 A . Letra : = 'B ';
Wr i teLn (P2 A .Edad, P2 A.Letra);
PI := P2 ;
A
P2 .Edad - 3 , -

P2 A . Letra := 'C' ;
Wr it eLn (PlA . Edad, P I A. Letra , P2 A. Edad , P2 A .L etra)
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 : Ain teger;

New (P) ;

. -- 17 ,'

En un puntero (P) se deben considerar dos valores:

P untero (P) Su valor es la posicin (direccin) de una variable integer.


P" 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 (P A) sen t enci a vl i da
Wr i te (P) sentenc i a no v l ida (error)

Asignacin
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 Y q A 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 Y q permanecen en distintas posiciones de
A A

memona..

\.,,~,~ ~-,-
~; . .'."""
.
::', _-- ' :--i.".

No se .
:,;
.. -, -

diferente . . . . ,'. .
"

, . "
, ,
i:
.' ",:. " " ,.......
" ."
.
" , '"
' .
,- ,

4.8
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) ;
P IA := 86 ; No se puede acceder a este valor-----
P2 A := 50 ;
P I:: P 2 ;
Writ e Ln (PIA, " , P2A) ;

Solucin
50 50 PI

86

P2

50
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, Dispo se 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 deja de existir.
A

2. P se vuelve indefinido.

La representacin grfica es:


I
p

situacin inicial

?
situacin despus de di spose (p)
p

EJEMPLO 4.9

1. var
p, Q: Ainteger;
begin
2. New ( p) ;
3. pA - 8;
-
4. Q -
- P;
5. QA -- 5;
6. Dispos e ( P)
end
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 h a r;
begin
p := nil;
i f p = nil
then
WriteLn ( ' e l punte ro P n o apun ta a n ad a')
else
Wr i t e Ln ( ' P se qu eda i n def in i d o apunta ' ) ;

proporciona la salida

el p unt e r o P no apunta a nada

..
,.- ,. . ,_o
,
.~;

............... ij. JC
.',.- .. -. ~r,i "l"--_

4.3.6. Naturaleza dinmica de los punteros


,
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 tero B: Aintege r;

las comparaciones:

if ( PunteroA = Punte r oB)


then < se nten c i a >;
if ( Pu nteroA <> Punt er o B )
then < se nt 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 ero B A)


then < sentenc i a >

Si dos punteros PI y P2 son del mismo tipo, el efecto de

Pl : = P 2 ;

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

Estructuras de datos dinmicas: punteros 141

La traza de memoria es

p p

Carpe Concha
,

q q

Dien Dien

La salida ser

Concha
Concha

4.3.8. Paso de punteros como parmetros


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

Cima de la memoria DOS

Lista libre (crece hacia abajo)

FreePtr

HeapPtr ~
Montculo (crece hacia arriba)

HeapOrg --I~ .... Ovr HeapEnd


Recubrimiento de Buffer
.... Ovr HeapOrg
Pila (crece hacia abajo)

SSeg:Sptr ~
Pila libre
SSeg:OOOO ~
Variables globales

Constantes con tipos


DSeg:OOOO ~

Segmento de cdigo de la primera unidad

Contenid o de una
imagen de
archiv o .EXE
Segmento de cdigo de la unidad System

Segmento de cdigo de la ltima unidad

Segmento de cdigo del programa principal

Program Segment Prefix (PSP)



PrefixSeg ~
Memoria baja

Figura 4.3. Mapa de memoria de Turbo Pascal 7.0.

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

~ El tamao de la zona
Aqu se almacena el cdigo Comienzo del de cdigo es el total
objeto. programa del tamao del cdigo
principal de programa principal
ms el tamao del
cdigo de todas las
unidades utilizadas
por el programa. El
Cdigo unidad n
tamao total del
cdigo slo est

limitado por la
memoria disponible.
Cdigo unidad 2

Cdigo unidad 1
--------------------~~ Tamao de la zona de
Comienzo de datos (suma de todas
datos las variables globales
Se almacenan variables
del programa principal
globales (estticas)
y todas las unidades
y constantes con tipos.
Fin de datos utilizadas). El mximo
es 65.520 bytes.
----------------------~~

Se almacenan variables de El tamao de la zona


subprograma, parmetros de la pila se establece
pasados y otros valores con las directivas del
auxiliares. Comienzo de la compilador.
pila
---------------------~ La pila crece hacia la
zona baja de la
Se almacenan variables Comienzo del
memoria.
dinmicas creadas por New y montculo
GetMen.
El montculo crece
hacia la zona alta de la
Cima del montculo memoria.

El tamao del
montculo se
establece con las
Espacio del montculo no opciones del
utilizado disponible para compilador. Si la
almacenar variables dinmicas memoria disponible es
adicionales. 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 Espacio ocupado en memoria
New Dispose MaxAvail
Mark Release MemAvail
Getmem FreeMem

4.5.3. New y Dispose


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)

varp un 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 pu n t, tamao)

varpun t variable puntero de cualquier tipo puntero


tama o expresin de tipo word

FreeMem libera una variable dinmica de un tamao dado.

Formato

FreeMem (varpunt, ta ma o)

Las variables asignadas con GetMem se liberan con FreeMem.


Estructuras de datos dinmicas: punteros 147

EJEMPLO 4.14
GetMem (y, 100);
FreeMem (y, ~OO);

Nota

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 : string[25J;
direccin : string[30J;
ciudad : string [20J;
edad : integer;
marca : 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 a j 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) Inicializa la lista.


Esvacia(L) Funcin que determina si la lista es vaca.
Inserprim(X,L) Inserta un nodo con la informacin X como primer nodo de la
lista L.
Inserta(X,P,L) Inserta en la lista L un nodo con el campo X, delante del nodo
de direccin P.
Inserfin(X,L) Inserta un nodo con el campo X como ltimo nodo de la lis-
ta L.
Localiza(X,L) Funcin que devuelve la posicin/direccin donde est el cam-
po de informacin X. Si no est devuelve nulo.
Suprime(X,L) Elimina de la lista el nodo que contiene a X.
Suprimedir(P,L) Elimina de la lista el nodo cuya direccin/posicin viene dada
por P.
Anterior(P,L) Funcin que devuelve la posicin/direccin del nodo ante-
rior a P.
Siguiente(P,L) Funcin que devuelve la posicin/direccin del nodo siguien-
te a P.
Primero(p) Funcin que devuelve la posicin/direccin del primer nodo
de la lista L.
Ultimo (P) Funcin que devuelve la posicin/direccin del ltimo nodo
de la lista L.
Anula(L) Esta operacin vaca la lista L.
Visualiza(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.
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 po inf 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 Elimin adup( var L : Lista);


var
P, Q : Posicion; { P posicin actual en L,
,
1 Q posici n avanzada )

begin
P : = Pr im e r o( L ) ;

while P<> nul o do ,
,

begin
Q := Siguiente (P , L) ; ,
,

while Q < > n u l o do


if Iguales (I nf o(P) , Info(Q)) then
Suprimedir (Q ,L )
el se ,
,

Q:= Sig uiente(Q,L); i


J.
P:= Siguien te( P,L ) :
j
end;
1
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 ,,


1

Max= 1 00 ;
I
,

-
Listas en/azadas: e/ TAO lista en/azada 157

type
Ti po in fo= {t i po d e l campo i n form a c i n d e c a da nodo}
List a = record
E leme ntos: array [l . . Max] of Tip o info ;
Ultim o: integer
end;
pos icion = O " Max;

El procedimiento Lis t a vac i a ( L) inicializa la lista, para lo cual simplemente se


pone a cero UI timo.

procedure Lis tav ac ialvar L: Lista);


begin
L .Ultim o := 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 : Tip oinf o ;var L : List a ) ;


var
l: i nte ger ;
begin
with L do
begin
for 1: = Ul t im o downto 2 do
Elemen tos [l+ l] := Elem e n tos[ l];
E le ment o s [1 ] : = X
ult im o : = ultimo + 1
end
end;

El procedimiento 1 n s e r t a ( X P, L) desplaza los elementos de la lista a partir de


I

la posicin P e inserta X en dicha posicin.

procedure lnsertal X: Tipo in fo;P : Posicio n; var L: L i s ta);


var
Q : Posicion;
begin
if L .Ul t im o = Ma x then
< err or : l ista L llena >
else if (P> L.u lt im o) o r IP< 1) then
. " .
< err o r: p oslclon n o eX l ste >
el se beg1n
for Q := L.U lti mo downto P do
{despla za lo s e le ment os a l a dere c ha}
L. Element os [ Q+ 1 ] : = L. Elemen to s [Ql ;
L . Ultimo := L.U lt imo+l ;
L . Elemen t os [ P ] : = X
end
end;
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}
L. Elementos [l] : = L. Elementos [l+ 1] ;
end
end;

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
Listas enlazadas: el TAO lista enlazada 159

Q: Pos i e i o n;
Le: bo o 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
Loea l i z a := O
end;

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 nte ro= ATipo ap unt 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
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
I
Pe: Ptrentero;
Pc: Pt r ca dena;

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
No mbre: stri ng[ 25 1;
Direcc: string[501;
Edad : intege r ;
Enlace: Ptrn odo
end;

Variables del tipo puntero Ptrnodo van a estar asociadas con variables referencia-
das del tipo Persona. '
var
P : Pt rn odo;
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.

,
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 (o una flecha).
A

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; Se asigna el campo Enlace de la variable referenciada por P l.
PIA.Enlace:= P2 A .Enlace;
P2:= nil; 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;

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 Mar Peter ... Urban nil

I,
Supngase los tipos
type
T i po i n f o =
Pt rn o d o = ANodo ;
No do = record
In f o : Tip o i nfo ;
Sgte : Ptrn odo
I end;

5.4. INICIAR UNA LISTA ENLAZADA


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 Listava c i a( var L: Ptrnodo);
begin
L:= nil
I
end;
I

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 v a cia := L = nil


end;


,

,

5.5. BSQUEDA EN LISTAS ENLAZADAS ,
,

1
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
1,,
-o

~
determinado; asimismo, se puede plantear una operacin Ex i s t e que sirve para deter- ,,
,
-~

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:Tip o inf o ; L : Ptrno do): Ptrnodo;


var
T : Ptrno do;
begin
T : = L;
while (TA . Sgte<> nil) and (TA.lnfo<> X) do
T: = TA .Sgte;
if T A. ln fo< > X then
Loca l iza : = nil
elee
Local iza := T
end;

function Existe(X: T ipoinfo ; L: Ptr nodo): bool ean ;


begin
if not Es vacia(L) then
begin
while (LA .l nfo<> X) and (LA . Sg te<> nil) do
L: = LA . Sgte;
Existe : = L A. lnfo=X
end
elee
Msge( ' Error en lla mada ' )
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: Ptr n odo ; L : Ptr nodo): 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 terio r:= n il
elee begin
while ( LA. Sgte< > P) and (L A. Sg te< > n i l ) do
L : = LA . Sgte ;

Anterio r:= 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 S i gu i en te (P : Ptrnodo; L : Ptrnodo) : P trn odo ;


begin
if Esvac i a ( L) o r (P =n il) then
S igu i e n te : =nil
else
,
,
S igu i en te : =P~ . S gt e

end;

, .
Ultimo (L)
Para obtener la direccin del ltimo nodo se ha de recorrer toda la lista.
function Ultimo(L:P tr nodo ) : Ptrnodo ;
{ El l ti mo de l i s ta vaca co n s i der a mos nil }
begin
if Esv acia ( L ) then
Ult i mo := ni l
else
begin
while LA . Sgte <> n i l do
L:= L ~ . Sgte ;
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 Crea r devuelve la direccin de un nuevo
nodo.
function Crear(X : T ipo i n f o ): Ptrnod o ;
var
N : Ptrnodo ;
begin
, n ew (N) ;
;
N ~ . In f o : = X;

N ~ . Sg t e : = nil;

Crea r: = 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 nil

A-- x

procedure In s e r p r im (X : T ipoin f o ; v ar L: Pt r n o do);


var
A : P t r n od o ;
beqin
A := Crear (X) ;
AA. Sgte:= L;
L: = A
end;

Inserta(X,P,L)

Aade a la lista L un nodo con el campo X, delante del nodo de direccin P.

p-

L- nil

A-....,
i
procedure I n se rt a(X : T i p o i n f o ; P: Ptrn o d o ; var L : Pt r n od o ) ;
var
A : Ptr n odo ; I
begin
A := Crea r ( X) ;
if Esvac ia(L) then
L: = A
elBe if P= L then
begin
AA. Sgte := P ;
L: = A
end
elBe begin {Ah ora es cuando se en l aza el nu evo n o do e n t r e e l n odo
a n t er i or y e l n o d o P }
Anter i or( P ,L ) A. Sg t e : = A;
AA. Sg t e := P
end
end;
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 In serta(X : T i po i nfo ; P: Ptrnodo ; var L: Ptrnodo) ;


elae
begin {E l nuevo nod o es enl azad o a cont inu ac i n de P, d espus s e
intercamb i a el ca mpo Info }
AA . Sgte : = p A. Sgte ;
pA . Sg t e : = A;
AA . lnfo := P A. lnfo ;
pA .lnf o : = X
end;

Inserfin(X,L)

Aade un nodo con el campo X como ltimo nodo de la lista.

L- N1 N2 N x nil

procedure Inserfin(X : T i poinfo ; var L: Ptrnodo) ;


.
, var
.
A: Ptrno do;
I begin
A := Crea r (X) ;
if Esvac i a( L ) then
L := A
elae
Ult i mo(L)A. Sgte : = A
end;

5.8. SUPRESiN DE UN ELEMENTO DE UNA LISTA


I
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 N2 N3 N4 O " - N nil

Suprime(X,L) Se elimina el nodo que contiene a X.


- -- - - -
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 liz a( L: Ptrnodo );


var
Q : Ptrno d o ;
beg1n
Q := L;
wh11e Q< > n11 do
beg1n
wr ite ln (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: Inse ror d 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 .

i
Listas enlazadas: el TAO lista enlazada 169

function Pos i nser(X : T i poi nf o ; L:Ptrn o d o ) :Pt r n o d o ;


var
T : P t rn o do ;
begin
T : = nil;
if Not Esvacia (L) then
begin
while (X >= L A. Inf o ) and (L A.Sgte<> ni l) do
begin
T:= L;
L : = LA . Sgte
end;
if X>= L A.In fo then {Es e l lt i mo n odo}
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 91 nil

37
N

procedure In serorden(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 co mo prime r n odo}
begin
NA.Sgt e : = L;
L:= N
end
elee begin
NA.Sgte:= AA.S g te ;
AA. Sgte : = N
end
end
end;
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 Or contiene un procedimiento El i mi 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- J
I

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;
Listas en/azadas: e/ TAO lista en/azada 171

Nodo = record
Inf o :Tipoinfo;
Sgte : Ptrnodo
end;
function Posinser (X:Tipoinf o ; L:Ptrnodo) : Ptr n od o ;
procedure Inserord e n (X : Tipoinfo, var L:Ptrnodo) ;
function Busc orden (X : T ip oinf o ; L :Ptr nodo) : Pt rn odo ;
implementation
.. . {C dig o correspondiente a los procedimientos / fu ncion es escrit os
anterior ment e }
end .

Codificacin del programa

program ListaOr(input, output);


uses Lista Orde n ada , Crt ;
const
Ele mentos - 55 ; ,

M = 99; i
var
L,Q:Ptrno do ;
Y: i n t ege r;

procedure Eli mi nar Du p(L : Ptrnodo);


var
A, Q: Ptrno do;
begin
A : - 'L ;
while A <> n i l do
if A ~ . Sgt e<> nil then
if A ~ .Info=A~.Sgte ~ . Info then {Un repetido}
begin
Q := AA . Sg te ;
AA. Sgte : = QA .Sg te ;
d i spose(Q)
end !
else A: =AA . Sg t e
else A:=AA . Sg te
end;

procedure Mo strar (L :P t rn o do);


var
Q:P t rno do ; ,
begin
Q: =L;
while Q <> ni l do
begin
wr ite (Q A.lnfo, " ); Q : =Q A.Sgte
end
end; , ,
. ' ;' .
begin {Bloque ppal }
L : =Nil; randomize;
for Y:= l to El ementos do
Ins e ro r de n (Random (99)+1, L );


172 Estructura de datos

c l rscr ; {l a l ista es mostrada}


Mos tr ar(L) ;
{Los e l ementos duplicados son e lim i nados d e la lista ordenada}
EliminarDup{L) ;
gotoxy(1 5, WhereY+l);
writel n ('L ista sin eleme n tos duplic ados') ;
Mostr ar(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.
!
i 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-
I 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 VectD ina;


interface
const
Mx=20;
type
Te l e m=r ea l;
Pt r= AEl e m;
Elem= record
Dat : Tele m;
Sgte :Ptr
end;
Tvect or=record
A, Ult:Ptr;
N : i n t eger {nmero de eleme n to s del vector}
end;

procedure Cr eac i on (var V :T vecto r );


function Dir eccio n (V :Tvector ; X: Te l em) : Ptr ;
function An t e ri or (V :Tvector ; W: P t r ) :P t r ;
procedure Asig n ar (var V: Tvector ; T: Te l e m) ;
procedure Bo rr ar (var V : Tvector ; T : Telem ) ;
procedure Mo st rar (V :T vector) ;
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. 1
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.

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, L 2 . 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_d e _Ent e r o s para encapsular el tipo lista de nmeros en-
teros.
Escribir la unidad L i 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.
178 Estructura de datos

5.9. El polinomio P(x) = Go + G1X + G:zX 2 + ... + 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
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
--1_ _' - - .- ... A ni!

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) Inicializa la lista.
Esvac i a (Ld) Funcin que determina si la lista es vaca.
In s erprim (X,Ld) Inserta un nodo con la infOJ macin X como primer nodo de
la lista Ld.
In serta (X,P,Ld) Inserta en la lista Ld un nodo con el campo X delante del
nodo de direccin P.
,
I nse rf in (X,Ld) Inserta un nodo con el campo X como ltimo nodo de la lis-
I ta Ld.
Loca li za (X , Ld ) Funcin que devuelve la posicin/direccin donde est el cam-
po de informacin x. Si no est devuelve nulo.
Suprim e (X,L d) Elimina de la lista el nodo que contiene a x.
Suprimed ir ( P,L d) Elimina de la lista el nodo cuya direccin/posicin viene dada
por P.
Prime ro (P) Funcin que devuelve la posicin/direccin del primer nodo
de la lista L.
ultimo (Ld) Funcin que devuelve la posicin/direccin del ltimo nodo
de la lista Ld.
Anul a (Ld) Esta operacin elimina/libera todos los nodos de la lista Ld.
visualiza ( 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-
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
T i poi n for - ... ;
P trndble = ANododble
Nod odb l e = record
I nfo : T ipoinf o ;
Sgt e , An te r: Pt rn db l e
end;

6.2.1. Creacin de nodos en la lista


Las operaciones utilizadas sern Cargar la lista (L i s taVa c 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 Esva c ia (Ld: Pt r ndble) : boole a n ;
begin
Esvacia : = Ld = n i l
end

Localiza
Devuelve la direccin de un nodo o ni l.
function Loca li za (X : T i poi n f o ; Ld : Ptrndb le) : Ptr n d b le ;
var
T: Pt rn dbl e;
begin
T : = Ld ;
if not Esvaci a (Ld) then
while (T A. Sgte < > n il) and (TA . lnfo < > X) do
T : = TA . Sgte ;
if T A. l n f o < > X then
Loca liza : =ni l
else
Locali za : = T
end;
!
,

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 Existe (P: P t rndb l e ; Ld:Ptrndbl e) : b oo lean;


, begin

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


begin
while ( Ld <> Pi and ( Ld A. Sgte<> nil ) do

Ld := Ld A.S gte ;
I Exis te := Ld = P
end
elee
Msge ( 'Err or e n l lamada ' )
end

Ultimo (Ld)

La operacin Ul tim o 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 nd ble) : 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
n e 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

P ~ . Sgte : = N;
N~ . Ante r: = P
end
end;

nil

Insertafin (X, Ld)

Aade un nodo con el campo x como ltimo nodo de la lista.

nil .. .

L ni I

procedure In sertafin (X : Ti p oinfo ; var Ld : P trndbl e);


var
N, U : Ptrndb l e ;
begin
N : = Cre ar (X) ;
if Esvac i a (Ld) then
Ld : = N
else begin
U := Ultim o (L d);

U~ . Sgte : = N;
N~ . Ante r := U
end
end;

6.2.2. Eliminacin de nodos


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-----------,
I I
I


nil ni 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)
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 ,l
3 Mertoli 7 ,I
<


4 Tonino l
5 Rufis A 3 1
6 Rios e
j

7 Fausto F
8
nil

8 Slisa N 3

9 Doroteo

---~---- .

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 Sg t e

- - - --.

Los tipos de datos y operaciones con lista doble de asegurados en la unidad Lis tA sg.

Unidad ListAseg
unit Lis t Aseg ;
interface
type
Ca dn a30 =st ri ng[30] ;
Cadna1 1 =st ri ng [1 1 ] ;
PtrAs= ~NodoAs ;
NodoAs= record
No mbre :Cadna 30 ;
I dt : Cadna11;
S_ asg : Pt r As; {Referenc i a a si guien te asegurado de u n mismo md i co}
Anter , Sgte : PtrAs
end;

{Oper aciones}
procedure Li stavacia (var Ld : PtrAs) ;
function Esva cia ( Ld: Pt r As ) : boole an;
function Localiza (x : Cadnall ; Ld:Pt r As) : PtrA s ;
function Ex i ste (P : PtrAs ; Ld : PtrAs) : boolean;
function Ult i mo (Ld : PtrAs) : PtrAs ;
procedure I nse rta (Nm: Cadna 30; I d : Cadnall ; P :P trAs ;var Ld : Pt rA s) ;
procedure In se rtad (Nm: Cadn a3 0 ; Id : Ca dnal1 ;P: PtrAs ;var Ld :Ptr As) ;
procedure Insertafi n (Nm:Cad n a 30 ; Id : Cadna l 1 ;var Ld :P trAs) ;
procedure Sup r ime (I d: Cadnall ; var Ld : Pt r As) ;
procedure Su pr emedir(P : PtrAs ; var Ld: Pt r As) ;
procedure Vis uali z a (Ld : Ptr As);
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 : Cad nal l ; P :P t r As ; var Ld :P t r As );


{A ade a l a l i s ta Ld un nodo co n e l campo X, de l a n te d e l n od o P }


var

A :P tr As ;
begin
A:= Cre a r (Nm, Id);
if Es vacia (Ld) then
Ld : =A i
el se if p=Ld then {D e l ante del pri mer n odo}

begin
AA . Sg te:=P;
p A. 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 n o d o
ante r i or y el nodo P}
pA . An t erA.Sgte:=A;
AA.Anter:=pA.An ter ;
AA. S gte:=P;
p A.Anter:=A
end
end;

procedure I nse rtad (Nm : Cad n a30 ;I d : Cadn a ll;p: Pt rA s; var Ld :P t rAs ) ;
{Aa d ir nodo c on el campo X a con t i nua cin de l nod o 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 = Ultim o( Ld ) then
In se rtafin(Nm,Id,Ld )
else if Existe(P,L d) then
begin {Ahora es cua n do se enl aza el n ue v o nodo, a co n ti nuacin
d el n odo P}
N: =C r ea r (Nm, I d ) ;
pA . Sg t eA . An ter : =N ;
NA. Sg t e :=p A. Sgte ;
p A. Sgte :=N;
NA. An te r:=P
end
end;

procedure Insertafin (Nm: Cad n a30 ;Id:Cadnall;var Ld :P trAs );


var
N, U: PtrAs;
begin
N : =Crear(Nm , I d) ;
if Esva c i a ( Ld ) then
Ld:= N
else begin
U: =Ult imo (Ld) ;
UA. Sgt e :=N;
NA . An t er := U
end
end;
190 Estructura de datos

{Borrado de n odos}
procedure Sup r ime(Id:Cadna l l ; var Ld: Pt r As) ;
var
P : PtrAs ;
begin
P : =Loca liza(I d , Ld) ;
if P<> nil then
Sup rimedir ( P , Ld)
el se
wri teln ( ' Error en la l lamada .' )
end;


procedure Su p 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 :P t r As) ;


procedure Esc r ibir(A : NodoAs) ;
begin
write(A . No mbre} ; 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 tM e d.
Unidad ListMed
unit Li stMe d;
interface
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
A
Posinser:=L . 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 Busc or d e n ( X : Cadna30 ; L :P t r Mdl : Pt r Md ; ,,


var
T:P t rMd ;
begin
T: =L ;
while (TA.Sg te <> n i ll and (TA .Nombre < Xl do
'.
T : =TA.Sgte; ~
if TA .Nombre =X then
Busc orden:=T
el se
,
Busc o r d e n : =nil
end;

procedure Mos t ra r (L : P trMd l ;


var
Q : P t r Md ;
begin
Q : =L ;
while Q<>nil do
begin
writeln(QA.N ombr e ," , QA.F o no); Q: =QA. Sg te
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,ListM e d, Crt;
var
Lme d , Md : PtrMd ;
Las g : PtrMd ;
Fme d , Fasg : T e x t ;
Nb : Cadna3 0 ;
Ch : char ;
Listas doblemente enlazadas 193


procedure Medicos(var Lm:PtrMd);
,

var
,
Nm:Cadna30;F:Cadnall; ,

J:integer;
\
begin
!
Lm:=nil;
\,
repeat i
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;

{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
L:=L~.Sgte;

K:=K - l
end;
Posicion:=L
end; ,
,

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

,
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 A D lista circular. Estas operaciones coinciden con las definidas en los T AD lista y
lista doblemente enlazada

Listavaei a (Le) Inicializa la lista.


E sva e i a (L e) Funcin que determina si la lista es vaCa.
Primero ( Le) Devuelve la direccin del primer nodo.
Ultimo (Le) Devuelve la direccin del ltimo nodo.
Ante r i o r ( P, Le) Devuelve la direccin del nodo anterior a P.
In s 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 se r f i n (X , Le) Inserta un nodo con el campo X como ltimo nodo de la lista L e .
Loc al i z a (X , Le) Funcin que devuelve la posicin/direccin donde est el cam-
po de informacin x . Si no est devuelve nulo.
S upr i me (X , Le) Elimina de la lista el nodo que contiene a X.
Sup r i med i r (P , Le ) Elimina de la lista el nodo cuya direccin/posicin viene dada
por P.
v is ual 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;
"'- -- -- - - _._ _ -- --
.. . - -- - -- ------ _ . _ - - - -- --

Listas doblemente enlazadas 197

if AA.Sgte= P then
An te ri o r:= A
elBe
An te rior:= ni l
end
end;

Loealiza(X, Le)

Funcin que devuelve la posicin/direccin donde est el campo de informacin X. Si


no est devuelve nulo.

function Loc aliza ( 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 T A.lnf o < > 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(L e ) 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 -- X ,
NA.Sgte -- N ,
Crear := N
end;

f-
A Al aadir un nuevo nodo: Le A B
~ ~

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
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

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
Tip oin 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:PtrDn c) ;


var A:PtrDne;
begin
if not Esvacia ( Ld e) then
begin
A:=Lde;
repeat
A := AA.Sgte;
Eseribir(AA.lnfo)
until A = Le;
end
end;

.. ..
rt t

a)

Cabecera --,

b)
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(D A.lnfo) ;
D:=D A.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:=q A.dcho
elee
begin
{"saca" de la lista el nodo q}
qA.izd o A.dcho:=q A.dcho;
202 Estructura de datos

if q A.dcho <> nil then


q A . d e hoA.l.Z
' d O:=q A .l.Z
' d O;
{aade q c om o anterior a p}
aux:=qA.d c 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:=P A.dcho
end
end;

procedure ordeneir (var el:ptro);


var
aux:ptro;
begin
if el<>nil then
begin
aux:=cl A.izdo ;
aux A.dcho :=nil;
cl A.izdo:=nil;
ordenar (el);
aux:=el;
while aux A.dcho <> nil do
aux:=aux A.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;
,"

,
,

Listas doblemente enlazadas 203

Ptrlc = ANodolc;
Nodolc= record
Info : Tinfo;
Sgte : Ptrle
endl
function Direccion(L c 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; I
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.
,
1

i"
,l
,

RESUMEN ,

l
1
1
,,
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.
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.

i
6.9. Dada la representacin de lista circular propuesta en 6.8, escribir las operaciones Lista_vaca
y la funcin Esvaca.
,"
,
,f 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
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) Crea una pila sin elementos.


Esvacia(P) Devuelve verdadero si la pila P no tiene elementos.
Cima(P) Devuelve el elemento que est en la cima de la pila.
Suprime(P) Elimina el elemento que est en la cima de la pila.
Sacar(X,P) Devuelve el elemento cabeza y lo suprime.
Meter(X,P) 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;

210 Estructura de datos

Sacar(X, P)

Esta operacin devuelve el elemento cabeza y lo suprime.

procedure Sacar(var X:T ipoe 1emen; var P:Ti pop i1 a) ;


begin
if not Esvacia(P ) then
with P do
begin
X:= Ele me 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: T ipo e1emen; var P: Tip opi1a) ;


begin
if not P11ena(P) then
with P do
begin
Ca b:= Cab+ 1;
E lementos[CabJ: = X
end
end;

1
,

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) ; I
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 DI ANTE VARIABLES


DINMICAS
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.
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 d e los el emen tos de l a p i l a}
ptrp l a= ANo doPla;
Nodopla= record

Elemen t o : T i poeleme n;

Enl a ce : PtrP l a
, end;
I Pilavacia(crear pila)

Crea una pila sin elementos.

procedure Pil ava ci a( var Pila : Ptr p l a) ;


begin
,

Pi l a := n il
end;

Esvacia

Funcin que determina si la pila no tiene elementos.

function Esvacia(P il a : Pt rp l a) : boo l ea n;


begin
Esvac i a : = pil a= n i l
end;

Cima(Pila)

Devuelve el elemento cabeza de la pila, sin modificar la pila.


I
Pilas:elTADPila 213

, function Cima(Pila: Ptrp l a): Tipoel e men;


begin
if not Esvac i a( Pila) then
Cima := pi laA .El e me nt o
end;

Suprime (Pila)

Con esta operacin se elimina y libera el elemento cabeza, modificando la pila.

procedure Sup rim e( var Pil a : Pt rpl a) ;


var
Q : Ptrpla;
begin
, if not Esvac i a( Pi la ) then
begin
Q : = Pil a ;
p ila:= PilaA .Enla ce ;
d ispose (Q)
I,
end
end;

"'"

Pila

,
I

Sacar(X, pila)

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

prime.
I
procedure Sacar( var X: Tipoe l eme n; var Pila : Ptrpla) ;
var
Q : P t rp la ;
I
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.

----,
-- --
- --
--- -
Pila

nil

procedure Meter(X: Tipoelemen; var Pila: Ptrpla);


var
Q: Ptrpla;
begin
new(Q) ;
QA.Elemento:= X;
QA.Enlace:= Pila;
pila:= Q
end;
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,

Par n t esis
() nivel mayor de prioridad
1\
Po t enc ia
Multip l / di v isi n : *, /
Suma / Resta
+, - 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 (pol a c a )


A* B / A+C (infi j a) --7 * AB / A+C --7 I * ABA+C --7 + / *AB AC (po l aca)
(A - B) ~C +D ( i n f i j a) --7 - A B ~C + D --7 ~-ABC +D --7 + ~ - A BC D ( p o la c 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.

l
,
..
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 F) - G) - H, la expresin en postfi-
A

ja se va ir formando con la siguiente secuencia:

Expresin Estado de la Pila


A Carcter A a la expresin; carcter * a la pila.
AB Carcter ( a la pila; carcter B a la expresin.
ABC Carcter + a la pila; carcter C a la expresin.
En este momento el estado de la pila es
+
(
* ,
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:
ABC+
ABC+D Carcter ( a la pila; carcter D a la expresin.
ABC+DE Carcter / a la pila; carcter E a la expresin.
ABC+DEF 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
ABC+DEFAj
ABC+DEFAj- Carcter - a la pila y se extrae a su vez -;
ABC+DEFAj-G Carcter G a la expresin; carcter ), son extrados
de la pila los operadores hasta un ( la pila queda *
ABC+DEFAj-G-* Carcter -, se saca de la pila * y se mete -
ABC+DEFAj-G-*H Carcter H se lleva a la expresin
Fin de entrada, se vaca la pila:
ABC+DEFAj-G-*H-

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 . Prioridad fuera pila


!Operador

/\
3 4
*, I 2 2
+, - 1 1 ,

( O 5
,
,
,
I
Obsrvese que no se trata el parntesis derecho ya que ste provoca sacar operadores 1
de la pila hasta el parntesis izquierdo. El algoritmo de paso de notacin infija a postfija: I,
,,l
l. Obtener caracteres de la expresin y repetir los pasos 2 al 4 para cada carcter.
I,

2. Si es operando, pasarlo a la expresin postfija.


-1
3. Si es operador:
1
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 1
1
cima de la pila, meterlo en la pila y repetir a partir de 1.
1
Si la prioridad del operador es menor o igual que la prioridad del opera- !I
dor de la cima, sacar cima de la pila y pasarlo a la expresin postfija, vol- ,
,
'J
ver a 3. 1
I
4. Si es parntesis derecho: 1,,
,
I
4.1. Sacar cima de pila y pasarlo a postfija. ,,
1
'o!

4.2. Si nueva cima es parntesis izquierdo, suprimir elemento cima. :


~
j
4.3. Si cima no es parntesis izquierdo, volver a 4.1. 1
.,,,
4.4. Volver a partir de 1. j,
5. Si quedan elementos en la pila pasarlos a la expresin postfija. 1

6. Fin del algoritmo.

, , ,
7.5. APLlCACION PRACTICA
, DE LA
, EVALUACION I,
J
DE UNA EXPRESION ARITMETICA :
,I
,
,,
,
,
,

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
Pilas:elTADPila 219

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);
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) ;
A~.Info := Ch;
A~.Sgte := 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:= P~.Info
end;

procedure Pborrar(var P: Plaopr );


var
A: Plaopr ;
begin
if not Pvacia(P) then
begin
A: =P;
P:=P~.Sgte;

dispose(A)
end;
end;
end.
1,I
,,

j
222 Estructura de datos I
,!
I
Psacar(It, P); j
un ti l I t = ' ( , ; 1
.~

end;
end;
repeat
Psacar(It, P);
J:= J+l;
Ar [J] . e : = 1 t ;
Ar[J] .oprdor:= true;
until Pvacia(P); l,

end; {del procedure} iI
end.
.,i
j
,
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;
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-Num 2
end;
Pometer(Valor, Pila)
end;
until 1= N
end;
begin
c lrscr;
writeln( 'Expresin aritmtica(termina # ) ' ) ;
Postfija(T, J);
writeln( 'Asignacin de valores numric os 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+Z I\-
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. 1
1
7.7. Utilizando las operaciones del TAD pila, escribir una operacin de copia, tal que devuelva 1,,
,,
la copia de una pila. I
7.8. Escribir una funcin para determinar si una secuencia de caracteres de entrada es de la I

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 #.
,
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) Crea la cola Q como cola vaca.


Qvacia(Q) Nos devuelve cierto si la cola est vaca.
Frente(Q) Devuelve el elemento frente de la cola.
Qborrar(Q) Elimina el elemento frente de la cola.
Qanula(Q) Convierte la cola en vaca.
Quitar(X,Q) Elimina y devuelve el frente de la cola.
Qponer(X,Q) 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 ~
II definicin del tipo de elemento
I

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 Se ha dejado un hueco no uti-


lizable, por lo que se desapro-
t t vecha memoria.
frente final
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 . Fre n 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 : T i 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 : T i poe l emen ; var Q: Cola) ;
procedure Desplazar ;
var l: posi cion ;
Colas y colas de prioridades: el TAO cola 231

begin
for I :~l to Q . F i nal - l do
Q . Da t o s [ 1 J : ~ Q . Da t o s [ 1 + 1 J
end;
begin
X: = Q .Datos[F rent 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/"
~Frente
---
" - -,

~*-
_o,
::...-
0_. _

I~-------vr--------~I
i ~Frente
Cola

Figura 8.2. Arrays circulares.


232 Estructura de datos

Final-----n~'{...2
n 1

p S B p 2....--Final


3

A
4
'Frente
T

i ~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 n 1

B p 2 2
/Frente
u
W 3 Final W 3

A
4
~ Frente

Figura 8.4. Insercin de nuevos Figura 8.5. Supresin de un


elementos en un array circular. 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 Qllen a(Q : Co l a ) : bool ean ;


begin
Ql l e na := Sig u ie n te (Sig u i e n te(Q .F i n a l ) )= Q . F r e nt e
end; i

Frente (Frente(Q
function Frente (Q : Co l a ) : Ti poe l e men;
begin
if not Qvacia (Q) then
Fr ente := Q . El e men tos [Q . F ren t 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 1

if not Qvacia (Q) then 1
l
Q . Fren te:= Q . Fr e nt e+ l
end;
i
Quitar (Quitar(X, Q 1
1
Elimina y devuelve el frente de la cola. En realidad esta operacin es un compendio de
las operaciones F rente y Qborrar.
procedure Quita r( var x: T i poeleme n; var Q : Col a );
,
,
begin
X : = F rente(Q);
Qb o rra r(Q)
end;

n ~--Final

e 2

3
-Frente
Q
4

o
p
5
6

Figura 8.6. Llenado del array circular.


;

Colas y colas de prioridades: el TAV cola 235

Qponer(X, Q)
Aade el elemento X a la cola. Se modifica la cola por el extremo final.

procedure Qp oner(X : Ti poel eme n; var Q: Cola) ;


begin
if not Qllena (Q) then
with Q do
begin
I Fina l:= S i guiente(F inal);
,

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 nil

Figura 8.7. Cola implementada con lista enlazada.

I
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 le na). Al ser una estructura dinmica crece y decrece segn
las necesidades. Las declaraciones para la representacin de cola mediante listas:

type
Tipoelemen - ... ;
Ptr n 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 Qcrea r(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) : boolea n;
begin
Qvacia := Q.Fr ente= n i l
end;

Frente (Frente (Q) )


Devuelve el elemento Frente de la cola.
function F r e n te(Q : Co l a) : Tipoe l e me n;
begin
if not Qvacia(Q) then
Frente := Q . Fren t e A. lnfo
end;

Borrar (Qborrar(Q
Esta operacin modifica la cola, elimina el elemento frente de la cola y es liberado.
procedure Qb o r rar( var Q : Cola) ;
var
A : Ptrnodoq ;
begin
if not Qvac i a(Q) then
with Q do
begin
A : = F re n te ;
Frente := F renteA . Sgte ;
,,
if Frente = nil Then ,
F inal:= nil;

d i s pose(A)
end
end;

Quitar (Quitar(X,Q
Elimina y devuelve el frente de la cola.
procedure Quitar( var X : Tipoele me n; var Q : Co l a);
begin
X : = Fren t 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); T~.rnfo:= x; T~.Sgte:= 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
Final~.Sgte:= 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;
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;
Colas y colas de prioridades: el TAO cola 239

Quitar(X, Q)
I

procedure Quita r (var x:Tipoelemen; var Q:Cola);


begin
X : = Frente (Q) ;
Qborra r(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 co n campo xl
, if not Qvacia(Q) then
begin
NA. Sgte : = QA .S gte ;
QA . Sgt e: = N
end
Q : = N;
end;

8.6. BleOlAS
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:
,
Cre arB q (Bq) : inicializa una bicola sin elementos.
Esvaci a (Bq) : devuelve verdadero si la bicola no tiene elementos.
Inserlzq (x, Bq ) : aade un elemento por extremo izquierdo.
InserDch (x , Bq) : aade un elemento por extremo derecho.
i Elimnlzq (x, Bq) : devuelve el elemento Izquierdo y lo tetira de la bicola.
Eli mnD ch (x , Bq) : 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.
,
,

i,
240 Estructura de datos

Frente: 3
LUZ AGUA RIO
Final: 5
1 2 3 4 5 6 7 8

Al aadirse el elemento SOL por el frente

Frente: 2
SOL LUZ AGUA RIO
Final: 5
1 2 3 4 5 6 7 8

Puede eliminarse por el final

Frente: 2
SOL LUZ AGUA
Final: 4
1 2 3 4 5 6 7 8

Figura 8.9. Estructura tipo Bicola.

PROBLEMA 8.1

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);
!
Colas y colas de prioridades: el TAO cola 243

procedure In s 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);


,i
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:Bic ol a;var Ok:boolean);


{Esta operac in retira una avioneta. O bien por un extremo, o bien
intermedia}
var
i D: integer;
I
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) ;

I
244 Estructura de datos

until Bq.Sa l ida=D;


Elisalida ( A,Bq); (es retir ado el elemento pedido)
(Son intr odu cid os los el e mentos saca dos)
repeat
Psacar(A,Pl ) ;
In sSalida(A ,Bq )
until Pva c 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 ,Bic o la ;
var
u: Avi on eta;
Ch : char ;
Bq : Bicola;
Bqw: Bi co la; {Bi co la de espera de e n trada en estacionamiento}
Sw: boolea n;
begin
clrsc r ;
CrearBq (Bq) ; Crear Bq ( Bqw);
write ( 'La entrada inter a ctiva, son lneas con un cha r y ');
writeln( 'nm ero matr icu la:E( l legada) , S(S al ida) ' ) ;
repeat
repeat
read(Ch) ; Ch := upcase(Ch)
until Ch in[ 'E', ' S ' J ;
re adl n (U) ;
if Ch = 'E' then
if not Esl lena (Bq) then
InsEnt rada (U,B q)
el se
En s Entrada(U,Bqw); {se aade a b i co la d e espe ra}
el se {re t irada de avio ne 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 TAD 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 may or 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 en tif = ... {Tipo de l i d e ntif icado r d el p r oceso}
Ti po_ proceso = record
Idt: Tipo_ i d e nt i f;
Prio ri 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 ~ 1P21 ~I P31 r.lp21 I ~lp221 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;
No doq= record
info: Tipo_pro ceso ;
sgte : Ptrnodoq
end;

Cp

1 P1 Q1 Ip11 P12 P1KI

2 P2 Q2 Ip21 P2K I

n Pn Qn 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 : in teger ;
fr e n t e ,
f ina l: Pt rn o do q
end;
Tabl a_cp = array[ l .. Max_p ri 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 (Ma x _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.
Colas y colas de prioridades: el TAO cola 249

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;

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

Nu mcola := J
elee
Numco l a := o
end;

function Qmaxp ri (var Tcp : tab l ac olas): int eger ;


{Bu sca cola de mx ima prioridad . si toda s las t a r eas e stn pro cesadas
devuelve Ol
var
J ,K: i n teger;
M: integer ;
begin
J: = O;
K : = O;
M: = Ma x_pr ior + 1 ; { valor de arra n que }
while J< Max_prior do
if not Qvac ia(Tcp [ J ] ) and (Tcp [ J] . Prd< M) then
begin
K:= J;
M:= Tcp[J]. P r d
end;
Qma x pr i:= K
end;

procedure pr esentar _ proc ( T : Co l aQp) ;


{ Es t e p r oce d im i en t o mue s t ra en pa n talla la tarea que va a ser procesada }
begin
if LL = O then
clrscr ;
LL : = LL+1
write (T.Frent eA . lnfo .T area ) ;
Write ln( 'Prio ri da d :', T.FrenteA.Info.P rior) ;
if (LL mod 24) = O then
begin
de la y(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 ',
'L E ER DISCO ', ' COMP I LAR ' , ' HWAX ' ,
, EJECUTAT ' , ' ES TA T ' , ' TMTAX ' ) ;
begin
if K i n [1 .. Max_ prior ] then
Tarea := Tar eas [ K]
end;
Colas y colas de prioridades: el TAO cola 251

begin
N := random( Nt) + 1 ; {Tarea al azar}
X .Ta rea : = Ta rea(N );
N := random(Max _ prio) + 1 ; {Prioridad al azar}
X. P rior:= 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 ' ) ;
ha lt( l )
end;
Tcp[N ] . P rd : = X . Prior ;
Qponer(X , T cp[N])
writ eln( ' S E GENERA TAR EA N Q : ' , J)
end;

procedure procesar _ proc (var Tcp:Tablaco l as ; var En co : boolea n );


var
1 : i ntege r;
begin
1 : = Qmaxpri(Tcp) ; {Co l a de mayor pr i oridad}
En c o : = 1<>0 ;
if 1 <> O then
begin
p resenta r_proc( T cp [ l ] ) ;
borrar (Tcp [ 1 ] )
end
end;
begin
LL : = O; {Para presentar ta r eas procesadas }
end.

Codificacin del programa de gestin de colas de prioridades

program Co l asdeprior i dades ;


uses
u nit co l a , c rt;
var
Tab l aq : Tab l aco l as;
1, J : in t eger;
Hm: boole a n ;
C : char ;
begin
ra n domi ze ;
CrearQp (Tablaq , max_ prio r ) ;
{El b ucl e se real iza max_proc * 3 di v 2 ite raci one s par a que
se generen Ma x _proc tareas . Por cada tare a p r ocesada , se
genera n dos n u evas}
J : =O ;
for i:= 1 to (Ma x_p roc*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_pr o c (Tablaq,j);
end;
repeat
pr o ce s ar_pr oc (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
T ipoele m = c har ;
Ptr Pi l a =Altemp;
Itemp = record
I n f o : T i poelem;
Sgte : P t rP il a
end

procedure Pilava cia( var Pil a : PtrP ila);


function Pvaci a(P il a: PtrPi la) : boo lea n ;
procedure Pm e ter(X : Tipoelem; var P i la : Pt r Pila) ;
procedure Pc ima( var X: Ti poe l e m; Pi l a : Ptr Pila) ;
procedure Pbo rr ar( var Pi l a : PtrP il a) ;
procedure Ps a car( var X: T i poelem ; var Pila : PtrPila) ;
{Fin de la secci n de i nter faz}

Codificacin de la unidad Colas


unit Lf ifo ;
interface
type
T ipoi nf o - in teger ;
Ptrnodoq =ANodoc;
Nodoc = record
In f o : T i p o inf o ;
Sgte : Pt rn odoq
end;
Col a = record
F r en t e ,
F i na l: Pt r nodoq
end;

procedure Qc re ar(var C : Cola);


function Qvacia (C : Co l a ): b oolea n;
procedure Qpone r(X : T i p oinf o ; var C :Col a) ;
procedure Qbo r rar( var C : Cola) ;
function Fre n te(C : Co l a) : T ipoi n fo ;
procedure Qu ita r (var X : Tipoi n fo ; var C : Co l a) ;
implementation

procedure Qcrea r ;
begin
C . Frente := ni l ;
C .F inal : = nil
end;

)
~

254 Estructura de datos

function Qvacia;
begin
Qvacia := (C .Fren te - nil)
end;

procedure Qponer;
var
A: pt rno d.,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
A := C.Frente;
C. Frente : = C.FrenteA.Sgte;
dispose(A)
end
end

function Frente;
begin
if (not Qvacia(C)) then
Frente := C.FrenteA.lnfo
end

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, P ila , Lfif o ;
var
Datos: text;
pla : Ptrpil a ;
Lfo : Cola;
-----------------------------..

256 Estructura de datos

if not Qvacia(Lfo) then


Qu i tar(52, L fo);
5 2 : = 51 +52 +R;
R : = 52 div 10;
52 := 52 mod 10 ;
Qp o n er (5 2, Nq )
end;
while not Qvac i a( L fo) do
begin
Quit a r(52 , L fo) ;
52 := 52+R ;
R := 52 d i v 10 ;
52 := S2 mod 1 0 ;
Qponer(S2 , Nq)
end;
if R <> O then Qpo ner (R , Nq ) ;
L f o : = Nq
end;

procedure Escribir(Q : Cola) ;


var
N : integ er;
begin
if not Qvacia (Q) then
begin
Qu i t ar (N, Q) ;
Esc ri b ir (Q) ;
write(N)
end
end;

begin
Abrir(Datos) ;
Qcrear( Lf o);
while not eo f (Dat os) do
begin
Leer n u mero(Datos , P l a);
Su ma r(Pl a, L fo)
end;
if not Qvacia(L f o) then
begin
wri teln( ' Res u l t ado d e l a suma d e n me r os gr an des ');
Esc ri b i r(L f 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:
1,
,

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
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 acerc~ndo a los valores de los
que depende la condicin de terminacin.
j
I
1
9.2. CUNDO NO UTILIZAR RECURSIVIDAD 1,
1
~

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 1
<

recursivas a procedimientos o funciones tienen un coste de tiempo mucho mayor que sus ,

,,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 melnvers o( L: Pun tero);
begin
if L <> nil then
begin
I mprimelnver so( L A. 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: p trpila;
P : Puntero;
begin
Pcrear (Pila) ;
P : = L;
while P <> nil do
begin
Pmeter( P, Pila) ;
P := P A.S g 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 o du cto(X , Y: l o ngi n t): l o n g int;


begin
if X >= 1 than
if (X mod 2) <> o then { Es impar }
Pro duct o := Y + Prod uc t o( X div 2 , Y * 2)
elee
Pro du cto : = Pr o du c t o(X div 2 , Y * 2)
alee
Producto .. - O
end;

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
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 a B e

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: inte ger ; A, B, C : cha r);


procedure Movimiento(N: integer; A, C : cha r);
begin
writeln( 'M ove r disco I ,N, I de I ,A, I a I/e)
end;
Recursividad: algoritmos recursivos 269

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) ;
Torres H(N - 1, B , A, C)
end
end;

9.3.2. Traza de un segmento


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
eoo r d = record
X : r eal ;
y : rea l
end;
var
O, F : Coo rd;
procedure Dib_sgmto(O, F: eoord) ;
var
M: eoo r 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_ sg mt o(O , M) ;
if WhereX > 7 0 then
Goto XY( S , Wh e re Y + 1 ) ;
wr i t e (I X : 3 : 1, , , , Y : 3 : 1, ' )
( I , I 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 N me ro de di s co s .
A
B
Vari ll a A
Var il l a B
e va ri l la e
Para cada uno de ellos se define una pila:
Pil aN
P i l aA
Pi l a B
p i lae
Adems la pila de direcciones: Pi 1 aD i r
Torre _ Ha noi(N, A , B, el
Crear pilas: Pi laN, Pil aA , Pi l a B , Pi l a e , P i la Di 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)
Sa c ar ( A, PilaA )
Sacar(B, PilaB)
Sacar ( C, PilaC)
Sa c 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 ila N) 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, P i l a in t ;

procedure Ha n o i t e r (N : i nteg er ; A, B , C : c h a r ) ;
var
Pil a A , P il a B , p ilaC : Pil a c ha r . Pt rPil a ;
Pi laN , P i l aD : P ilaint . PtrPi la ;
Paso : in t eger;
T : c ha r ;
begin
P i lachar .Pc re a r( P i laA ) ;
P ila cha r . Pcr ear (P i l a B ) ;
P ilachar . Pcrear (PilaC) ;
P il a i n t . Pcrea r (Pi laN) ;
p il ain t . Pc rear ( Pi l aD ) ;
P i laint . Pm e t e r( l,P il aD ) ;
while not P i l aint . Pv acia (PilaD) do
i f (N = 1 ) then
begin
Mov e r di sco(N ,A , C) ;
P i la int . P s a car (P as o , pi l aD) ;
if not P i lain t . Pva c i a(P il aD) then
begin
Pi la cha r . P saca r(A, pilaA) ;
Pi la cha r . P sac a r (B, pilaB) ;
P i la c h a r . Ps ac ar(C , PilaC) ;
P il a i n t . Psaca r ( N ,P il aN)
end
end
else begin
P i l aint. P saca r(Pas o , Pil aD ) ;
Case Pas o of
1 : begin
Pila char . Pme t er ( A,Pi laA) ;
P i l a c h a r . Pmeter (B ,P ilaB ) ;
Pi l ach a r . Pm eter IC , PilaC) ;
P ilai nt . Pmet e r(N, Pi l a N) ;
P il a i nt . Pmete r (2, P il aD ) ; {Pa so ac tual }
P i 1 a i n t . Pme 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) ;
{No e s n e c esario alm ac ena r los argum e n to s A, B, C , N p ue s no
se utilizan }
Pi l a i n t . Pmet er (1, Pi l aD) ;
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: in te g er
end;
Ptr P i l a = AI te mp;
I te mp = record
I nf o : Ele me n t o ;
Sgte : PtrP il a
end;

El procedimiento Ha n o i ter 2 :

procedure Ha n oi ter2( N : in tege r; A , B, e : eha r) ;


var
P il a : P trPil a ;
T : Ele mento;
procedure Est a d o( var S t : E lemen to ; A,B , e : eha r; N,O : in t 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 ) ;
E s ta d o(T , A , B, e , N, l J ;
Pmeter (T, P i l a ) ;
while not Pva e i a (P i la) do
with T do
begin
Psa ear ( T, P i l a );
if (Nd = 1 ) then
Mo ver _ d i seo( Nd , Pa , Pe)
else
Recursividad: algoritmos recursivos 275

case Dir of
1: begin
Dir := 2;
Pmeter (T, Pila ); {Estado actual}
Estado(T,Pa,Pc,Pb,Nd-l,l) ;
Pmeter(T,Pila) ;
end;
2: begin
Mover_disco (Nd, Pa, Pc);
Estado(T,Pb,Pa,Pc,Nd-l,l) ;
Pmeter(T,pila) ;
end
end
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 P il aint , Pilachar, Pilastat , crt, printer ;
const
Maxnumdiscos = 15;
var
N: integer;
A,B,C: char;

procedure mover_d isco (N: in t 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
,I
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) ;
. ..... _._------------------

276 Estructura de datos

Pi l aint .Pcrear(PilaN} ;
P i 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,P i 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} ;
N := N- 1;
T := B; B : = e ; e := T
end;
2 : begin
Mover_disco(N,A , e} ;
Pilain t . Pmeter(l,Pila D} ;
N := N- 1;
T := B; B := A; A : = T
end
end
end
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) ;
Recursividad: algoritmos recursivos 2n

Est ado (T,A,B, C ,N,l) ;


Pmet e r (T, P i l a) ;
while not Pvac i a(Pi la ) do
with T do
begin
Psaca r (T , Pi l a) ;
if (Nd = 1) then
Mo ver_di sco (Nd , Pa, Pc)
else
Case Dir of
1: begin
Dir : = 2 ;
Pmeter (T , P ila ) ; { Est ado actual}
Est ado( T,Pa,Pc, Pb ,Nd- l,l) ;
Pm eter(T , P ila) ;
end;
2 : begin
Move r_d i sco(Nd, Pa , Pc );
Estado( T, Pb , Pa , Pc , Nd-l , l) ;
Pmeter( T, P ila) ;
end
end
end
end;
begin
clrscr ;
A:= 'A';
B . - 'B",
.-
C - 'C",
wr i t e( 'Numero d e discos? : ' ) ;
repeat
read ln ( N)
until N in (l .. Maxnumdi scos ];
cl r scr ;
I wr i te l n(Lst , ' Soluc i n recursiva con ' ,N , ' d i scos ' ) ;
mover_t o rr e (N, A,B ,C ) ;
wri teln(L s t ) ;
writ e ln ( Ls t , ' So l uc i n it e rativ al con ', N, ' di s co s' ) ;
I Ha no it e rl(N,A,B, C) ;
wr i teln;
writeln(L s t , ' So l uc in i terativ a2 con ', N,' di scos ' ) ;
Ha n o 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
Seleccio nar n uevo movimiento del caballo
si (Est e n tablero) y (No pas ya) entonces
An ota r movi mi e n to e n e l table ro
si (No comp l etado t able ro) entonces
Nuevo ensay o : Caballo
{Vuelta de l l ama d a recurs i va }
si (No se a l can z so lu cin) entonces

Borrar anotac~ o n ante r~or
fin_si
fin si
fin si
hasta (Completa do 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
Tab l 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
Tab l er o = array [ l .. N, 1 .. N ) of integer ;
Coord = array[1. . 2 , 1. .8 ) of i nteger ;
var
T: Tab l ero ;
H : Coord;
r , J : intege r;
S : boolea n;
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 ln [ 1 .. N]) then
if T[Nx, Ny] = O then
begin
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] -- 1;
H[1,2] -- 1 ,. H[2,2] -- 2;
H[1,3] -- -1,, H[2,3] -- 2 ,.
H[1,4] -- ~ 2 ; H[2,4] -- 1 ,.
H[1,5] - - 2 ; H[2,5] -- -1;
H[1,6] -- -1 ; H[2,6] -- -2;
H[1,7] -- 1 ; H[2,7] -- -2;
H[1,8] -- 2 ; H[2,8] -- -1;
for I -- 1 to N do
for J -- 1 to N do
T[I,J] .. -- O ;
{El caballo parte de la casilla (l,l)}
T[l,l] -- 1 ;
Caballo(2,1,1,S) ;
if S then
for I := 1 to N do
begin
for J := 1 to N do
wr i t e (T [ I , J] : 4 ) ;
writeln
end
el se
writeln('NO SE ALCANZA SOLUCION')
end.
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
Se lec cio nar nuevo paso hacia l a soluci n
si vl id o entonces
Anotar el paso
si no completada solucin entonces
EnsayarSolu c in a partir del nuev o paso
si no alcanza solucin completa entonces
.
borrar anotac~on
,

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 resolve~.

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
I 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;
Ii interface
const
I
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 : = Pila A.I nfo ;
Pila := Pila A. 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, P i l aC ;
type
I ncr e mentos - array [1 .. 8 ] of integer;
Tabla = array [ind ice, i n d i ce] of intege r ;
var
Cp : Ptrp ila;
R : Tipoelem;
Xn, Xp , Yn , Yp : integer; {c oo rde n adas cas il las}
Fila, Co l u mna: I ndice;
Rl : set of Indice ;
In c X,
I n c Y: I n c remen t o s ; {Des pla za mie n tos relativos }
Ta b lero : Tabla;
So luciones, Salto, Nu mMo v : i n t eger ;
Recorrido , Colo cado : 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
Nu mmo 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.numm ov : 4 , in f o . sa l to : 2, i n fo . x:2, '-', i n Eo . y) ;
end
end;

procedure Iniciartable r o (var Tab l ero : Tabla);


var
Fila, Columna : Indi c e;


284 Estructura de datos

begin
for Fila := 1 to N do
for Columna := 1 to N do
Tablero[Fila, Columna] ..-
- O
end;

procedure Incre(var Incx, Incy: Incrementos);


begin {Desplazamientos relativos para desde una posicin dada dar ,

,
un salto de caballo} ,,
e,,
IncX[1] := 2; IncY[1] := 1;
IncX[2] := 1; IncY[2] := 2; ,
I
IncX[3] := -1; IncY[3] := 2; ,
IncX[4] -- -2; IncY[4] -- 1; ,
IncX[5] -- -2; IncY[5] -- -1; ,I
1
IncX[6] - -1; IncY[6] -- -2;
IncX[7] --
IncX[8] -
1 ; IncY[7] -- -2;
2 ; IncY[8] - -1;
I
end;
l
procedure Escribetablero(var Tablero :Tabla);
var
Fila, Columna: Indice;

begin
for Columna := N downto 1 do
begin
for Fila := 1 to N do
write (Tablero [Fila, Columna]: 5) ;
writeln
end;
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 J
;
begin ,
if Recorrido then j

begin
Pcima (Cp, R);
with R do
Tablero[X,Y] := O;
Salto := R.Salto;
Pborrar (Cp) ;

,
1
Recursividad: algoritmos recursivos 285

" Vu e lta atrs " tl asta l legar a u n a casi~la des de la q lle rl o


se ago ta r o n todos los saltos y asi pode r encont r ar otra
. "
s o 1.UC lon
while ( Salto = 81 and not Pvaci a(Cpl do
begin
Pcim a ( Cp , R I;
with R do
Tab ler o [X , Y] .. -- () ,,
Pbo, rar (Cpl ;
NUTIIInOV : ~ N\;nmov 1;
if not Pvacia(Cpl then
begin
Pcima(Cp, RI ;
SalLo : = R. . Salto
end
end
if not pvacia(Cp l then
begin
T abl ero [R , X, R , V j := O; {D es ha ce a n te rior para b squ e d a
d e otra SC)l tl(::i!" .\
.

Numm e)v : = R . N\lIT\m OV 1;


Pborrar (Cpl ;
Recorrido : = false
end
end
else S alt o .. .. o;

if not pvaci a(C p ) then


begin
Co lo cado : = f a l se ;
Pc imalCp, RI ; (P ara dar
repeat
Salto : = Salto-1 ;
Xn :~ R . X + In c x lSalto );
'In := R . Y + Incy[Salto] ;
if ( Xn in R: ) and ('In in Rl ) then
Colocad o : = Tab'ero ' Xn , Vn 1 -- O,
until co~o cado or (Salto = 8) ;
if Co l oc a do then {Anota movim ien to}
begin
Nummov : ~ N um n~ov ~ 1.. ,.
Table r o ( Xn , Y r; ] : -- Nu m~ o v ;
Ll:...no tar( R , Nurn~nov , Sa lto , Xn, Yn ) ;
Pme ter I Cp, R) ;
if Numm ov = N * N then ( ru:a com pl etada!
begin
Re corrido - = t- r "'"" p'_1-
l.

SOlll Cio !leS : = Sol;Jc: iones + 1 ;


wri teln ( ' SOLUCION ': 4 ,1, Sol uciones) ;
:';s cribeLab~ero (;'<'lbJ ero ) ;

end
end
else (N o p~d o coloca ~ s n Num~ov+l a partir de N,l mmC)V \
while not Colocado and not ? vaci a ( Cp ) do
286 Estructura de datos

begin {M arc h a at rs : e s sacado el movimien t o anter i or


par a nu ev a " pr u eba " con otro sal to}
Pcima(Cp , R ) ;
with R do
Tab l ero [ X, Y] : = O;
Sa l to : = R . Salto ; {Es el l t i mo Sa lto)
Pbo rrar (Cp) ;
if not Pv a ci a(Cp ) then
begin
Pcima(Cp , R);
with R do
begin
Xp : = X;
Yp : = Y
end;
while (S a lto < 8) and not Colo ca do do
begin
Salto : = Salto + 1;
Xn := xp + Incx[Salto] ;
Yn : = Yp + I nc y [ Salt o];
if (Xn in Rl) and (Y n in Rl ) then
if Tab l e r o [ Xn , Yn ] = O then
begin
Co lo ca do := true ;
Nummov := R . Nu mmov + 1;
Tab l er o[ Xn, Yn ] : =Nu mmo v;
Ano t ar( R , Nummo v, 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 oca do )
end { f in de if not Pva ci a }
end; (fi n del mien t 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 ; { N mer o d e r ei n a 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 o n: b oo l ean ;
1: in t eger ;

procedure Co l ocar _ Reinas (r : i n te g er ; v a r S : b o olea n ) ;


var
K: i nteger ;
function Va li do(J : integer) : bool e an ;

{ In spec ci o n a s i la r e i na d e la co l um n a J e s atacada por a l guna relna
colocada anteriorme n te}
var
R : in t eger ;
V : boo l ean ;
begin
V : = true ;
for R : = 1 to J-l do
begin
V : = V and (Reinas[R] <> Rein a s[J]) ;
{No es t . e n la mi s ma f il a }
{No est en alguna de las dos diago n a l es : }
V : = V and ((Re i nas [J ] + J) <> (Reinas [R] + R)) ;
V := V and ((Rei n as[J] - J) < > ( Re i na s [R ] - R))
end;
Val i do := V
288 Estructura de datos

end;
begin
K : = (J ; {In ici.a liza r pos ibl es mo vim ient o s}
repeat
K : ~K + l ;

S : .:. : t illse ;

Reinus [I] {T enta tiv a d e co l ocar re l na 1 en ti l a K,
: = K; a l u ve z
q uelia a n otado m ovi~i e n t o)
if Val ido(I ) then
if T < 8 then 18 Pllede su!;ti tuir se por NI
begin {No comp let ad o e l p roble ma}
Co lo caI' _ Re ina s(I + 1, S I ;
if not S then ( Vuelta atr s)
Reinas[I] : = (J
end
else (L as 8 rein as c ol oc a das )
S : = true
until S or (K = 8)
end;

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 P i la R ;
interface
c on st

N = 8;
type
Rang o l .. N ;
7

P tr Pila = AN odo ;
Nodo = record
NI' , Co l: word ;
sg te : Pt r Pila
end
procedure PcI' e ar (var Pila : P trPi l a) ;
function Pva cia ( P ila : Plr P il a) : bool ea n ;
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) := false;
Ddch[Nr + Co) : = fal se;
Dizq[Nr - Col : = false
end;

begin
ClrScr;
write( 'Intr oduzca dimensin del tablero: ');
repeat

L
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] : = tr ue ;
for i : = 1 - Nf to Nf - 1 do Dizq [ i l : = t rue ;
Pcre a r(Cp) ; Nr := O; Co l : = O;
Pm e t er (C p, Nr , Col ) ;
while (Nr < Nf) and not Pvac i a(C p) do
begin
Nr : = Nr + 1 ; Colo cado : = fals e ;
while not Co locado and (C ol < Nf ) do
begin
Co l := Col + 1 ;
if Co libr e[Col] then
if Ddch[Nr + Col] then
if Diz q[ Nr - Co l] then
begin
Ocupa r (Co l ibr e , Ddc h, Di zq , Nr , Col) ;
Colocado : = t rue;
Pm e t e r (C p , Nr , Co l );
CA l := O
end
end;
if not Col oca d o then
begin
if Cp A. Nr < > O then
begin
Lib e rar(C olib re , 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 ('N O ENCU ENTRO S OLUCION')
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.
-

Recursividad: algoritmos recursivos 291

const
N = ... { m ximo de pesos prev i s t o }
type
Vector = array [ l . . N] of in t ege r;
var
Peso s: Ve ctor;

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 = . . . , {mx im o de pesos previsto }
type
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 : in teger ; {Obje tivo}
{V : Es el objet i vo }
{Candidato : I nd i ce de l peso a aa dir }
{Cuenta : Sum a parc i a l de pesos }

procedure Moc hi la(V : i n teger ; Ca n didato : i n teger;


Cu e n ta: i n teger ; var S : boo l ea n );
begin
if Cuenta = V then
S := t rue
el se if (C uenta < V) and (Candidato <= N) then
begin
{Es a n o tado el objeto Can didat o y sigue l a b squeda}
Bo l sa : = Bolsa + [Ca n d i dato] ;
Mochi l a(V , Ca ndidato + 1, Cuenta + Pe sos[Cand i dato] , S) ;
if not S then {Es excluido Cand i dato , para s egu i r
ta nt ea n do co n si g ui e n te }
begin
Bo l sa : = Bolsa - [ Candida t o ];
Mochila(V , Ca nd idato + 1 , Cue n 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 ch i l a (V : in tege r; Ca ndi dat o: int ege r; Cu enta : in te ger;
var s : boo l ea n ) ;
var
Pc an d i , P s tat : Pi l i nt ;
Pcuent : P i lreal;
St, C: i n t eger ;
Pso : real ;
begin
S : = f a l se;
Pcr e ar(Pc a ndi) ;
P i la real .P c r ea r (Pcue nt ) ;
Pcrear(Ps t at) ;
Pmeter(O, Pstat) ; {Es as i gnado e l estado inicial}
repeat
if Cue n ta = V then
S : = true
el se if (C uent a < V) and (Ca nd i d at o <= N ) then
begin
{Es ano t ado e l obje t o Cand i dato y sigue l a b squeda}
Bols a : = Bo lsa + [ Can d id a t o ];
Cuenta := Cue n ta + Pesos [Cand i dato] ;
P i l area l. Pmeter(Cue n ta , Peue nt ) ;
Candi d ato := Candi dato + 1;
Pmet er (1 , Pstat) ;
end
el se if (Cuenta> V) and (Cima (Pstat) = O) or
(Cand idato > N) then
Recursividad: algoritmos recursivos 293

begin
Ca n dida t o : = Ca n d i dato - 1;
Pborrar( Pstat ) ;
end
else if Cim a (Pstat) = 1 then
begin {Se ex cluye al c andidato y se vuelve a prob a r}
Bols a : = Bol sa - [Candidato ];
P i la real. Ps a car (Cuenta , Pcu e n t);
Ca ndidato := Ca ndidat o + 1;
Pborr ar (Pstat) ;
Pmeter(2, Pstat)
end
el se if C im a (Pstat) = 2 then
begin
Candi dato : = Ca n d idat o - 1 ;
Pborrar( P stat )
end
until Pv a c ia (Ps t at) or S
end;

{Al h abe r dos unid ad es de p i las las refer e n cias a l as r utinas d e l a


unidad P il a real las cual ifi c amos co n 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 ; { tama o 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 rin t o = array[ Lat i tud , Lo n 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 ab e r ( AO , L O, Ex ito) ;
if Ex i t o then
Ve rlab(L)
else
writeln ( , HorrOr n o sa limos del laber in to !!' )
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 Generadorp erm u t a eio n 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 x grado ;
var
A : array [ Apu n tador ] of Apu ntado r;
N : integ er;
X : e har;
procedure proee sopermu t 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 permu ta( K,N: Apu n tado r ) ; .\



,

,

j
Recursividad: algoritmos recursivos 297

var
p : Apuntador ;
begin
P .. -- O ,.
repeat
A[K ] :=A[pJ;
A[p] .'-K'- ,
if K = N then
procesopermuta c i o n
else

pe r muta(K+1.N) ;
{Ah ora se " co l o ca" en la a n t eri o r , rep r esentad o por A [K ] )
A [ p] : =A [ K] ;
p : = A [ p];
until p = O;
write l n ;
end;

begin
c lr scr ;
repeat
write( 'N u mero de e l eme n t o s a permutar:') ;re ad ln(N);
until N in [l .. Maxgr a d o] ;
write l n( 'Permut aci o n 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 solu cion then


if mej o r ( s o luc i on) then
o pti mo :=soluc io n

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(inpu t , ou tput);
uses crt;
const
N = 10 ;
type
Indice - 1 .. N;
Objet o - Record
va l: i nteger;
pso : integ er
end;
Li sta = array [Indicel of Objeto ;
Conj = set of Indice;
var
A: Lista;
Psomx, Tpeso,
Tvalor, Mva lor ,
T, K: intege r ;
Ac t, Opt o Conj ;

procedure Obj etos(va r 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
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
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 ;
{VaE x es e l va l or mx i mo q u e pod r a alca n za r la se l ecc i n ac t ua l)
if VaEx > Mvalor then
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 ensaya n do ya que no va a
s u p er ar e l va l o r pt im o act u a l : Mval o r}
end;

begin
c l rscr ;
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 ('v al 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 varian d o d esde el mni mo , h as t a al canzar e l
mx i mo o 10 pruebas , cada prueba au menta e l peso e n 3 un i dades}
T := Min (A) ; Psomx : = T ;
repeat
Ac t := [ ]; Op t : = [ 1;
Mvalor : = O;
Maleta (l, O,T va l or , Mvalor ) ;
so lu c ion (Opt,Psomx , Mvalo r ) ;
Psom x := Psomx+3
until (Psomx > Tpeso) or (Pso mx > T+I0 * 3)
end.

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.
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 : T ipo Homb r e)


var
R: en t e ro
inicio
Desde R r 1 hasta n hacer
<To ma r pre f ere n c i a R-s ima de homb r e H>
si acept ab le entonces
<Anot ar matri mon io >
si <H no es el l timo hombre> entonces
En sayar(H +l)
sino
<El co njunt o d e mat rim onios 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 = ... ; {N me ro de pa rej as}
ty pe
T ipohombre = 1 .. N;
Tipomuje r = 1 .. N;
Pr efhombre s = array [Tipoh o mbre , 1 .. NJ of T ipomujer;
Pr ef muje re s = array [Ti pomu j er, l .. NJ of Ti pohombr e ;
Par h o mbres= array [Tipohombre J of Ti po mu j e r;

,
1
302 Estructura de datos

Par muje r es = array [ Ti p omu j eres ] of Ti po h o mbre;


var
Phb: Pre fh o mbr es ;
Pmj : Pr e f mujeres ;
V : Parho mb re s ;
F: Pa r 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;

Solter a [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 : T i poHombre)


var
R : e n tero ;
M: Tipomu je r;
inicio
Desde R r 1 hasta N hacer
M r Phb [H, R] {Mujer candidata }
si Soltera[M] y <Estab l e> entonces
V [H ] r M
F[ M ] r H
So l te r a [M ] r False
si H < N entonces
Ensay ar(H+ l)
sino
<A n o t a r, co njunt o ya es es t ab l e>
fin_si
Solter a [ 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 [ Tipohomb r e ,Ti pomu j er] of 1 .. N ;


Rmh : array [Tipomuje r, 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 YRmh [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 u al 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 ~ Rm h[M,H ]
mientras (1 < Tope) y Estab le hacer
Hh ~ P m j [M ,I]
1 ~ 1 +1
si Hh < H entonces { Hh ya tiene par eja }
Est able ~ Rhm [ Hh, M] > Rhm[ Hh , V[H h]] {Es table s i Hh pr efi ere }
fin si { 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; {Nmer o de parejas a formar}
type
Tipohombre = 1 .. N;
Tipomujer = 1 .. N;
Prefhombres = array [Tipohombre, 1 .. Nl of Tipo mu je r;
prefmujeres = array [Tip o muje r , 1 .. Nl of Tipohombre;
Parhombres = array [Tipohombrel of Tip omujer;

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: Tip o hombre;
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:Tipo mujer;R:integer) :bo o 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;
Recursividad: algoritmos recursivos 305

if not Sol t er a[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}
I for R := 1 to N do
begin
M := Phb [ H, R];
if So ltera [Ml and Es table( H, M, R) then
begin
, V[H) "" -- M",
F [ M) "" -- H",
SOltera [M) := false;
if H < N then
Ensayar (H + 1)
else {Encontrada una asignaci n estable }
Escrib i r ;
Soltera [M) : = true
end
end
end;
begin (bloque principal)
clr scr ;
(Entrada de rango de preferencias de hombres)
for H := 1 to N do
begin
writeln('Preferen c ias de hombre', H,' segn ran go 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 ra ngo de preferencias de mujeres)
for M : = 1 to N do
begin
wr i te ln('Pr efe ren cias de mujer', M, ' seg n rang o de 1 a " N) ;
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.
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:

1 si x ~ y
G(x, y) =
G(x-y+I)+l 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: cha r;
begin
r e ad (e) ;
if eo ln then
Rev e s := ' * '
el Be
Rev e 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 Desco n ocido(N , Despl : i ntege r ) ;


var
K : inte ge r;
begin
if N > O then
begin
Des c onocido( N- l , Des pl +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, Des p 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 si m = O
A(m,n) = A(m-l,l) si n = O
A(m,n) = A(m-I,A(m,n-l 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 ~ 1

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:


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,

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
I
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.
-

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 Una secuencia de nodos conectados dentro de un rbol.


Longitud del camino Es el nmero de nodos menos uno (r - 1). Si r > 0, se dice que
el camino es propio.
I
Altura del rbol 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.
Nivel (profundidad) 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.
Grado (aridad) Es el nmero de hijos del nodo. La aridad de un rbol se defi-
ne como el mximo de la aridad de sus nodos.
Hermanos 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

Luis y Juana

Micaela Lucas Mara

Luis
(Carchelejo) Juana Mara

Luis
Graciela Victoria
(Madrid)

Figura 10.3. Arbol genealgico.


,,

10.2. RBOLES BINARIOS


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.

B B C B


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.

I
D Padre
,
,,
,,
I
,,
,
j,
,

Hijo izquierdo H J Hijo derecho

Figura 10.6. Padre e hijos de un rbol binario.


,

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

316 Estructura de datos

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

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.

I
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.

c_

(a) (b) (e)

Figura 10.10. rboles binarios con los mismos nodos pero alturas diferentes.
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 (TD ) ]


,
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.
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. '

, .

, .- - -
", '"
, ,.',,;', . 1
-_._.- -': '
. .:... _.- ,
:,. ::_---,--- -

.': .. :': ,". , .... .. . >

recorrido preorden recorrido enorden recorrido postorden


l. Visitar el raz l. Ir a subrbol izquierdo l. Ir a subrbol izquierdo l
,
2. Ir a subrbol izquierdo 2. Visitar el raz 2. Ir a subrbol derecho ,
1
",
3. Ir a subrbol derecho 3. Ir a subrbol derecho 3. Visitar el raz

,,

En el rbol de la Figura 10.14 los posibles recorridos pueden ser:
,
1

Recorrido preorden visita los nodos en el orden GDBACEFKHJIML. ,

I 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.

o K

B E H M

J
L
A e F


Figura 10.14. Arbol binario.

I
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 = ANod o Arbol

No doArb ol = record
Da to s:NombreTipo;
Izda, Dch a: PtrA rb o l; ( p unter os a hi j os )
end; (Nod o Ar b o 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

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 Nue v o lt e mP t r : P t r Arbo l ; Num : Nombre Ti po) ;


begin
ne w (NuevoltemPt r ) ;
Nuev o lte mP t rA .Da t os : = Num;
Nuevolt emPt rA . lzdo := n i l ,'
Nu evo lt emP trA . Dcho := n i l;
end {NuevaHoja}

function Es Hoja (unNodo : Pt rArbol) : boolean ;


begin
if unNod o = n i l then
Es Hoja : = fa l se ;
elBe
EsHo j a : =(unNo do A.lz do - n il ) and (unNo d 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:
I
l. Recorrer el subrbol izquierdo (1). !,
2. Visitar el nodo raz (N). 1


3. Recorrer el subrbol derecho (D).

El algoritmo correspondiente es

En o rden(A)

Si el ar b o l n o e st a v a c ~ o entonces
inicio
Recorrer el su ba r bol izqu ier d o
visitar el n odo raiz
Re corre r el subarbo l 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.
326 Estructura de datos

A
Visita de los nodos: D, S, E, A, F, e, G
4

S e
2 6

D E F G

1 3 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 n o es va c i o entonces
inicio
ver los dato s e n el r a iz de T
preorden (sub arbo l iz q uie rdo del rai z d e T)
preorden (sub ar b o l de re c ho del raiz d e T)
fin

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. Recorrer el subrbol izquierdo (1).

2. Recorrer el subrbol derecho (D).


3. Visitar el raz (N).
rboles binarios 327

A
Visita los nodos : A-B-D-E-C-F-G
1

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 n o es ta y ac io entonces

~n~c~o

Postorde n ( s ubarbol iz qu i e rdo del ra iz de A)


Posto rde n (suba r bol derecho d el raiz de A)
Vi sua l i zar l os dato s de l r a i z de A
fin

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
Visita los nodos D-E-B-F-G-C-A
7

B C

3 6

o E F G

1 2 4 5

Figura 10.21. Recorrido postorden de un rbol binario.


.."..... , ... _-------

328 Estructura de datos

EJEMPLO 10.3
Deducir los tres recorridos del rbol binario siguiente:

E z

A G p

Solucin
Preorden :MEAGZPQ (NID)
Enorden :AEGMPQZ ( IND)
Postorden :AGEQPZM ( IDN)

I 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:
I


const LongMax = 30 (longitud mxima del nombre)

type NombreTipo = string [LongMaxl ;

ptrTipo = ~nodoT ipo;

nod o Tipo - record


Nombre:nombreTipo;
Hijolzdo:ptrTipo; (puntero a Hijo izquierdo )
HijoDcho:ptrTipo (puntero a Hij o derech o )
end;
Tip oArbo lBin = ptrTipo;

var A : TipoArbolBin; ( puntero a raz del rbol)


rboles binarios 329

Por ejemplo el procedimiento EnOrden puede ser:


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

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 ()


Potencla

A

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:


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 ) ~ -AB~C+D ~ ~-ABC+D ~ +~-ABCD (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+ / (polaca inversa)
A*B / A+C (infija) ~ AB* /A+C ~ AB*A /+C AB*A/ C+ (polaca inversa)
(A-B) ~ C+D (infija) ~ AB - ~ C+D AB-C ~+D ~ AB-C~D+ (polaca inversa)

10.6.2. rbol de expresin


.
.

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:

.

+

I -
,
.
H
..
i
.
.
,
* *

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.

:.
!
..
!

.
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
Info: PtrA;
,,
Sgte: Plaptr
end;
,;,
~.

'O"
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 Crearnod o( 1z: PtrA; 1nf:char; Dr:PtrA; var A:PtrA);
begin
, new(A) ;
, AA.C ;= 1nf;
i i
AA.1zqdo ;= 1z;
AA.Drcho := Dr
endl
begin
Pcrear(P);
for 1:= 1 to J do
if not Ar[I] .Oprdor then
begin
Crearnodo(nil, Ar[1].C, nil, A3);

Pmeter(A3, P)
end
elBe begin
Psacar(A2, P);
I Psacar(Al, P);
Crearnodo(Al, Ar[1] .C, A2, A3);
Pmeter(A3, P)
end;
Psacar (A3, P); {Devuelv e el rbol con la expresin}

R:= A3
end;

10.6.5. Evaluacin de la exp