Estructura de Datos

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 66

Capltulo

flD5T[fl«rOil

»r»0ro5

OBJETIVOS
. Entender en qué consiste el proceso de abstracción.
. Describir la técnica de la abstracción de datos para el diseño de
estructuras de datos.
. Comprender qué es una estructura de datos.
. Entender el diseño de una estructura de datos a través de una
especificación lógica.
. Ubicar los niveles de abstracción al programar.
. Identificar los beneficios de utlltzar la abstracción de datos como
estrategia de trabajo en el desarrollo de software.
f,bstracción de datos

¿Qué es una abstracción?


i;. ::'
En términos simples, una absfracción es un proceso mental, mediante el
cual se extraen los rasgos esenciales de algo para representarlos por
medio de un lenguaje gráfico o escrito. Puesto que es un proceso
mental, la abstracción es una acción subjetiva y creativa, esto es, de-
O^:**^pende del contexto psicológico de la persona que la realiza.
','
,r Por ejemplo, se dice que algunas de las pinturas de Picasso son abs-
tractas, no porque sean difíciles de entender, sino porque a través de
, ciertos trazos simples, y de acuerdo con su criterio mental, el pintor
plasmó los rasgos esenciales de ese algo real que trataba de represen-
tar por medio de un lenguaje gráfico.
En la vida cotidiana, continuamente se hacen abstracciones, por
ejemplo cuando describimos a una persona: "Reconocerán al profe-
sor Garay por su enoÍne nariz, su barba y sus anteojos; además, es
muy alto, y tiene un carácter muy amigable". Cuando hacemos un
mapa para describir cómo se llega al rancho donde será el día de
campo, extraemos los rasgos importantes del camino: "Al llegar al
cruce donde está una piedra gigantesca, das vuelta a la derecha y verás
un ¡írbo1 lleno de flores rojas; ahí encontrarás la entrada al rancho."

¿Por qué es ¡mportante la abstracc¡ón?


Aunque la gente realiza cotidianamente el proceso de abstracción, debe
convertirse en una habilidad para quien estudie una carrera relaciona-
da con la computación. La capacidad de modelar una realidad por
medio de herramientas computacionales requiere necesariamente de
hacer continuas abstracciones, por 1o que es vital conocer metodologías
que desarrollen esta habilidad.

¿Qué es la abstracción de datos?

La abstracción de datos es una. técnica o metodología .que permite


diseñar estructuras de datos. Consiste, básicamente, er-t representar
bajo ciertos lineamientos de formato las caracteísticas esenciales de
una estructura de datos. Este proceso de diseño se olvida de los detalles
específicos de implementación de los datos, razón por la cual se trata
de una absffacción.
i[n que consiste la especificación légica de un TDfl?

¿Qué es una estructura de datos?


Cualquier colección o grupo de datos organizados de tal forma que ten-
gan asociados un conjunto de operaciones para poder manipularlos, se
dice que conforma una estructura de datos.
Por ejemplo, cualquier lenguaje de alto nivel provee trpicamente de
tipos de datos estructurados o estructuras de datos predefinidas, como
los arreglos o los registros. Un arregl.o es un conjunto de datos, todos
del mismo tipo, con una organización lineal y con métodos claros de
acceso a través de sus subíndices. Las operaciones tradicionales sobre
los arreglos incluyen la comparación, la asignación, la escritura, etc.
En un nivel rnás bajo, podría verse a los números enteros como estruc-
turas de datos: se componen de un grupo de dígitos y tienen asociadas
operaciones como sumar, restar y multiplicar, entre otras.

¿Qué es un Tipo de Dato Abstracto (TDA)?


La técnica de la abstracción de datos establece que al diseñar una
nueva estructura de datos, ésta pasa a ser un Tipo de Dato Abstracto
(TDA), que podrá implementarse en cualquier lenguaje y aplicarse en
cualquier concepto.
Por lo tanto, al usar la metodología de la abstracción de datos se
diseñariín TDA, siguiendo los lineamientos para hacer una especifica-
ción lógica o abstracta del mismo TDA.

¿En qué cons¡ste la espec¡ficación lógica de un TDA?

La especificación lógica de un TDA es un documento en el que se "O


plasma la abstracción realizada al diseñar una estructura de datos.
Dicho documento pasará a ser el mapa o plano mediante el cual se
construirá (implementará) la estructura de datos y en el que se defini-
rán claramente las reglas en las que podrá usarse (aplicarse) el TDA.
Aunque existe una fundamentación matemática para esta técnica,
no es el objetivo de este libro profundizar en ella, por 1o que se utilizará
el lenguaje natural para describir la especificación de un TDA.
El documento de la especificación lógica de un TDA consiste de los
siguientes cuatro puntos:
flbstracción de datos

estructura de datos'
1. Elementos que conformarán la
individuales que guar-
En este puná se describe el tipo de los datos
datálaestnrctura'Porejemplo'númeroserteros'caracteres'fechas'
etcétera'
registros con los datos de un empleado'

guardarán los-elementos'
2. Tipo de organización en que se
pala los datos en la
O-* -- Existen solamerrte cuatro ilpo. J" organizaaión
estructura,tacualdeberáteneralgunadelassiguientesorganizaciones:
.Lineal:Sihayunarelacióndeunoaunoentreloselementos.
los
una relación de uno a muchos entre
' Jerrúrquicá, éi nuy
elementos.
.Red:Sihayunarelacióndemuchosamuchosentreloselementos.
entre los elementos'
' Sin relacián: Sino hay relaciones
Lasrelacionesentreloselementossedan'porejemplo'cuandoexiste
esté antes o después que otro
algún motivo para que un elemento
(figura 1.1).

Estructuna Estructura
Estructuras
jer"ár"quica de red
lineales

"o e
e 8e
@

No hay relac¡Ón
Relación de muchos a muchos
Belación de uno a uno Belación de uno a vanlos

de datos'
Figura 'lf . Tipos de estructuras u organizaciones

de la es-
Este punto op"io"uf, y en é1 se describkála capacidad
",
tructura en cuanto al rango posible de
datos por guardar'

estructura'
4. Descripción de las operaciones de la
debe describirse con
cada operacion retailonada con la estructura
los siguientes Puntos:
. Nombre de la oPeración'
. Descripción breve de su utilidad'
. Datos de entrada a la oPeración'
Ejemplo

. Datos que genera como salida la operación.


' Precondición: condición que deberá cumplirse antes de utilizar
la
operación para que se realice sin problemas.
' Postcondición condición en que queda el rDA después de
ejecutar
la operación.

@ Ejemplo

-a
flbstracción de dalos

UTILIDAD: Sirve para verificar si una cadena está vacfa o no.r


ENTRADA: ,:. , Cadena§ que se vErificaxá., , i

SALIDA: VERDADERO si la cadena S no tiene caracteres,


FALSO en caso contrario.
PRECOI{DICIÓN: Ninguna
o POSTCONDICIÓN: Ninguna (pues la cadena S Ro se modifica). i
,

LLENA
UTILIDAD: .
§irve para yerificar si una caden¿ está llena o no,
ENTRffW' 'cadenaSqrte,správerificada',,, l'

SALIDA: VERDADERO si la cadena S contiene ya 80


caracteres, EALSO en caso contrario.

II.IVIERTE. ,

UTILIDAD: §irve para invertir eI ordeR de los caracteres en una


cadeü&, , ,

ENTRADA: Cadena § a la que se desea ipvertir eI orden de los


caracteres,
SALIDA: Cadena S modificada.
PRECONDICIéN:
POSTCONDICIÓN: La secuencia de caracteres en la cadéna S se '
invierte, de forrna que el primer carácter toma el
lugar del último, el segundo el del penríltimo y asf
sucesivárdente.

Definir claramente la especificación lóglcadel TDA facilita posterior-


mente la construcción y aplicación de la estructura de datos.

¿Guáles son los niveles de abstracción de datos?


Al aplicar la abstracción de datos se pueden definir tres niveles de
trabajo:

1. El nivel lógico o abstracto, que correspondería a la especificación


lógica del TDA que se describió anteriormente. En este nivel se define
abstractamente la estructura de datos y las operaciones relaciona-
das con ella. La descripción que se obtenga en este nivel debe ser
ioué es ra independencia de datos g er ocurtamiento
de información?

independiente defienguaje de programación


en el que se impremen-
tará o usará la estructura.
2' El nivel físico o de implementación.
En este nivel se decide el len-
guaje de programación en que se implem
entarára estructura, qué
tipos de datos ya. definidos servir¿ín para
representarta y, finalmente,
bajo estas consideraciones, se implernenta
como u, -áooto a cada
una de las operaciones del TDA. Este nivel
toma el diseño que se ha
realizado a niver lógico y, siguiendo ar pie
de la retra las especifica-
ciones de cada operación, construye la
Átructura qu. port".iormente
se usará en el nivel aplicación.
3' En el nivel aplicación o de uso el programador
usará el TDA para
resolver determinada aplicación. Ef uso
der rDA se limita a llamar
las operaciones sobre ra estructura que
se requiera siem-
pre de cumplir con las reglas de cada "ri¿ur¿o
operación especificadas en el
nivel lógico.

fe-es la independencia de datos y er ocurtamiento


información?

De 1o descrito en la sección se observa que ha¡r una indepen-


'/,/ dencia bien marcada entre ellnterior
nivel físico y el nivel de aplicación del
Il;t:,:: :11*áilos*" ;*;l;;.*i¿i*ro (tgura 1 2). Esto signi_
.
fic,1 eu3-uuien implementa el TDA no debe estar irnu.r"ri¿o";;?i;
aplicación que tendrá la estructura y quien
use la estructura no tiene
i porqué saber cómo se implementaron
sus operaciones.
f se dice qr" iu forma en que se almacenan
I ' *-'" "'"-'
L" "'tonces,
estructura es independiente de su apliá.i0,
los datos en lal
aqu" p*, usuario pro-
!;;;;;;;""e oculto cómo se implementaron las "r op.ru"iár"s*-**-o
11
TDA Esro, sin lugar a dudas, simplifica la
labor der usuario del
TDA, pues se olvida de detalles de programación
sólo del diseño r{sico del propio TDA.
rI b;;; *r;;
Aáicionalm.ni, .r imprementa_
dor del TDA, podrá hacer cambios o
mejoras a su implementación, res-
petando la especificación lógica y
sin afectar en lá más mínimo ras
aplicaci ones desarroll adas.
Bbstracción de datos

¿Gómo distinguir los niveles de abstracc¡ón?


.. .. , :

Una analogíapodríahacerse al comparar este proceso con el que se rea-


liza alconsffuir una casa (figura 1.2). Primero se trabaja en e1 nivel lógi-
co al pedirle a un arquitecto que diseñe el plano; el arquitecto hace una
3-*-.-abstracción y plasma en el papel los rasgos principales de la casa Por'*-"**:^"*-****-
construir. Además, especifica claramente medidas y condiciones de cons-
trucción y de uso. Una vez aprobado el diseño, se procede en el nivel
físico, que cofrespondería a la construcción. Los albañiles seguirán
paso a paso tras especificaciones dadas en el plano (diseño en nivel lógi-
co) y no tienen por que preguntar para qué se utilizará cada uno de los
espacios construidos. Además , atilizarán el material más apropiado
para cada sitr¡ación. Una vez que la constr-ucción esté terminada, lle-
gará su dueño para habitarla, dándole el uso correspondiente a cada
espacio (nivel aplicación). El dueño, alutllizat la casa, no necesita sa-
ber cómo se hizo, con qué materiales o quiénes la construyeron; sin
embargo, le será útil conocer alguhas medidas o condiciones de
construcción que se representan en el plano (nivel lógico).

Figura 1.2. Relación entre los niveles de abstracción.

De Ia misma forma, cuando se desea aplicar la abstracción de datos


en el desarrollo de software que requiere de una estructura de datos, se
debe comenzaf con el diseño a nivellógico del TDA, continuar con su
implementación y finalmente con su uso en el desarrollo de la aplicación
correspondiente. En este proceso podrán intervenir tres personas: el di-
señador del TDA, un programador a nivel físico y un programador a
nivel aplicación. Cuando el mismo programador trabaje en los niveles
Ejemplo

físico y de aplicación, debe tener en cuenta la regla de no invadir los ni-


veles, respetando el nivel lógico que es intermediario.

¿Qué venta¡as ofrece utilizar la técnica de abstracción


de datos?
Seguir la regla de los tres niveles de abstracción redunda en un mejor
desarrollo de software. La técnica obliga a diseñar modularmente y,
como consecuencia, se tiene una implementación más clara, documen-
taday es fácil darle mantenimiento. Adicionalmente, gracias a la inde-
pendencia de datos y al ocultamiento de información, se pueden crear
paquetes como unidades de software reutilizable, con lo que se obtienen
estructuras de datos genéricas.
Quien atlriza un TDA se limita a llamar las operaciones, cuidando
solamente de cumplir con las especificaciones del diseño lógico, lo
que facilita y hace más rápido el desarrollo de aplicaciones, pues no es
necesario manejar los detalles físicos de la estructura.
La abstraccién de datos es uno de los principios que fundameitan
la programación orientada a objetos, y se describirá en el siguiente
capítulo.

.//,*^
66k
§@
Ejemplo

En cierta aplicación científica se requiere calcular el factorial de un


número entero positivo. La función factorial aplicada sobre un núme-
ro es la multiplicación de todos los números, desde el t hasta el valor
del númerocorreSpondiente(n! = 1 *2*3 (n-l) *n ).

Solución obvia en C++:

int l;
factorial =
for(intj-n;j>0;.i--)
factorial = factorial x ji
Sin embargo, es importante notar que:

. El factorial de un número crece en forma exponencial:


l! = 1,2! = 2, 3! = 6,4! = 24, 5! = 120, 6l = 720,7! = 5040, B! = 40320...
ñbstracción de datos

. La capacidad de los tipos de dato enteros en C++ está limitada.

El tipo unsigned long, en cuatro bytes, soporta como valor miíximo


4,294,967 ,295 lo cual permitiría obtener sólo hasta el factorial de L2.

Por 1o tanto, se requiere de un tipo de dato con una capacidad para al-
macenar a cualquier número entero, sin importar qué tan grande sea;
o" ya que C++ no provee de un tipo estándar paru este caso, se puede di-
señar un TDA para lutllizar números enteros grandes, el cual a su vez
será una estructura de datos.

Diseño del TDA numerote (nivel lógico)

llt,can'tt$4d de dfgitwib jo,cudqrderio.umhir,raoidr.'-§iá'e.ebqrgE;'se;


puede limitar a una capacidad m¿{xima de mil dígitos.
- Operaciones: las mismas qué posee el tipo de dafo entero.
EJercicios

Con base en este diseño lógico, se puede pasar a la implementación del


TDA (nivel físico) para posteriormente utilizarlo (nivel de aplicación)
y resolver el problema factorial eficientemente.
Este ejemplo será retomado en el siguiente capítulo para analizar
los niveles físico y de aplicación.

GONCLUSIONES
En la evolución del desarollo de software, se han descubierto una gran
cantidad de estructuras de datos, con propósitos firmes y claros, que no
pierden actualidad y forman parte de las bases para cualquier futuro
desarrollador de software. El propósito de este material, es mostrar ca-
da una de estas estructuras en sus tres niveles de abstracción, por lo que
los capítulos posteriores, se vuelven el mejor ejemplo de las ideas mos-
tradas en este capítulo. Deben ser de especial interés los capítulos de
strings, pilas y filas.
Sin embargo, la metodología aquí presentada puede ser utilizada
para ef diseño de nuevas estructuras de acuerdo con las necesidades de
aplicaciones y ajustando el punto de referencia de los niveles de abs-
tracción. Además, la comprensión de estas ideas facilitaú el entendi-
miento de la filosofía de la programación orientada a objetos.

EJEBCICIOS

1. Defina los siguientes conceptos:

* Abstracción
x Abstracción de datos
* Especificación lógica
x Nivel de abstracción
* Independencia de niveles
x Precondición
x Postcondición
x Módulo
x Abstracción modular
flbstracción de datos

2. Describa situaciones de la vida cotidiana en las que se realicen abs-


traccrones.

a
J. Recuerde cómo comprendió el concepto de una matriz (arreglo bi-
dimensional) en un lenguaje de programación. Si se considera la
matizcomo un TDA, defina su especificación lógica y comente las
o**- característicasdesunive1físicoya1gunasdesusposiblesap1ica--
ciones.

4. Explique cómo es que un registro en Pascal (o struct en c), cumple


aorr l*, caracteísticas de una estructura de datos'

5. El tipo de dato string, puede vetse como un tipo de dato abstracto


(TDA), para el cual pudiéramos diseñaf su especificación lógica.
sin embargo, el propio lenguaje c o c++, provee este tipo de dato
a través de las bibliotecas string;h y/o cstring.h'

a) ¿Cuál es la principal diferencia entre el manejo de los süings como


objetos y el manejo de los strings como arreglos? Explique breve-
ji,
mente las diferencias e indique en qué nivel de abstracción se
encuentran esas diferencias. Justifique su respuesta'
b) Las siguientes ffes operaciones tÍpicas se pueden realtzar sobre un
TDA string:

Copiar un string en otro (o asignar un string a otro)'


Concatenar o unir dos strings'
comparar dos strings verificando si son iguales o diferentes.

. Describa cada operación bajo el formato de 1a especificación ló-


gica de una operación, según el funcionamiento de las funciones
predefinidas que provee el lenguaje para los strings como Íure-
glos. Indique, además, el nombre de la función.
. Analice si las funciones predefinidas en el lenguaje, correspon-
dientes a estas operaciones para los strings como objetos, tienen
alguna diferencia con respecto a }a especificación lógica que
obtuvo en el punto anterior. En caso de que haya alguna dife-
rencia, explíquela indicando claramente en qué operación y cuál es
el cambio en la especificación lógica. Indique, además, cuál es el
nombre de la función (método).
c) A continuación se muestran tres secciones de código en lenguaje
c++, que al ejecutarse realizan exactamente la misma función:
eutoeualuación

' Identifique cuál es ra función que se está rearizando con estos códigos.
. Clasifique los códigos de mayor a menor abstracción.
' Identifique en qué niver de abstracción se
está trabajando en cada
uno de los códigos.

6. Diseñe las operaciones aritméticas y relacionales


merote descrito en este capítulo.
para el rDA nu-

i-----

RUToEURLURc I óN q ?
f ¡r¡E-r
-___¡r-r__-___-___-E_ ___.!

verdadero o falso
...Conteste:
-"***o
l' La abstracción de datos es una metodologíaparadiseñar
sistemas
computacionales.

2' La especificación lógica de un TDA determina


qué tipo de herra_
mientas de un renguaje computacional
se utlrizaranp*á i*pt"rn"r-
tar el TDA

3' si una operación de un TDAno tiene precondiciones,


significa
que quien use la operación en el niver
de aplicación no ándrá que
preocuparse por hacer validaciones
especiales, antes de Iamar a la
operación, para que ésta funcione correctamente.
Rbstracción de datos

4. Lapostcondición en la definición lógica de una operación de un


TDA, le dará información a quien la implementa en el nivel físi-
co de 1o qge debe codificar.

5. La implementación de un TDA puede mo{ificSrse sinafectar los


programas de aplicación que ya se hayan irnplementado'-
o---*-"

:
i

T
il
I
{
+
:i
I
:
;l
il

t -L
I
Capltulo
I

DIOQflIIflrcil
OilIIIIflDfl fl ODJTIOS

OBJETIVOS

'Entender los principios básicos de ra programación orientada a


objetos.
' Repasar y comprender la terminología de ra programación orientada
a objetos: objeto, clase, mensaje, método, here-ncia, polimorfismo,
encapsulamiento.
'Identificar las ventajas y desventajas de la programación orientada
a objetos.
'Relacionar los conceptos de ra abstracción de datos con ros de la
programación orientada a objetos.
'Ejemplificar la implementación del nivel físico de un TDA utilizan_
do la programación orientada a objetos en el lenguaje
de
programación C++.
Programación orientada a objetos

¿Qué es la programación or¡entada a obietos?


El término de programación orientada aobjetos se puso de moda en la
década de 1990, aunque sus orígenes se remontan a los años 70
to,
lenguajes simula 7 y smalltalk. A grandes rasgos, ra programación "on
orientada a objetos podría definirse como una filosofía para programar
!-encapsulando datos y código para formar objetos, que interactrían para
, I obtener los resultador
' "rp"ruáor.
A diferencia de 1a programación tradicional (procedural), en la pro-
, :gfamación orientada-ao6jetos sólo se puede u""".* a los datos que
' "conforman un objeto a través del código
asociado al,propio objeto.
Asimismo, laprográinación orientada a objetos posee los mecanismos
de herencia y polimorfismo como características que dan mayor poder
y flexibilid ad a la programación.

¿Qué es un obieto?

En la programación orientada a objetos, un objeto es un paquete que


contiene datos y el código en forma de subrutinas que operariín sobre
los datos del propio objeto. Los datos que guarda un objeto se llaman
atributos del objeto, mientras que a las subrutinur qu" operan sobre
los datos se les conoce como métodos. Los objetos-de un programa
se comunican enviándose mensajes, y así se generan los resultados
correspondientes.
Para los fines de este libro, hay una relación muy estrecha
entre la
abstracción de datos y la programación orientada u áb¡"tor, por lo que
cualquier estructuía de datos, vista como un TDA, se considera como
yn objeto en la programación orientada a objetos. La especificación
lógica de un TDAdetermina claramente cuáles son las op"áiorr"s
v¿íli-
das en la estructura de datos, por ro que de ahí se obiendr¡ín
directa-
me¡¡te los métodos del objeto; los atributos del objeto se determinarán
con base en la representación física que se le quieia dar al rDA.

F: J:
iOué son la herencia.g et polimorfismo?

¿Qué venta¡as ofrece imptementar las estructuras de


datos con la programación orientada a objetos?

Puesto que la programación orientada a objetos se apoya en la idea


de la abstacción de datos, estrán implícitos los beneficios de la técnica
que se mencionó en el capítulo anterior. Adicionalmente, se obliga al
programador a separ¿r claramente la construcción a nivel físico de la
estructura de datos de la aplicación que se le dará. Las estructuras de
datos implementadas como objetos pueden guardarse como unidades
de software que pueden emplearse en diferentes aplicaciones. Además,
los mecanismos de herencia y polimorfismo permiten generar nuevas
estructuras de las ya existentes.

¿Qué son la herencia y el polimorfismo?


La herencia es el proceso mediante el cual un objeto se define adqui-
riendo las propiedades de otro, es decir, hereda ros atributos y méto-
dos de un objeto superior. Por ejemplo, el objeto leónheredatodas las
propiedades del objeto mamífero, que a su vez hereda las propiedades
del objeto vertebrado, que su vez hereda los atributos del objeto cri-
mal. sino existiera el mecanismo de herencia, cada objeto tendría que
definir sus características; al haber herencia, cada objeto define sólo
los atributos adicionales y específicos, y no los comunes al objeto de
quien hereda.
El polimorfismo es un mecanismo mediante el cual se puede lo-
grar que una misma operación se realice de diferentes formas, según
los objetos sobre los que se aplica. por ejemplo, el símbolo +, tradi-
cionalmente usado para sumar dos números, puede redefinirse por" '*"-o
polimorfismo para que sirva también para concatenar dos strings.
Aunque estas ideas son muy importantes dentro de la filosofía de
la programación orientada a objetos, se mencionanán sólo dentro de las
estructuras de datos que 1o justifiquen
Programación orie'ntada a obietos

¿Qué es una clase?

La mayoía de los lenguajes de programación orientada a objetos utili-


zaneltérmino Clase para describir a los objetos de un mismo tipo. Nor-
malmentb, la definición de una clase es la declaración de'un tipo de
dato que involucra la especificación de los atributos y los métodos
de un objeto. Cuando se decláre una variable del tipo de dato de la
clase, se:creará un objeto o una instancia de objeto que ya contiene
físicamente a los atributos y métodos asociados'

¿Gómo se usan los obietos?


Los objetos sólo pueden utilizarse enviiíndoles mensajes para que reac-
cionen con alguna acción que repercuta en el estado de un programa.
Puesto que los datos que contiene un objeto sólo pueden utilizarse a
través ¿i fOs métodos del mismo, los mensajes en sí son los nombres
de los métodos asociados.
El envío de mensajes a los objeto§ y entre los objetos es 1o que dará
al final e1 réstiltado esperado de.un prográma.

66 Ejemplo
En un sistema bancario,'las cuentas de cheques de los clientes pueden
considerarse objetos. Todos ellos pertenecerían a una clase llamada
CUENIA_DEJHEQUES que define, para cada instancia,los siguien-
tes datos:

- Número de la cuenta
- Nombre del cliente
- Sucursal donde se abrió la cuenta
- Saldo de la cuenta

I
Ejemplo

Entre los mé1odos que pudieran asociarse a los od¡etos de la clase


CUENTA-DE-CI{EQUES pueden mencronarse :

. AUIA-DE-CUENTA. Este método se ejecutaría al crear un objeto


de la clase CUENIA_DE_CHEQUES, e implica solicitar de reclado
los datos correspondientes para guardarlos en los atributos'del
objeto y colocar el valor de cero en el saldo actual.

. DEPOSITO. Este método agrega la cantidad especificada al saldo


de la cuenta.

. RETIRO. Este método quita al saldo de la cuenta la cantidad espe-


cificadai validando que sea posible retirú esa cantidad.

. MUESTRA_SALDO. Este método muestra en pantalla el saldo de


la cuenta correspohdiente.
.i ,.

Dada la definición anterior, los objetos de tipo CUEI\TA_DE_CHE-


QUES, responderán a mensajes con los nombres: ALfA_DE_CUEN-
TA, DEPÓSITO, RETIRO, MUESTRA_SALDO, que coffesponden
a los nombres de los métodos. Los objetos responderán a los mensa-
jes, ejecutando el código asociado a los métodos correspondientes
(figura 2.1).

Mensajes
El objeto responderá
a lbs mensajes eiecutando
los métodos correspondientes.
->

Figura 21. Flelación entre los té¡rninos CLASE, OBJET0, MENSAJE


y MÉToD0.
Programación orientada a objetos

Aunque en la actualidad existen diversos lenguajes orientados a obje-


tos, algunos más puros que otros, este material.uilizaráobjetos para
representar estructuras de datos en el lenguaje C++.
Dadas las características de este m4terial, se deja al estudiante la pro-
fundización en el estudio de este tema y de los lenguajes. Consulie la
bibliografía su gerida.

Sintaxis para utilizar obietos en G++


Definición de clases:

clnss no,mbre
,{ ll Lista de atributos, con.la sintaxis de la
// declaración tradiciotwl de variables en C

ll Lista de métodos, usand.o la sintax,is de la


// declaración trad.icional de funciones en C
];
Definicién de objetos:

--> Declarar varigbles del tipo de la clnse.

Envío de mensajes:

v arinble . nornbre del e


-objeto -mensaj

@ Eiemplo
¿Recuerda la necesidad del TDA numerote en el ejemplo del cálculo
del factorial en el capítulo anterior? Ahora procederemos a analizar
cómo podría ser su implementación en el nivel físico.

¿Cómo se puede representar en memoria el TDA num.erote?


Una primera idea, fácil de conceptualizal es utilizar un arreglo que
sirva para guardar mil dígitos (en forma de caracteres). Para poder
controlar cuántos de estos rnil espacios del arreglo realmente está
empleando un nuflrcrole, se requiere un indicador de la cantidad de dí-
gitos que contiene elnumerote. Éstos pueden implementarse como los
atributos de un objeto que representarán an numerote.
Ejemplo

El TDA numerote en lenguaje C++ se programaía así:

class Numerote
{ private:
char iiigitos[1000];
int cantidad;
public:
//. Métodos que programan las operaciones
];
Es muy importante notar que el nombre de la clase es un nuevo tipo de
dato. t¿r E¡
a
ut§§g!
¿Cómo se impleme ntaránlas operaciones?
{hs
Flr L
pff
'l'*
'tr ¡

x§j
l,*T!t
El diseño lógico determina la abstracción modular para cada una de las - dt,'t
operaciones. Sin embafgo, dado que el TDA numerote es un objeto, . ril'
conviene programar las operaciones como un método de la clase l¿J§f
I
;ffi
a,H

(función miembro). Además, puesto que un objeto nulmerote está invo- u_:5 §tr
q
lucrado en la implementación de la operación, no será necesario maRe-
jado como parámeffo.
msa ,\§
0a* [u
H
H
La programación de la operación despliega, sería:
¡¡i
void Numerote : : de splie Sa( )
{ for (int i = 0; i<cantidad;i++)
cout << disitosfjJ;
]:
Es importante notar cómo la función no reqaiere el parámetro del
numerote, pues al ser un método de la clase, se trabaja automática-
mente sobre los atributos del objeto involucrado.
La operación suma no representa estrictamente un comportamiento de
los numerofes, sino que puede verse como una aplicación, por lo que
puede implementarse como una función libre y pafa facilitar su irn-
plementación se puede hacer amiga de la clase:

friend Numefote suma (Numerote N|, Namerote,N2);

Por otro lado, utilizando las características del lenguaje C++, se puede
aprovechar el concepto de sobrecarga de operadores para dar un nom-
bre más práctico a las operaciones:
Programación orientada a objetos

friend Numerote opgrator+.(Numerote NJ, Numerote N2);


friend ostream& operator<< (ostream &os, Numerote N);

De esta manera, la aplicación final del TDA numerote podría imple-


mentarse así: , '

Numerote factorial;

for(intj-n;j>0;j--)
factorial = factorial * j ;

Este código supone que se tienen'definidas las operaciones de asigna-


ción y multiplicación de numerotes y enteros.
Es importante observar qüetlh irtrplementación de:la'aplicación es
independiente de la forma en que se implementó el nivel físico del.
TDA numerote.

1. Defina los siguientes conceptos:


. Clase
'Objeto
. Mensaje.r,
r Polimorfismo

2. Implemente el objeto CUENTA_BANCARIAen lenguaje C++. En-


víe mensajEs para depositar y retirar dinsrg, mostrando el estado de
cuenta después de cada operación.

3. Tome.la,espocificaci§n lógica del.TDA CADENAdel capítulo ante-


rior e implemente el TDA como un objeto en cualquier lenguaje.
Ejercicios

4' :A continuación se muestra ra


decra¡acién de una crase en renguaje
. c++,'que es út, para rcpres entar aun punto
¿"i pu"á-;ordenado:

class Punto
{ public:,
: punto(
); //,Método constructor qu1 iyiciqliza
en la coordenqda (0,0)
, void Lee( ); // !!éndo que tee aa iirt"rir-"lrírr'";rr":;::;"ada (x,y)
v o i d D e sp ti e a('j
s ; 1
i
u n la ;; ;; ;ü, "i*li
i i', ¿lráííí,
@,,y ) d e t

float Distancia{punto p');


"; " "'
, //,Eis¡e.método carcura la distancia
del pui,ta qutq
// recibe el mensaje al punto i.
plivate:.
float x, y; ,l,I:,,:::::,!,:,::,guardan tos yatores de ta coordenada (ay)
]; // que corresponden a un punto en plano
el cqordenado.

a) Escriba la imprementación del


método Distancia,cuyo ehcabe_
zldo ya.esta defiinido en la clase puio.Reclrerde
qtre la distan-
cia,entré dos puntos (xr, yr) y (xz,y2),
fórmula: ' ¿'J L" se calcula con fu Jguiu*"

Distancia = \/1xr_fil-r-qf;D

b) El triríngulo es una figura geométrica


que puede definirse como
un objeto que contiene tres vértióes,
donde cada vértice
' punto en el plano coordenado. frtilizando la crase
-p-*n*,
es ün
puede definir una crase para ,"
los triángulos ¿" ñ.igri"íte
nera: ma_

o
class Tricingulo
{ public:
se encuentran los encabezados
,rrrror'f,&'í de los métodos asociados a un tridnguro.

Punto vr, v2, v3; // Estos atribufos co*esponden a


]; l* t ,.iÁr, del tyi¡inguro
",

Basándose en estas características


y en el método que implementó en
el inciso anterior, describa ra implemeniacion
de una función miembro
(método) de la clase
como valores de salida las
?:*f-"t:qr.."g."r"
longitudes de los tres lados áa
,ri,inguií. s" pu"o" ,ro*;;
res de los vértices ya están valididos f,u" to, uuto_
y, srempre corresponden a los
vértices a" un-tiáguto.
Programacién orientada a obietos

puede tener tres o más


c) El polígono es una figura geométrica'que
base en los vértices que
lados y que también fuede- definirse con
contenga.
puntos para definir un p?
Si se considera que se usa un arreglo de
lígonode.N,vértices(N>3),elarreglocontendríalosvaloresde
lascoordenadasdelosvérticesordenadosdetalformaque,alunir
se forma un lado del-"----"'
o-"*-, .i-pti** rr,a "" "i *"gto con el segundo forma offo lado' y así
polígono, áiu"it"r con el tercero se
"gt"'lo
hasta iorfn* elúltimo lado con elúltimo
punto y el
.,r."rir*"rrt",
Primer Punto del arreglo' paÍa implementar
Utilice ru á"rmurión-typedef Punto Poligono[N];
el perÍmetro de un polígono
una función libre que sirva para calcular
considerado parámeiro de entrada. considere que el ""s1-9
"orno y que siempre tiene 'N'
ya se cargó con los datos de un polígono'
vértices.
UtilicelaclasePuntoyelmétodoDistanciadefinidosenelinciso
polígono es la surna de las
a. Recuerde que el perímetro de un
longitudes de sus lados'

r----- RuToEuRLURc I ÓN q i
Ir
t

de programación orienta-
l. Carac@rtsdcas esenciales de los lenguajes
dos a objetos:

b) EncaPsulamiento
a) Recursividad
d) Todas las anteriores
c) Funcionalidad
e) Ninguna de las anteriores

2.Contesteverdaderoofalso.Unmétodoeslapeticiónquesehacea
comportamiento:
un'objeto para que éste reaccione con cierto
flutoeualuación

3. Valor resultante de evaluar la siguiente expresión en lenguaje C++:


8+3Vo2

a) cero b)8 c)1


d)7 e)9

4. Si se considera que la variable n yatiene un valor mayor que cero,


¿qué valor se obtiene en la variable r después de ejecutar el esta-
futo for?

."_ t,t,
I -

for (int i = l; i <- n; i++) r x= ¡;


a) r gaardael valor de la siguiente multiplicación: I * 2 * 3 * ... * (n-l) *
n
b) rguardalamultiplicacióndenporn, nveces (n* n* n* .....* n)
c) r guarda el valor de r * j
d) r guarda el valor de I * n
e) r guarda el valor de 1

5. Conteste verdadero o falso. Una función que contiene tres paráme-


tros por referencia (utilizan el operador &) y dos parámetros por
valor, genera como salida al menos tres valores:

6. Dada la siguiente declaración, se puede afirmar que:

class Fecha
{ public:
Fecha( );
Fecha(int a, int m, int d); ll inicializa la fecha con valores dados
void despliega ( ); ll despliega en pantalla unafecha
"-o
int cantidad-dias-franscurridos( ): llcalcula cantidad de días transcurridos desde
ltl/t/1900
private:
int Año, Mes, Dia; ];
Fecha fl , fl,(1997, 8, 20);

a) fl
esun objeto de la clase b)Fecha es un objeto de la clase
Fecha f2
e) fl es un método de la clase d)Fecha es un método de la
Fecha clasefl
e)/ es un mensaje de la clase
Fecha
Sogmlrció¡añentada a objetos

7. ¿Cuál de las siguientes instrucciones envía correctamente un


mensaje a algunos de los objetos definidos en la declaración de la
pregunta anterior?

a) ft.despliega( );
b) fl,(1997,1,12);
o--"-" c) Fechafl( );
d) fI.mes;
e) cantidad_dias _tra.ns c urrido s (f2, ) ;

Según la declaración de la pregunta 6, ¿cuántas veces se ejecuta el


método constructor?

a) ninguna vez, pues no se ha utilizado


b) sólo una vez ,(
c) dos veces
d) tres veces
e) tantas veces como se haya llamado al método en el programa

9.'Según la declaración de la pregunta 6, ¿cuántos objetos estarán


involucrados cuando el programador utilice el'método
c ant i da¿ an sc ur r i do s?
-dtas -tr

a) ningún objeto
b) sólo un objeto
c) dos objetos
d) tres objetos
e) tantos objetos como se requieran

10. Tomando como base la declaración de la pregunta 6, y suponiendo


que la siguiente instrucción es válida:

tf (fl < fl) cout << "In fecha es posterior"


ffutoeualuaclón

¿Qué declaración tendría que incluirse en la definición


para que la instrucción anteriár de la clase
fo*il;*, correctamente?

b)[iend char operator < (Fech.afl, Fechafl);


c-![fena Fecha operator < (Fechafl;
d)friend char operator < ( );
e)friend char operator < (Fechafl;
Capltulo
ptD[r5iltrfl(oil

DrtST[Uffi[fl50r
»ITO5
OBJETIVOS
'Entender qué es la representación física de una estructura de datos.
'Describir las características que distinguen a la representación por posiciones,
y ala representación por ligas o encadenamientos.
'Definir qué es un apuntador y cuáles su aplicación en el contexto de un lenguaje
de programación.
'Distinguir la diferencia entre una dirección de memoria física o real y una dirección
lógica o relativa (arreglos).
'Entender cuáles son las diferencias entre el uso de la memoria estática y la memoria
dinámica.
' Comprender las ventajas de utilizar la memoria dinámica en las aplicaciones de
software.
' Conocer las operaciones para crear y liberar espacios de memoria dinámica.
' Aplicar correctamente las reglas para utilizar a la memoria dinámica.
'Aplicar los conceptos de apuntadores y memoria dinámica para trabajar con objetos
dinámicos y objetos con atributos dinámicos.
' Ejemplificar los conceptos con la programación del nivel físico de un TDA utilizando
la programación orientada a objetos y los atributos dinámicos.
Bepresentación de estructuras de datos

¿Qué es la representación de una estructura


de datos?

Básicamente, puede entenderse como el punto de conexión entre la es-


pecificación lágica de un TDA y su implementación en un lenguaje de
'; programación particular. Dentro del proceso de abstracción de datos, la
O_-__.._
iepiesentación de una estructura corresponde al inicio del segundo
nivel de abstracción, es decir, el nivel físico. Esta etapa construye un
de datos
esquema de cómo se almacenariín los elementos de la esffuctura
en la memoria, de tal forma que se logre su óptimo aprovechamiento.

pafa una
¿Qué tipos de representaciones ex¡sten
datos?
r.

estructura de
Independientemente de las facilidades de implernentació¡ que oftez,
ür lenguajes de programación, una estructura de datos (TDA) pue{e
"u,
representarse de dos formas:

. por posiciones (almacenamiento contiguo)'

. por ligas (almacenamiento disperso)'

¿Gómo funcion a la representación de una


estructura
de datos Por Posic¡ones?

En este tipo de representación, el lugar físico donde se almacena un


elemento, determina automáticamente su posición relativa en la estruc=
tura de datos. Básicamente, se puede pensar en ella como un espacio
de almacenamiento contiguo donde cada lugar sirve para almacenar un
elemento, de tal forma que si un elemento está almacenado en el lugar
K, tendrila K-ésima posición dentro de la estructura y, obviamente, el
elemento K + L estaráubicado exactamente después del K y se alma-
cenaráen el lugar K + L del espacio de almacenamiento. Esta represen-
tación se ejemplifica en la figura 3.1.
iOué herramientas existen tipicamente en la magoria de los lenguajes de prograrnación
para desarrollar una representación por posiciones?

Figura 31. Flepresentación por posiciones [almacenamiento contiguo].

como ya se mencionó anteriormente, una de las principales caracterís-


ticas de este tipo de representación es que la dirección (posición) de un
elemento depende directamente del lugar físico donde se almacenó.
Además, se establece implícitamente una relación de linealidad entre
los elementos almacenados, ya que, del elemento I (que está en la
posición 1), sigue el elemento 2 (queestá en la posición 2j,y del2 sigue
el elemento 3; y, obviamente, antes del elemento 3 está el,2 y así suce-
sivamente.

éQué herramientas existen típicamente en la mayoría


de los lenguajes de programación para desarrollar una
representación por posiciones?
"""'-'a
casi todos los lenguajes de programación proveen al programador de
herramientas útiles para representar estructuras de datos en forma
contigua.
Las herramientas empleadas para representaciones contiguas que, a
su vez, resultan ser estructuras de datos implícitas del lenguaje, son:

arreglos de elementos uniformes: permiten armacenar un conjunto de


elementos del'mismo,tipo;ya sea simple (como enteros, strings, etc.) o
compuestos (registros con elementos de diferentes tipos). Figwa.3.2.
fg¡r-us¡?ct¡n ¡le estnrct¡rras ds üatss

o***-.--*

Figura 3.2. Arreglo de elementos


uníformes

Registros de elementos de diversos


tipos: permiten definir estructu_
ras que conjuntan valores de diferent..
iipor, almacenán¿of,o, como si
fueran una unidad (figura 3.3).

Figura 3.3. Registro de elementos


de diversos tipos.

Archivos secuenciares: al iguar que


los arregros, esta estructura permi_
te almlcenar un conjunto de elementos,
aunque ro hace en Ia memoria
secundaria.

éQué ventaias y desventaias tiene la representación


por posiciones?

una de las principales ventajas de utilizar


representación contigua es
su fácil implementación, adernás
de su rapidez de recorrido, debido a
que la dirección de cada eremenro
está implícrtu ,u fori"ión física.
Sin embargo, este tipo de representaciones
. para ",
gráá"r;;;_
ti"""
jas realizar manipulacionls sobre la
estructura, principarmente
cuando se desea agregar un nuevo
elemento en algún rugar que no sea
ácómo funciona ra representación de una
estructura de datos por rigas?

el último. Esto se debe a que, dado que los


elementos están almacena-
dos ren forma contigua, no existe un espacio
físico disponible entre
ellos; de tal forma que se tendría que
"generar', uo nu"ro espacio. La
única forma de hacerro es desplai ar hacia abajo
los elementos que
estiín después de la posición de inserción
deseaáa, togrando con esto
que se genere un espacio para poder agregff
un nuevo elemento.
De manera sim,ar, borrar un elemento que
no sea el último deja un
hueco no permitido entre los elementos; si no
se elimina ese espacio,
ya no se podría usar la posicién física del
elemento como su referencia
de dirección. La única manera de solucionar
este problema es despla-
zaf vna posición hacia, anlba los elementos que están
después del
elemento borrado.

¿Góino funcio_na la representación de una estructura


de datos por tigas? i

En este tipo de representación la ubicación física


de un elemento no de_
termina la posición relativa que tiene denrro ¿"
almacenamiento en este tipo de representación ".t
ru o.;;;" datos. El :;

," ,"ur¿u forma dis_ I

I
persa, es decir, dos elementos contiguos
en la estructura"nde datos no
necesariamente deben estár almacenados
físicamente en posiciones
contiguas dentro del espacio de almacenamiento,
como se muestra en
la figtlr.a 3.4.

2
-'o

K+1

Figura 3.4. Almacenamiento disperso.


á0ué es un apuntador?

una de ellas es que dicha representación no es exclusiva de las es-


tructuras que mantienen una organización lineal; es decir, también se
puede lutilizar para estructuras más generales, que requieren de una
organización no-lineal.
otra ventaja es la posibilidad de agregar y eliminar elementos de la
estructura sin tener que desplazar los elementos que ya estaban en ella
(tal y como ocuffe en el almacenamiento contiguo).
Asimismo, una de las ventajas principales es que la representación
por ligas permite un uso más eficiente del espacio de almacenamiento,
ya que se puede hacer crecer y decrecer la estructura según se requiera,
lo que no es posible hacer con la representación contigua.

a herramientas brindan Ia mayoría de los


éQué
lenguajes de programación para desarrollar
una representación por ligas?
Básicamente,, en la mayoría de los lenguajes de programación no
existen herramientas predefinidas para soportar una representación
por ligas; por 1o tanto, es el programador quien implementa las es-
tructuras. La construcción de este tipo de representaciones se apoya
en el concepto de apuntador (tipo de dato capaz de almacenar una
dirección de memoria).
una de las estructuras de datos lineales que utiliza este tipo de re-
presentación es la lista encadenada que, de hecho, se considera la
abstracción de la representación por ligas para una estructura de datos
lineal y, por ello, se emplea como una opción para representar otras
estructuras de datos lineales más especializadas. La descripción del
TDA lista encadenada se explicará en el siguiente capíturo. por ahora, o
es importante conocer las herramientas auxiliares para trabajar efi-
cientemente con una representación por ligas.

¿Qué es un apuntadotQ
Un apuntador se define como un tipo de d,ato capazde almacenar una
dirección de memoria. Se considera como referencia indirecta a un ele-
mento.
Los apuntadores pueden ser un tipo de dato especial dentro del len-
guaje de programación en cuyo caso, guardarán direcciones de memoria
real; o bien, el programador puede simular el funcionamiento de un
Representación de estructuras de datos

apuntador, por ejemplo, cuando una variable de tipo entero guarda la


posición (subfndice) de un dato en un arreglo. Para efectos de este ca-
pítulo, es importante conocer cómo se trabaja con los apuntadores que
proveen algunos lenguajes como tipo de dato.
La figura 3.6 muestra la diferencia entre una variable tradicional y
una de tipo apuntador.

n
VABl

:
n+1
ffi
t
:
É
t
i
J

*VAFI2
"*
l4
-l

ffi*ffi¡Hffi
Figura 3.6. Difenencia entre una variable Fadicional VABl y un apuntador VAR2.

¿Pafa
No todos los lenguajes de programaciónpermiJen el uso de apuntadores,
aunque la mayoría 1o hace. Sus principales aplicaciones están relacio-
nadas con el manejo de la memoria dinámica (concepto que se explica-
rá más adelante) y en lenguajes como C y C++; además, se emplean
para permitir el paso de los parámetros por referencia a los módulos.

Is
I
áCómo se utiliza un apuntador en lenguaje C/C++?

¿Gómo se declara un apuntador en lenguaje G/G++?


La declaración de un apuntador se realiza de la siguiente forma:

tipo_de_dato xnombre-apuntador;

Por ejemplo:

int *p;
char *c;

En este ejemplo,la variable p almacenará direcciones de elementos


enteros, mientras que c guardará la dirección de valores carácter.
La definición de un apuntador puede incluir cualquier tipo de dato, ya
sea simple o estructurado. Observe que la diferencia entre una variable
tradicional y una variable apuntador es el asterisco que acompaña la
declaración de dicha variable.

¿Gómo se ut¡l¡za un apuntador en lenguaje C/G++?

En lenguaje CIC++ hay dos operadores muy importantes para la mani-


pulación de apuntadores: el operador de indirección, que se identifica
con el símbolo * y el operador de dirección, que se identifica con el
símbolo &.

El operador de indirección se emplea para obtener el valor almace-


nado en la dirección que guarda la variable apuntador; es decir, accesa
el contenido y con é1 se puede rcalizar cualquier operación permitida_. .-" -a
pila ese tipo de valor. Se utiliza de la siguiente forma:

El operador de dirección se usa para obtener la dirección de alguna


variable. Dicha dirección puede almacenarse en un apuntador capaz de
guardar direcciones del rnismo tipo de dato que la variable, en esta forma:

&Variable.

Observe que el operador de indirección sólo se puede emplear con


variables apuntador, mientras que,el operador de.dirección puede em-
plearse con cualquier tipo de variables.
Bepresentacién de estructuras de datos

Asi si se tiene la declaración y las operaciones:

int a, b, *p, *q; P=&a;


a=3;
q=p;
U_xq+2;
o
se tiene que:
. El apuntador p almacena la dirección de la variable a.
. La variable a guarda el valor de 3.
. El apuntador q guardarálamisma dirección que almacena el apun-
tador p.
I
. La variab\e b toma e\ conteniüo apuntaüo por \a üireccrón a\ma-
aenada en q (un 3) y le suma un 2, pot lo tar$o b tomará el va\ot
\l de 5.
'I §\Le\§ \e\§e-
\ . DespuLs \e R§\t§ §!t\uü§\§\',\§\§§§\t'§\§N\\§§
ri[
tI
tü moria con a, *P Y
*q'
t it
* ,litir

ii
#
¿Qué es la memoria"dinámica?
.ffi
{
*lti'
,U

"'ll;

ffi Muchoslenguajesdeprogramaciónpermitenmanejardostiposd:d
macenámientodedatosenlamemórianrinciga}:glalmacenamiento
dinámico'
estático lo automático) y el almacenamiento
:

,l:,"

LamemoriaestáticaeslaquesemaneJatradicionalmente.Sus
son:
PrinciPales características

. una variable, ya sea global o


Se define explícitamente al declarar
local' ' .r----^-^-r^
.ElcomPiladorgeneraautomáticamenteelespaciodememoria.
. se mantiene fija durante toda la vida de la variable (independien-
temente de que se utilice o no)'
s^ ^^^^^ '

Lamemoriadinámicapermitecrearydestruirespaciosdememona'
la ejecución del
progiamador durante
segrín indicaciones explícitas del
son:
programa' Sus principales características
denominada heap'
' lJttlizauna parte de la memoria principal
'Ñ;;etusoeficientedelamemoriadurantelaejeclción'
que almlce,nel direcciones de memorra
' nlqíit" apuntadores
que éstas se asignart dinámicamente'
,.u1, dudo
zcómo se pueden crear g liberar espacios
de memoria dinámica?

¿Gómo se pueden crear y riberar espac¡os de


dinámica? memor¡a
Los espacios de memoria din¡ímica
se crean y se destruyen, a petición
explícita del programador, mediante
operacione, de cada
trp: detnguaje. En eHenguaje c se cuenta "rp""iurus
con ras operaciones mailoc
y free. En C++ se utilizan los,operadores
new y delete.
El operador new se utiliza de la siguiente
forma:

apuntador = new fipo_de_dato;

La ejecución de un new una petición al sistema operativo para


que se le otorgue un.espacio .hace
de memoria del heap del taáaño asocia-
do al tipo de dato indicado. si er espacio
de memoria está disponible,
la operación regresa la dirección ál o"l
otorga al programulg. rpor eso, se asigna ".pr;;;;;#;;ffi;rJ
a una variable apuntador el
resul tado de I new ). n o h ubiera . rpu.io ;"
de cero (NrrLL). El.Si "ñ;;;.""rd;;;;;l ;;
apunrador tomi el valor ¿" ru
ese nuevo espacio, que estará ,"p*uoo
iiió"¿ñ;ffi;;
que sea liberado.
f";"ir;;;"i""*r"f r,"rr"

El operador delete se utiliza de la siguiente


forma:

La ejecución der derete provoca que


se libere er espacio direcciona_
do por el apuntador, dejándolo con
un valor in¿efinido. Esto quiere
decir que, al espacio referenciadopor
el apuntador, el sistema operativo
lo considerará como merno¡ia disponibre
en el heap vvL L
J' por
-'vsi' y, 10 tanto, ya
no se podrá accesar.
".- -"o

Por ejemplo, si se tiene ra siguiente


decraración de variabres
: int a, *p;
se podría asignar un espacio dinámico
ut upu,tuJ*;;;;rnera si_
guiente: p=newint:

Para accesar el espacio dinrímico


uprnruJo por p yasignarle el valor
que guarda la variable a, se ejecutaríalasiguiente
instru"ccion:
*P=a;

cuando ya no se requiera utlrizar er


espacio diniímico apuntado por
p, se deberárcalizar la instrucción:
delete p;
Representación de estructuras de datos

¿Cuáles son las reglas para programar con apuntadores


y memoria dinámica?
Al programar, estas herramientas brindan un potencial muy importan-
te fara manejar eficientemente la memoria con diversas estructuras de
da-tos. Sin embargo, manejar directamentela memoria
tiene sus nesgos
o""" ""' con ciertas t"-glu:
V *"V i*portalnte qo" io* programadores cumplan
"-
queevrtenque\osploBlaÑt§q\§\tN\Lt\tputr\nüorcs.yseno{\aüiná-
mica fallen en su ejecución'
Estasregla.."hu,.agrupadoenelsiguiente''Decálogoparaprogra-
mar coffectamente utilizando memoria diniímica"
:

l.Porcadavezqueseejecute|lrlnew,deberáejecutarselufndelete
antes de terminar la ejecución de un
programa'

Lamemoriadinámicanoesglobalnilocal;provienedeun¿írea
dememoria,heap,queadministraelsistemaoperativo.Porlotan-
to, ,i.i"á op"*,ino reserya_los espacios {3 memoria dinámica
"t importar si el
sin
que se solicitan hasta que se indica su liberación,
programa en cuestión terminó o no su ejecución'

2.lJnd.eleteactúaliberandoelespaciodememoriaapuntado,inde.
en el mismo
pendientemente de que existan más apuntadores
espacio.

los apuntadores con


Cuando se libera un espacio dinámico' todos
referencia hacia el mismo guardan un valor
indefinido (basura), y
ya no es posible accesar ningún dato a través de
ellos'

al terminar su eje-
3. Un apuntador local a un módulo se destruye
hace referencia.
cucián, sin importar a qué espacio de memoria

Se deberá cuidar que los apuntadores locales


no dejen "volando"
espaciosdememoriudi,á,''i"ucuandoseterminelaejecucióndel
*ódoloalquepertenecen,amenosqueelespaciosolicitadovayaa
parámetro de salida)'
eliminarse del módulo (como resultado o

4.BasuraY nada son diferentes'

Elvalornadaesválidoparaunapuntadoryrepresenta''noapun-
taraalgúnelementoenrnemoria.';elva|orbasuraescualquier
zcuáles son las reglas para programar con apuntadores U memoria dinámica?

valor indefinido. En el lenguaje c++, la constante NULL repre-


senta el valor de nada en los apuntadores.

5. Hacer w delete con un apuntador que no hace referencia a un


espacio de memoria dinámica provoca fallas de ejecución.

La operación delete sólo actúa con espacios de memoria solici-


tados al sistema operativo con un new. siun apuntador con valor de
nada (NULL), está indefinido, o bien, apunta a un espacio de me-
moria estática, la operación delete sobre este apuntador podrá
provocar fallas al ejecutar el programa.

6. Una referencia a través de un apuntador, cuyo valor sea NULL,


provocará fallas en la ejecución del programa.

Cuando un apuntador señala a na.da,rzo es posible hacer una in-


dirección (con el operador x), pues no se hace referencia a ningún
elemento. Normalmente, se cancela la ejecución del programa.

7. Al asignar un valor a un apuntador con la operación new, el


apuntador perderá su valor anterior, independientemente de
qué esté señalando.

La operación new genera el valor de Ia dirección del espacio de


memoria dinámica recién creado, para asignarlo a un apuntador. si
el apuntador tiene un valor indefinido o valor de nada (NULL), no
habrá ningún problema al crear esta referencia, pero si er apuntador
ya referencia a otro espacio de memoria dinámica, deberá evitarse
]u'sar new con ese apuntador, o bien, referenciar previamente el es--**__a
pacio ya creado con otro apuntador, para no dejarlo ,'volando',.

8. No siempre se tiene que realizar an new para utilizar un apun-


tador.

Los apuntadores por sí mismos son espacios de memoria que


guardan como dato una dirección. una forma de asignarles valor es
a través de un new, sin embargo también pemliten la asignación di-
recta del válor de otro apuntador o de la constante nada (NULL).
Aquí se aplican las reglas de congruencia entre tipos de variables.

9. Los valores de los apuntadores se pueden comparar para verifi-


car si señalan lo mismo o no.
Representación de estructuras üe üatos

Los operadores de comparación de igualdad y desigualdad (== y


!-) se pueden aplicar sobre variables apuntador, para verificar sus
referencias. Aquí también se aplican las reglas de congruencia entre
tipos de variables.

10. A un dato referenciado por un apuntador se le pueden aplicar


o todas las operaciones válidas para el tipo de dato.

Para hacer referencia al dato apuntado, siempre se utiliza el ope-


rador de indirección (x). Cuando el elemento apuntado es un objeto,
se puede emplear el operador -> para el envío de mensajes, de
acuerdo con la siguiente equivalencia:
( * ap _obj ).mensaj e = ap _obj ->mensaj e.

¿Guál es la relación entre los apuntadores y los


arreg¡os en lenguaje G/G++?
El nombre de un arreglo es, por sí mismo, un apuntador al primer ele-
mento del arreglo. Por lo tanto, si se declaró un arreglo de 100 enteros
de la siguiente forma: int af100J; se puede decir que d es un apuntador
al arreglo y que *a accesa aI elemento a[0].
Gracias a que en el lenguaje C existe la "aritmética de apuntadores",
los arreglos pueden manejarse con apuntadores con la siguiente equi-
valencia:

arre glo [j ] es equivalente a x ( arre glo +j )


&arregloIi] es equivalente a (arreglo+j)

Por 1o tanto: arreglo[0] es igual a *arreglo y &arreglo[O] es igual


a arreglo.

Por otro lado, con las facilidades de la memoria dinámica se pueden


crear arreglos dindmicos del tamaño que se requiera en tiempo de eje-
cución. La forma de hacerlo en C++ implica una variación al formato
del new y del delete, como se muestra en el siguiente ejemplo:

Tipo xarueglo; //se define sólo el apuntador


arreglo = new Tipo[tamaño]; // aquí se crea el arreglo dindmicamente
l/El acceso puede ser como un arreglo tradicional: arreglo[subíndice]
ilelete[ ] arreglo; // para liberar el espacio dintímico del arreglo
áCómo se pueden crear objetos dinámicos?

@ Eiempto

ARREGLO ESTÁTICO ARREGLO


"*Á*,"O
int dato§[200J; int xdatos, tam;
¡or.(j=l¡i1200;
cin
¡++¡
)> datos[jJ;
'il,"lr'='ff; int[tamJ;
;;;0=o; j<tam; j++)
cin >> dans[jJ;
.!..

Nota: observe que la definición de un arreglo


din¿ímico permite el uso de una variable pia
su tamaño.

¿Gómo sé pueden crear obietos dinámicos?


,,,

El concepto de la memoria dinámica en ros


objetos puede utilizarse de
dos maneras: creando din¿ímicamente
objeto, requieran, o
"uñoEnseambos
con objetos cuyos akibutos se crean diniímicamente.
casos
se aplican las reglas mencionadas anteriormente.
Incluso, se pueden
llegar autilizar objetos dinámicos que contengan
atributos din¿ímicos.

Paraftabajar con un objeto que se crea


dinámicamente, se aprican
lglformatos ya conocidos considerando que
el nombre de la clase de los ""."-""o
objetos es"por símismo, un tipo de dato.
Así; si se.tiene deñnida lá cla-
se Ejemplo, la forrira de definir
un objéto dinámico o" áci¿.lrse sería:

Ejemplo 'ap;
ap = new Ejemplo;

E.n caso de que la clase Ejemplo tenga un método constructor


pariímetros, la forma de crear un ob¡"to con
parumetnzado seúa:

ap = new Ejernplo(argumentos);
de datos
Bepresentación de estructuras

Paraaccesarlosatributosométodospúblicos.deunobjetodinámi-
así sobre el apuntador:
co, el op",uao,^ o" indirección
'" "iirá"'ra el lenguaje provee de
Sin embargo' ó;tcaso'
fap).mensaje'
simplifica esta escritut"" t]":1: equivalente a:
un operador que que se haga
L't op"'uOor -) se puede emplear siempre
ap->mensaie' por medio de un apuntador'
d" J";#; on ou1"to ilil; 1o------"-'-"*:
referencia
p"J;;';"n"' utriUutos dinámicos'
to, objetos
a"*, por otro taáo,f' ¿"
de memoria variables'
que permite
"'"*iO' á"
"bj""t """tputiot
Para este caso, se esperaría
que el
según ru, o"á*1JJ", "¡""*ión.
métodoconstructorhagaelrr.*"o*.pondienteyqueelmétododes- caso' ad-
tiuere tl-ile;;;' d"l to"" delete' En estedefinición
tructor "t'ib;;; destructores en la
de los métodos
quiere
'"'tid;i";;;;;'"ia i
á",,"u clase' i
@ Eiemulo
class EiemPl
{ private: que apuntard a un espacio
dinómico d'e memorru
int *aP; ll atributo

.nublic: Eiempto(int tam) {-ap = new :--.r+^*1.


in[tum" I lla?nera un espacio
' 'lf;,::o\,!l ff,r;-,'""'
'-Eiempto| generado por et
P''-'. r { detete[1 ap; ]
'!i'!:':-:,'^:::acio
llconstructor
l.

i
que pueden
diferentes combinaciones
Ahora, se ejemplifi catánlas
I
I
y memoria dinámica-
II ocurrir entre memoria estática
t
atributos estáticos'
tr 1. Objetos estáticos con una clase:
¡
que t*""to' la siguiente definición de
$ Supongamos
Ip, class EiemPlo
t
{l
{ public:
i: int ai
.....];
tjemplo

y ge declara'un objeto:

Ejemplo obj;

obj es un objeto estático.con un atributo estático, que si se quiere


accesar se haría con la expresión oáj.a
Obviamente, lo único que"se le puede asignar al atributo ¿ es
un valor entero.

2. Objetos estáticos con atributos dinámicos


Ahora supongamos que la definición de la clase contiene como
atributo a un apuntador:

class Ejemplo
{public:
int xa;
.....];
y se declara un objeto:

Ejemplo obj;
,
obj es un objeto estático con un atributo apuntadol que puede di.
reccionar a uR espacio dinámicor.que si se quiere accesar se harla
con la expresión obj.a y, obviamente, lo único que se puede asig-
nar al apuntador ¿ es una dirección.
una forma de asignar un espacio de memoria dinámico al apun-
tador a sería: obj.a = new int; y la forma de referenciar este espa-
cio dinámico para asignarle ün Valor sería: *(obj.a) = valor; que
es equivalente a *obJ,a = 8; dado que el operador punto (.) tiene
prioridad sobre el operador de indirección (*). -'*-*"a

3. ObJetos dinámicos con atributos estáticos


Ahora, supongamos que nuevamente se tiene la definición de la
clase con un atributo estático:

class Ejemplo
{ pubtic:
int a;
..... J ,

pero se declara un objeto dinámico a través de un apuntador:

Ejemplo *ap - new Ejemplo;


Bepresentación de estructuras de datos

La forma de accesar el atributo c del objeto apuntado por ¿rp se-


úa con la expresión ap->a.
obviamente, lo único que se puede asignar al atributo ¿ es un valor
entero, a través de una expresión como:

ap->a=valor;
o"-
4. Objetos dinámicos con atributos dinámicos
Finalmente, supongamos que tenemos el caso anterior, pero con un
atributo dinámico:

class Ejemplo
{public:
int *a;
.....];
pero se declara un objeto dinámico a través de un apuntador:

Ejemplo *ap=r"w Ejemplo ;

donde ¿p es un apuntador a un objeto dinrímico que tiene un atributo


que se puede direccionar a un espacio dinámico, que si se
desea ac-
cesar s€ haría con Ia expresión ap-s,sy lo único qu" ,. puede
asignar
al apuntador ¿ es una dirección.
una forma de asignarle un espacio dé memoria dinámico al apun-
tador ¿ sería:

y la manera de referenciar este espacio dinámico para asignarle un


valor sería:
x(ap->a)=valor;
que es equivalente a j

*ap->a=8;
dado que el operador flecha(->) tiene prioridad sobre el
operador de
indirección (*).

Estos conceptos se utilizarán y contextualizarán en una aplicación


práctica (listas encadenadas) y se explicarán en el siguiente
capítulo.
á0ué debe cuidarse a! pasar como parámetros objetos dinámicos en lenguaje C/C++?

éQué debe cuidarse al pasar como parámetros obietos


dinámicos en lenguaje CIG++?
Analicemos qué pasa cuando úabajamos con objetos estiíticos y se tiene
una declaración típica de pariímetros por valor:
void Ejemplo (Objeto obj);
Cuando se hace la llamada Bjemplo(x), automáticamente se crea el
objeto obj, qae tiene en sus atributos una copia de los atributos de x
(figura 3.7).

,4*G}'t
l, est¿ticos ,\ obj
x I *ffi/
r---r I
\:
\*_-/
Figura 3.7.

Ahora analicemos (figura 3.8), bajo esta misma declaración de


párametros, qué pasa cuando el objeto tiene atributos creados dinámi-
camente, es decir, el objeto tiene atributos que son apuntadores que
direccionan espacios creados din¿ímicamente.

x obj
-o

Figura 3.8.

como se puede observar, la copia automática en el parámetro obj es


sólo del valor del apuntador, por lo que el espacio dinámico estaía
siendo apuntado por los dos objetos al mismo tiempo.
El problema surge cuando el objeto obj deja de existir (al terminar
la ejecución del médulo Ejemplo), y se ejecuta automáticamente el
Bepresentación de estructuras de datos

método destructor sobre obj, por lo que afecta irremediablemente al


objeto x. Esto se aprecia en la siguiente figura (3.9):

x obi

Figura 3.9.

La solución a este problema es manejar el parámetro como una


referencia, pues, en este caso, al momento de llamar al módulo el pa-
rámetro no será una copia, sino una referencia (apuntador) al objeto
que actúa como argumento. Esto se aprecia en la figura 3.10:

obj

/;
qfu.
Figura 3fO.

Ya que desde el punto de vista del diseño es importante que el paní-


metro acníe sólo como entrada, el lenguaje provee el declarativo const
para que la referencia no se modifique bajo ninguna circunstancia.
De esta manera, cuando termina la ejecución del módulo, el pariíme-
tro formal obj, se destruye, pero, al ser sólo un apuntador, no afecta
al objeto referenciado, pues no se ejecuta el método destructor involu-
crado.
En este caso, el encabezado del módulo sería así:

void Ejemplo (const Objeto &obj);

Por lo tanto, cuando se desee emplear un objeto con atributos diná-


micos como parámetro de entrada a un módulo, deberá utilizarse el
declarativo const, declarando el parámetro por referencia.

Algunos detalles importantes en la programación, que utiliza herra-


mientas del lenguaje C++ se pueden encontrar en el Anexo A.

,i
til!
L,
Ejerc¡c¡os

EJERCICI.OS
1. suponga la siguiente definición dé clases y variables en lenguaje
C++:

class Ejeml class Ejem2


{ private: { private:
inta,b,c; char x, *y;
public: public:
Ejemt) { }; Ejem20
Ejeml(int x) { a = b = c = x; }; { x=0;
void despliega 0 y = newchar[SJ; ];
{cout<<a<<b<<c; }; -Ejem20
]; { deleteIJ y; ]'
];
Ejeml objl, *API, *Ap2; Ejem2 obj2, obj3, *Ap3;

Responda las siguientes preguntas:

a) ¿Curíntas veces se ejecutaron métodos constructores, según la de-


claración anterior?

b) ¿Cuáles el valor de los atributos de los objetos objl y obj2?

c) ¿Para qué objetos y cuiíndo se ejecutará un método destructor? -***"o

d) Escriba la instrucción para crear un objeto apuntado por ApI, ini-


cializando sus atributos con l.
e) Escriba,la insffucción p¿¿ia qq" créado en el,inciso d) sea
'
apuntado también por Ap2: "t;oui"to'
!,

f) Escriba la instrucción para crear un objeto apuntado por Api.


¿Qué valores tienen los atributos del objeto?

g) Escriba la instrucción para que el apuntadorA^pI señale,al obje-


to objl. ¿Qué sucede con el objeto que señalaba antes Apl?
Hutoeualuación

class Cornplejo
{ public:
Complejo);
Complejo(float x, float y);
float parte_Real0;
void escribe);
void lee);
private:
float real, imaginario; ];

Complejo numl, num2 (2,0) , xnum3, *num4, arreglo[lLJ;

l. ¿cuál de las siguientes instrucciones envía correctamente un men-


saje a alguno de los objetos definidos en la declaración?

a) escribe(numl);
b) num3.lee\;
c) num2.Complejo( l, j ) ;
d) num3->Complejo;
e) (*num3).Parte_Real0; ' :

2. ¿cuálde las siguientes opciones crea correctamente un objeto de la


clase Complejo?

a) Comptejo *num\( l, 0) ;
b) Complejo num6=new Complejo (3,1);
c) numl=new Complejo;
d) num3=new Complejo (4,0);
e) Ninguna de las anteriores.
"**--o
3. suponiendo que se pudieran accesar los affibutos privados de
la cla-
se, ¿cuálde las siguientes asignaciones es válida?

a) numl.real = *num3.real;
b) arre g lo - >re al = num3 ->re al ;
c) x numl .real=num2.real
d) arre glo [2 J ->real = ( x num3 ).real ;
e) num3->real = arreglo[5J.real

.:

i
,il

d
i,l Bepresentacién de estructuras de datos

4. Si se supone que P y Q son variables apuntador que apuntan al mis-


mo tipo de dato, y que aÚrn no se han inicializado, ¿cluál de los seg-
mentos siguientes de código está libre de fallas en su ejecución?
Nola.' considere que dejar nodos "volando" (sin referenciarlos) es también una
falla de ejecución.

o
a) if (P == Q) P = new Tipo; b) Q = new Tipo;
elseQ=newTiPo; P =NULL;
cout << *P << *Q; tf (P == Q) P=new Tipo;
else delete Q;

c)P=newTipo; d) delete P; e) P-newTipo;


Q. = new Tipo; delete Q; Q=P;
if(P!=Q)P=Q; P = new Tipo; delete P;
delete Q; Q = new Tipo; delete Q;

5. Considere el siguiente fragmento de código en C++:

float a '= 2.0, *b, *c;

b= &a;
c=new float;
*c = *b;
a= *c +1.5;
cout <<*b <<*c,'

¿Qué valores se desple garánen pantalla al ejecutarlo?

a) 2.0 2.0
b) 3.s 2.0
c) dirección de a y dirección dada en el new.
d) dirección de a y 3.5
e) 3.5 3.5
aprtulo
F-*.-.-

r51fl5 ilr(flDiltflDfl5

.OBJETIVOS

. Entender qué es una lista encadenada.


. Describir eI TDA lista encadenada.
. Comprender cómo se puede representar una lista encadenada, tanto
en memoria estática como en memoria dinámica.
. Describir la forma en que se pueden implementar las operaciones de
inserción de un elemento, eliminación de un elemento y desplegado
de los elementos de una lista encadenada.
. Identificar las caracteísticas, ventajas y desventajas de una lista en-
cadenada circular.
. Identificar las características, ventajas y desventajas de una lista do-
blemente encadenada y una lista doblemente encadenada circular.
Listas Encadenadas

¿Qué es una lista encadenada?

La lista encadenada es una estructura de datos que tiene :una organiza-


ción lineal y se caracteriza porque cada uno de sus elementos tiene que
indicar dónde se encuentra el siguiente elemento de la lista (figura 4.1);
O ., Por lo tanto, es una abstracción de la representación por ligas para una
estructura de datos lineal.
una lista encadenada es un TDA que se convierte en una opción
para representar otras estructuras de datos o TDA.

t_
L----LE []!=--* H]-trf-"*[,, Nl
Figura 41.

Cada elemento de la lista se guarda en un nodo que contiene la


información y el valor que indica en dónde se encuentra el siguiente
dato en la lista.

¿Cuál es Ia espec¡ficación lógica del TDA lista


encadenada?

La especificación lógica para el TDA lista encadenada es:

los elementos de una lista se denominan nodos, que almacenan da-


tos sirnplesoesfiuctu¡ados. . i

I¿ esüucturade una liqta es liaeal, esto es, existe un elemgnto llayna-


do "el primero' y otro llamado "el último,; cada elemento üene un
único sucesor y antecesor; cada uno de Ios elementos tiene asignada
, tna rlnica po*iciónsu la lista, esto es,la posición del prirnerelernen-

to es la 1o'la de slr sucesor es 2, etc. Si la tista no está,vacfa, su§ .

elementos tendnín las posiciones l, 2,.., N,donde N es la cantidad


de elementos de la lista.
áCr¡á§ es üa especif !e ae ióm tréqsca del TDfi tista encadenada?

Sólo se muestran algunas operaciones generales que pueden ser


útiles para cualquier aplicación.

METER INICIO LISTA


ENTRADA: la lista y el nuevo elemento
SALIDA: la lista con el nuevo elemento al inicio
PRECONDICIÓN: ninguna
POSTCONDICIÓN: la lista contiene el elemento nuevo al inicio

METER-FINAL* LISTA
ENTRADA: la lista y el nuevo elemento
SALIDA: la lista con el nuevo elemento al final
PRECONDICIÓN: ninguna
POSTCONDICIÓN: la lista contiene al elemento nuevo al final

METER*EN ORDEN ESPECIAL LISTA


ENTRADA: la lista y el nuevo elemento
SALIDA: la lista con el nuevo elemento en el lugar que le corresponde
PRECONDICIÓN: nmguna
POSTCONDICION: la lista contiene al elemento nuevo en el orden que le
corresponde

SACAR-INICIO LISTA
ENTRADA: la lista a la que se va a sacar el elemento
SALIDA: lalista con un elemento menos y, en viejo, el valor que se sacó
PRECONDICION: la lista no está vacía
POSTCONDICION: la lista contiene un elemenro menos (el del inicio)

SACAR_FINAL_LISTA
ENTRADA: la lista de la que se va a sacar el elemento
SALIDA: Ia lista con un elemento menos y. en viejo, el valor que se sacó
PRECONDICIÓN: la lista no está vacía
POSTCONDICIÓN: h lista contiene un elemento menos (el del final)
ffi
SACAR-EN CIAL-LISTA
-ORDEN-ESPE
ENTRADA: la lista de la que se va a sacar el elemento y el elemento que se
desea sacar
la lista con un elemento menos
la lista no estiá vacíay contiene al elemento que se quiere sacar.
la lisla contiene un elemento menos y corresponde al que se sacó

la lista y el elemento por buscar


la lista como estaba y un valor de verdadero si encontró el
elemento en la lista o falso si el elemento no se encuentra en
la lista
PRECONDICIÓN: ninguna
POSTCONDICIÓN: ninguna

ffi%
'e.,d
I
Listas Encadenadas

¿Gómo se ut¡l¡zan ra memoria estática y ¡a dinámica para


representar el TDA lista encadenada?
una lista encadenada está formada por un conjunto de
nodos ligados
entre sí. se denomina nodo de lista encadenada-ar
espacio de memoria
que almacena un elemento de la lista y la
direcciónionde se encuen_
O tra el siguiente elemento de la estructura (figura
4.2).

Figura 4.2. Esquema de,nodo para una lista encadenada.

La lista encadenada puede representarse en memoria


estática utili-
zando un arreglo de nodos o, más común, con
memoria diniímica utilizan-
do nodos encadenados a través de apuntadores.
cualquiera que sea la representación seleccionada debe
existir un
apuntador principal, externo a la estructura, que
almacene ru ¿iiecciJn
del primer elemento de la lista, ya que, a partir
de é1, ,"
resto de los elementos (cada uno guarda lá dirección ";;;;;i
de su sucesor).
La figura 4.3 muestra el esquemu d" oru lista encadenada
en memo-
ria estática y la figura 4.4 erequivalente en memoria
dinámica.

Elemento

Posición del pr imer" elemento = 4

Figura 4.3, Lista encadenada con memoria


estática.
zcómo se puede implementar una lista encadenada en lenguaje c++?

Lista

LFnB-rut----=---ry*_-gL_-ry
I

Figura 4.4. Lista encadenada con memoria dinámica.

cualquier operación que se efectúe sobre una lista encadenada


debe cuidar el correcto encadenamiento de 1os elementos, ya que un
apuntador mal colocado provocará pérdidas en la lista y afectará la
integridad de la estructura.

¿Gómo puede implementar una lista encadenada


en lengua¡e G++7
La implementación de una lista encadenada requiere primero de un
tipo de dato que represente a un nodo que, a su vez, permita agrupar el
valor almacenado y la dirección del siguiente elemento.
Las opciones para esta representación, que ofrece el lenguaje C++,
son a través de un objeto o un registro (struct).
Dado que un nodo sirve para formar una lista, es recomendable que
en cualquier representación seleccionadaparu el nodo, se pueda tener
acceso a los elementos que lo conforman; es decir, los atributos deben
ser públicos.
A continuación se muestran las dos opciones de representación:

class Nodo struct Nodo


{ public: {
tipoinfo info; tipoinfo info;
Nodo* sig; Nodo* sig;
Nodo) { sig = NULL; } Nodo) { sig = NULL; }
Nodo ( tipoinfo dato ) Nodo ( tipoinfo dato )
{ info = dato; sig = ¡¡¡¡77, , { info = datoi sig = ¡¡977. ¡
]; ]:

unavez definido el tipo de dato de los nodos, la representación de


la lista encadenada se especifica con un apuntador al inicio de la lista,
como se muestra a continuación:
class Lista
{ private:
Nodo* inicio;
public:
Lista) { inicio = NIJLL; }
-Lista) { llinstrucciones para liberar los nodos de la lista }
o--^- ll otros métodos, según el diseño
];

¿Guáles'son las situac¡onesr tlpicas de implementación


en una lista encadenada?
Para visualizar las situaciones más comunes de implementación de una
lista encadenada, se analizarán diversos ejemplos.

6ffi Eiemplo
Ejempla f. Agregar un nodo,innrediatamenté'después' del' nodo
apuntado por P en la lista de'la figura 4.5: i

!ntglo
l
I

I
I

ln

Figura 4.5.

En este caso, se puede observar que la secuencia de pasos será:

1. Crear un nuevo nodo,con un apuntador auxiliar,


2.Encadenar el nuevo nodo al siguiente nodo de P.
3. Apuntar el siguiente de P al nuevo nodo.

Esto se puede visualizar como en la figura 4.6:


Ejemplo

(ffi Eiemplo (continúa)

inicio

[ru*
Figura 4.6.

Es muy importante que el paso 2 se realice antes que el paso 3, pues


de lo contrario, se perdería la referencia de todos los nodos que seguían
al nodo apuntado por P.
Las instrucciones equivalentes a este análisis, en lenguaje CIC++,
E
serían:
t¿, g
l. Nodox Q = new Nodo;
2. Q->sig - P->sig; He$
3. P->sig = Q; Lr.s #
Ejemplo 2. Eliminar el nodo que está después del nodo apuntado por ffihs
P en la figura 4.7. L)*5 ff
mss #
tntcro 0s* ffi
q
r.¡i

o
--ffiu
Figura.4.7.

Aqui se puede observar que la secuencia de pasos será:

1. Colocar un apuntador auxiliar en el nodo que se va a borrar.


2. Reacomodar el encadenamiento haciendo un puente del nodo
apuntado por P al que ahora será su siguiente.
3. Liberar el nodo que se desea borrar.

Esto se puede visualizar en la figura 4.8:


Iistas Encadenadas

(s Eiemplo (continúa)

tntcto

o--

Figura 4.8. I

Al igual que en el caso anterior, es importante que se siga la secuen-


cia mencionada; si no es así, se perdeía la referencia al nodo que se
quiere borrar.
Las instrucciones equivalentes a este análisis, en lenguaje C/C++,
serían:

L Nodo *Q = P-> sig ;


2. P -> sig = 9-> srg ; ll otambién P ->sig - P ->sig->szg,'
3. delete Q ;
Ejemplo 3. Desplegar la información contenida en una lista.
Puesto que se requiere recoffer todos los nodos de la lista desple-
gándolos, será importartte utllizar un apuntador auxiliar que permita
hacer de la siguiente forma los movimientos sobre la lista:
l. Colocar un apuntador auxiliar al inicio de Ia lista.
2. Desplegar la información del nodo.
3. Mover el apuntador auxiliar hacia el siguiente nodo.
4. Repetir los pasos 2 y 3 hasta que se termine la lista.
Estos pasos se pueden traducir, en términos del lenguaje C/C++, de
la siguiente manera:
Nodo *p;
P = inicio ;
while (p != NULL)
{ cout << p -> info ;
p=p_>sig;
]
Esta estructura de ciclo que recorre todos los nodos puede ser útil
para otras aplicaciones donde se requiera visitar todos los nodos de la
Ii sta.

Ejemplo 4.Elíminar el nodo señalado por el apuntador P en la lista de


lafiglura 4.9.
ZCúales son las uariantes de una lista encadenada?

Eiemplo (continúa)
@
inicio

Figura 4.9.

¿Se puede eliminar ejecutando sólo la instrucción delete P;? Obvia-


mente s( pero esta acción dejaría "volando" el resto de los nodos de la
lista. Es importante observar que, primero, se debe "hacer el puente"
del nodo anterior al apuntado por P, al siguiente nodo del señalado por
P. Sin embargo, para llegar al nodo anterior al apuntado por P, se re-
querirá de un apuntador auxiliar que recorra la lista hasta llegar a ese
nodo y, posteriormente, realizar las instrucciones ya conocidas. El có-
digo que realiza esta acción es:

Nodo *q;
q = inicio;
while (q->sig!=P) /l este ciclo recorre al apuntador q hasta que esté en el nodo
q = q->sig; // anterior al que se deseaborrar
e->sig=p-rtrf ' // esta instrucción "hace el puente"
delete P;

Los casos que hemos analizado representan todas las situaciones tí-
picas con las que se puede enfrentar un programador al trabajar con
una lista; si se comprenden, es fácil extrapolar las situaciones con di-
ferentes variantes.

¿Guáles son las variantes de una lista encadenada?


Si se consideran las caracteísticas de una lista encadenada es posible
generar diversas variantes de gran utilidad. Entre las más comunes se
encuentran:

. Listas encadenadas circulares


. Listas doblemente encadenadas
. Listas doblemente encadenadas circulares
. Listas con múltiples encadenamientos
Listas Encadenadas

Í,.1.,

:i
iiú,
!r'-l
¿Gómo es una lista encadenada circular?
li,.,

L
La lista encadenada circular es una ligera variante de la lista encadena-
í1i da lineal; se obtiene al considerar el "primer" nodo de la lista como el zu-
t{
cesor del último nodo, almacenando la dirección del primer elemento en
,t]l el campo de dirección delúltimo, en lugar de almacenar la dirección nu-
i
It, la. Al realizar esta modificación se genera automáticamente un círculo'
donde realmente ya no existe ni el primero ni un último elemento.

Características generales de una list¿ circular


. Es necesario mantener un apuntador general a la estructura (Lista)'
aunque ya no apunte obligatoriamente al primer elemento'
. La dirección nula no existe en la lista, excepto cuando la lista está
vacía.
. Si la lista contiene un solo elemento, el campo de dirección
apuntará a ese mismo nodo.
. Como la lista es un círculo, es posible llegar a cualquier nodo de la
lista a partir de cualquiera de sus nodos, lo que es imposible en una
lista lineal (figura 4.10).

Lista

Figura 4fO. Esquema de una lista encadenada circular.

A continuación se muestra el código en lenguaje C++ de las instruc-


ciones que sirven para desplegaf la información de una lista circular:

if (inicio != NULL)
{P=inicio;
do
{ cout << P -> info ;
P=P-¡slg,'
] while (P != inicio) )
Observe la importancia de validar el caso extremo de la lista vacía, y
de controlar con un ciclo do...white el desplegado de la información-
iCómo es una lista doblemente encadenada?

¿Gómo es una lista doblemente encadenada?


Estas listas presentan una variación más sustancial que la anterior. Este
tipo de listas se utilizan cuando la aplicación sobre una lista encadena-
da debe recorer la lista en ambos sentidos, algo imposible de realizar
en una lista encadenada lineal y, aunque es posible hacerlo en una
lista circular, resulta muy ineficiente.

Características generales de una lista doblemente encadenada


. Se requiere mantener un apuntador general a la esffuctura (Lista), a
pesar de que los nodos conocen a su predecesor y a su sucesor. No
es necesario que lista apunte al primer elemento de la lista, ya que
siempre se podrá llegar a é1 (figura 4.lI).
. Cada nodo requiere almacenar, además del elemento, dos direccio-
nes: la del predecesor y la del sucesor.
. El movimiento de apuntadores puede hacerse en ambas direcciones.

Lista
I

V
ffiI ryT--Tq-> ffi*T--TW->W-T-TH
I
" t . {<--t*L__IJ<--fu^I_lJ<--ffi1__ÍJ

Figura 4f1. Esquerna de una lista doblemente encadenada.

Los nodos de una lista doblemente encadenada se definiían de la


siguiente manera en el lenguaje C++:
-. o
class Nodo
{ public:
tipoinfo info;
Nodo xsig, *ant;
Nodo) { sig = ant = NULL; }
];
La eliminación del nodo señalado por etr apuntador P en una lista
doblemente encadenada, requerirá de las siguientes instrucciones en
lenguaje C++:

P->ant->sig = P->sig;
P->sig->ant = P-)ant;
delete P;
[¡stas Encadenadas

La inserción de un nodo después del nodo señalado por el apunta-


dor P en una lista doblemente encadenada, requeirá de las siguientes
instrucciones en lenguaje C++:

Nodo xnuevo = new Nodo;


nuevo->sig - P->sig;
o' "* nuevo->ant = P->ant.
P->sig->ant = nuevo;
P->sig = rttt€voi

¿Gómo es una lista doblemente encadenada circular?


r En este tipo de listas, cada nodo almacena la dirección de su sucesor y
f
ü de su predecesor. No existe un inicio ni un final.
tl

Características generales de una lista circular doblemente enca-


denada circular
. Se requiere mantener un apuntador general a la estructura (Lista),
a pesar de que los nodos conocen a su predecesor y a su sucesor.
Este apuntador puede guardar la dirección de cualquier nodo de
la lista (figura 4.12).
. Cada nodo requiere almacenar, además del elemento, dos direc-
ciones (la del predecesor y la del sucesor).
. La dirección nula no existe en la lista, excepto cuando está vacía.
. Si la lista contiene un elemento, el campo de dirección apuntará a
ese mismo nodo.
. El movimiento de apuntadores puede hacerse en ambas direcciones'

Figura 4.'12. Esquema de una l¡sta doblemente encadenada circulan


Ejercicios

¿Gómo es una lista con múltiples encadenamientos?


Esta variante permite mezclar listas que
contienen diferentes elemen-
tos' to anterior se logra cuando los nodos
almacenan la dirección de
otra lista (figura 4.13).,Estas mezclas pueden
llegar a ser tan comple-
jas como la aplicación lo requiera.

Lista
v
-

ffi-ffi ffi
-T- M
ffi
Figura zlf3. Esquéma de una lista con múltiples
encadenamientos.

EJEBCICIOS
,. ." ."....
Resuelva cada uno de los siguientes ejercicios
sobre listas encadena_
das' considere que cada uno debe prolramarse
como si fuera un mé-
rodo de la crase Lista. para esto, to*.
á;;;;h d"ffi;n
¿" lu.lu_
se Lista explicada previament". t;r-;lb i;ffi.láo,J; ¿..
I. Escriba la implemenración de un método
llamado: MIEMBRO_DE,
el cual recibe un daro y verifique si existe
lu ii.iu. Er'método re_
gresará un I si el elemento se encuentra "n
dentro ¿. u ririu o un 0, en
caso contrario.
Listas Encadenadas

2.Escribalaimplementacióndeunmétodollamado:INDICE'elcual
recibeundatoyregresalaposicióndondeseubicalaprimeraocu-
dío. considere que el primer elemento de la lista
rrencia de dicho
Seencuentraenlaposibión1yasísucesivamente.Encasodefloglll
un 0'
contrarse el dato, el método deberá regresar

3.EscribalaimplementacióndeunmétodollamadoCUENTA-DAIOS,
elcualrecibeundatoygeneracomoresultadolacantidaddeveces
queexisteeldato"ntuti*ta.Elmétodonomodificalalistaysedebe
elementos'
considerar que la lista puede o no tener

4.EscribalaimplementacióndeunmétodollamadoCoPIA,quesirva
pafagener*"o*salidaunacopiadelalista.Elmétodo,alejecu-
para la lista que será una copia'
tarse, debe generar nuevos nodos

5.EscribalaimplementacióndeunmétododenominadoIMPARES,
"q*""ri-inalosnodosqueseencuentrenenposicionesimparesde
al primer elemento' al tercero' al quinto
y
la lista; es decir, borrará
que Ia lista no está vacía'
así sucesivamente. Se puede suponer

6. A continuación se describe un método para la clase lista' Implernén-


telo en C++.

MEZCLA listas'
elementos de dos
FUNCIONAMIENTO: une, en fornÍa alterna,'los
ENTRADA: dos listas encadenadas, Ll'Y L2'
la lista L1 contiene los elementos de las dos listas'
SALIDA:
acomodados de manera alterna'
PRECONDICIÓN: las listas existen y no estiín vacías'
la lista L2 queda vacíay la L1 queda con los
elementos
POSTCONDICIÓN:
en forma altema.

T.EscribalaimplementacióndeunmétodollamadoINVIERTE,que
la lista, de tal forma
invertirá el orden original de 1o§ elementos en
primero, el penúltimo será el
ür" "i?frr-" "t"-"ri* será ahora el elúltimo' Considere que la
,"g,rndo,y así hasta que el primero sea
ii;";;" ár,a ru"áy.q,r" no se construiráwanueva, sólo se inverti-
rá el orden de loJ áta'.""ot de la lista original'

g. A continuación se describe un método paralaclase Lista' Implemén-


telo en C++.
flutbeualuación

SPLIT .: I

FIINCIONAMIENTO: divide los elernentos de una lista, de rat forma, qqe se


convierte en dos nuevas listas. Los elementos de la pri-
mera lista serián los que se encontraban en las pesiciones
1, 3, 5 ... de la lista original y la segunda tendrá los de-
más elementos. No crea dos nuevas listas, sólo divide la
original.
ENTRADA: una lista encadenada (L).
SALIDA: dos listas (IMPARES y PARES).
PRECONDICIÓN: la Lista existe.
POSTCONDICIÓN: la lista L queda sin elementos. Las listas PARES e IMPA'
RES co.ltienen a los elementos de la lista original, de
acuerdo con su posición.

Frr-r- R UTO E U R L U R C I Ó N' q I


I
t
L--- ¡¡r{

1. Suponga que se tiene la siguiehte lista encadenada (representada en


, un arreglo de nodos): ., ,, ,, , 1

,INFO

t1l
fzl
t3l Valor del apuntador
e*enno a la lista=4
l4l
t5l
t6I
17l

tB1
--"-- --o

Si se elimina de la lista el nodo que contiene a ALEX como infor-


mación, ¿cuálde los enunciados es verdadero? ,: ,

a) El nodo que guarda a ADRIANA b) El nodo que guarda a FRANCISCO


ahora tendrá como valor en SIG la ahora tendrá como valor en SIG la
posición 5. posición 7.

c) El nodo que guarda a ALEX ahora d) El nodo que guarda a ADRIANA


tendrá como valor en SIG la posi- ahora tendrá como valor en SIG la
ción 1. posición 7.

e) El nodo que guarda a ¡ORGB atrora


tendrá como valor en SIG la posi-
ción 4.
Listas Encadenadas

2. ¿Cuál de los códigos une dos listas encadenadas que ya tienen valores
para forrnar una sola lista? Utilice,la siguiente declaración:

struct Nodo.
xsig;
{ int valor; Nodo };
Nodo *aux,
*listql, *lista2; ll donde listal y lisn2 son apuntctdores al primer nodo de cada lista.
]-*""-

a) aux = listal; b) aux = listal;


while (aux != NULL) while (aux->sig != NULL)
antx = aux->sig; aux = aux->sig;
aux->sig = lista2; aux->sig = lista2;

c) aux = listal; d) aux = lista2;


while (aux != lista2) while (aux-,>sig != NULL)
aux = aux->stg; ' aux = aux->sig;
annc = lista2; aux->sig = lista2;

e) Ninguna de las anteriores

3. Dada la lista doblemente encadenada circular, ¿cuál es el dato que


se despliega en pantalla al ejecutar la siguiente instrucción?

c out<< li sta-> si g - > ant- > ant - >info ;

Lista

b)B c)c d)D e)E

También podría gustarte