Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

Embed Size (px)

Citation preview

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    1/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 1

    APUNTES SOBRE MEMORIA DINAMICA Y PUNTEROS

    Una estructura se dice dinmicasi su tamao cambia en tiempo de ejecucindel programa. De los tipos de datos vistos: struct,int, char , bool, float, double,no permiten construirestructuras dinmicas. El espacio de memoria utilizadose reserva cuando comienza la ejecucin del bloque donde estn declaradas yeste espacio no vara en toda la ejecucin del bloque.

    El tipo puntero

    Un puntero es una variable que apunta o referencia a una ubicacin dememoriaen la cual hay datos. El contenido del puntero es la direccinde esaubicacin. Para entender qu es un puntero veremos primero cmo sealmacenan los datos en un computador. La memoria de un computador est

    compuesta por unidades bsicas llamadas bits. Cada bit slo puede tomar dosvalores, normalmente denominados alto y bajo, 1 y 0. Pero trabajar con bitsno es prctico, y por eso se agrupan. Cada grupo de 8 bits forma un byteuocteto. En realidad el microprocesador, y por lo tanto nuestro programa, slopuede manejar directamente bytes o grupos de dos o cuatro bytes. Paraacceder a los bits hay que acceder antes a los bytes.

    Cada byte de la memoria de un computador tiene una direccin, llamadadireccin de memoria.

    Los microprocesadores trabajan con una unidad bsica de informacin, a la

    que se denomina palabra (en ingls Word). Dependiendo del tipo demicroprocesador una palabra puede estar compuesta por uno, dos, cuatro,ocho o diecisis bytes. Hablaremos en estos casos de plataformas de 8, 16, 32,64 128 bits. Se habla indistintamente de direcciones de memoria, aunque laspalabras sean de distinta longitud. Cada direccin de memoria contienesiempre un byte. Lo que suceder cuando las palabras sean, por ejemplo, de32 bits es que accederemos a posiciones de memoria que sern mltiplos de 4.

    Por otra parte, la mayor parte de los objetos que usamos en nuestrosprogramas no caben en una direccin de memoria. La solucin utilizada paramanejar objetos que ocupen ms de un byte es usar posiciones de memoria

    correlativas. De este modo, la direccin de un objeto es la direccin dememoria de la primera posicin que contiene ese objeto. Dicho de otro modo,si para almacenar un objeto se precisan cuatro bytes, y la direccin dememoria de la primera posicin es n, el objeto ocupar las posiciones desde na n+3, y la direccin del objeto ser, tambin, n.

    Todo esto sucede en el interior de la mquina, y nos importa relativamentepoco. Pero podemos saber qu tipo de plataforma estamos usandoaveriguando el tamao del tipo int, y para ello hay que usar el operadorsizeof, por ejemplo:

    cout

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    2/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 2

    Ahora veamos cmo funcionan los punteros. Un puntero es un tipo especial deobjeto que contiene, ni ms ni menos que, la direccin de memoria de unobjeto. Por supuesto, almacenada a partir de esa direccin de memoria puede

    haber cualquier clase de objeto: un char, un int, un float, un array, unaestructura, una funcin u otro puntero. Seremos nosotros los responsables dedecidir ese contenido, al declarar el puntero.

    De hecho, podramos decir que existen tantos tipos diferentes de punteroscomo tipos de objetos puedan ser referenciados mediante punteros. Sitenemos esto en cuenta, los punteros que apunten a tipos de objetos distintos,sern tipos diferentes. Por ejemplo, no podemos asignar a un puntero a charel valor de un puntero a int.

    Intentemos ver con mayor claridad el funcionamiento de los punteros.

    Podemos considerar la memoria del ordenador como un gran array, de modoque podemos acceder a cada celda de memoria a travs de un ndice. Podemosconsiderar que la primera posicin del array es la 0 celda[0].

    Si usamos una variable para almacenar el ndice, por ejemplo, indice=0,entonces celda[0] == celda[indice]. Finalmente, si prescindimos de la notacinde los arrays, podemos ver que el ndice se comporta exactamente igual queun puntero.

    El puntero indicepodra tener por ejemplo, el valor 3, en ese caso, el valorapuntado por indicetendra el valor 'val3'. Las celdas de memoria tienen unaexistencia fsica, es decir son algo real y existirn siempre,

    array = ARREGLO

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    3/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 3

    independientemente del valor del puntero. Existirn incluso si no existe elpuntero.

    De forma recproca, la existencia o no existencia de un puntero no implica laexistencia o la inexistencia del objeto. De la misma forma que el hecho de nosealar a un rbol, no implica la inexistencia del rbol. Algo ms oscuro es sitenemos un puntero para rboles, que no est sealando a un rbol. Unpuntero de ese tipo no tendra uso si estamos en medio del mar: tener esepuntero no crea rboles de forma automtica cuando sealemos con l. Es unpuntero, no una varita mgica.

    Del mismo modo, el valor de la direccin que contiene un puntero no implicaque esa direccin sea vlida, en el sentido de que no tiene por qu contener ladireccin de un objeto del tipo especificado por el puntero.

    Supongamos que tenemos un mapa en la pared, y supongamos tambin queexisten diferentes tipos de punteros lser para sealar diferentes tipos depuntos en el mapa (ya s que esto suena raro, pero usemos la imaginacin).Creamos un puntero para sealar ciudades. Nada ms crearlo (o encenderlo),el puntero sealar a cualquier sitio, podra sealar incluso a un punto fueradel mapa. En general, daremos por sentado que una vez creado, el puntero notiene por qu apuntar a una ciudad, y aunque apunte al mapa, podra estarsealando a un mar o a un ro.

    Con los punteros en C++ ocurre lo mismo. El valor inicial del puntero, cuandose declara, podra estar fuera del mapa, es decir, contener direcciones dememoria que no existen. Pero, incluso sealando a un punto de la memoria, esmuy probable que no seale a un objeto del tipo adecuado. Debemosconsiderar esto como el caso ms probable, y no usar jamsun puntero queno haya sido inicializado correctamente.

    Dentro del array de celdas de memoria existirn zonas que contendrnprogramas y datos, tanto del usuario como del propio sistema operativo o deotros programas, el sistema operativo se encarga de gestionar esa memoria,prohibiendo o protegiendo determinadas zonas.

    Pero el propio puntero, como objeto que es, tambin se almacenar en

    memoria, y por lo tanto, tambin tendr una direccin de memoria. Cuandodeclaramos un puntero estaremos reservando la memoria necesaria paraalmacenarlo, aunque, como pasa con el resto del los objetos, el contenido deesa memoria contendr basura.

    En principio, debemos asignar a un puntero, o bien la direccin de un objetoexistente, o bien la de uno creado explcitamente durante la ejecucin delprograma o un valor conocido que indique que no seala a ningn objeto, esdecir el valor 0. El sistema operativo, cuanto ms avanzado es, mejor suelecontrolar la memoria. Ese control se traduce en impedir el acceso adeterminadas direcciones reservadas por el sistema.

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    4/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 4

    Declaracin de punteros:

    Los punteros se declaran igual que el resto de los objetos, pero precediendo el

    identificador con un asterisco (*).

    Sintaxis:

    *;

    Ejemplos:

    i nt *pEnt er o;char *pCaract er ;st r uct st Punt o *pPunt o;

    Los punteros slo pueden apuntar a objetos de un tipo determinado, en elejemplo,pEnteroslo puede apuntar a un objeto de tipo int.

    La forma:

    * ;

    Con el (*) junto al tipo, en lugar de junto al identificador del objeto, tambinest permitida. De hecho, tambin es legal la forma:

    * ;

    Veamos algunos matices. Tomemos el primer ejemplo:

    i nt *pEnt er o;

    Equivale a:

    i nt * pEnt er o;

    Otro detalle importante es que, aunque las tres formas de situar el asterisco enla declaracin son equivalentes, algunas de ellas pueden inducirnos a error,sobre todo si se declaran varios objetos en la misma lnea:

    i nt* x, y;

    En este caso,xes un puntero a int, pero yno es ms que un objeto de tipoint. Colocar el asterisco junto al tipo puede que indique ms claramente queestamos declarando un puntero, pero hay que tener en cuenta que slo afectaal primer objeto declarado, si quisiramos declarar ambos objetos comopunteros a inttendremos que hacerlo de otro modo:

    i nt * x, *y;/ / O:

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    5/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 5

    i nt *x, *y;/ / O:i nt * x;i nt * y;

    Los punteros apuntan a objetos, por lo tanto, lo primero que tenemos quesaber hacer con nuestros punteros es asignarles direcciones de memoriavlidas de objetos. Para averiguar la direccin de memoria de cualquier objetousaremos el operador de direccin (&), que leeremos como "direccin de".

    Por supuesto, los tipos tienen que ser "compatibles", no podemos almacenar ladireccin de un objeto de tipo charen un puntero de tipo int.

    Por ejemplo:

    i nt A;i nt *pA;

    pA = &A;

    Segn este ejemplo,pAes un puntero a intque apunta a la direccin donde sealmacena el valor del enteroA.

    Objeto apuntado por un puntero

    La operacin contraria es obtener el objeto referenciado por un puntero, con el

    fin de manipularlo, ya sea modificando su valor u obteniendo el valor actual.

    Para manipular el objeto apuntado por un puntero usaremos el operador deindireccin, que es un asterisco (*).

    En C++ es muy habitual que el mismo smbolo se use para varias cosasdiferentes, este es el caso del asterisco, que se usa como operador demultiplicacin, para la declaracin de punteros y, como vemos ahora, comooperador de indireccin. Como operador de indireccin slo est permitidousarlo con punteros, y podemos leerlo como "objeto apuntado por".

    Por ejemplo:

    i nt *pEnt er o;i nt x = 10;i nt y;

    pEnter o = &y;*pEnt ero = x; / / ( 1)

    En (1) asignamos al objeto apuntado porpEnteroen valor del objetox. ComopEntero apunta al objeto y, esta sentencia equivale (segn la secuencia delprograma), a asignar a yel valor dex.

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    6/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 6

    Diferencia entre punteros y otros objetos

    Debemos tener muy claro, en el ejemplo anterior, quepEnteroes un objeto deltipo "puntero a int", pero que *pEntero NOes un objeto de tipo int, sino unaexpresin.

    Por qu decimos esto?

    Pues porque, como pasa con todos los objetos en C++, cuando se declaranslo se reserva espacio para almacenarlos, pero no se asigna ningn valorinicial, (recuerda que nuestro puntero para rboles no crea rbol cada vez quesealemos con l). El contenido del objeto permanecer sin cambios, de modoque el valor inicial del puntero ser aleatorio e indeterminado. Debemossuponer que contiene una direccin no vlida.

    SipEnteroapunta a un objeto de tipo int, *pEntero ser el contenido de eseobjeto, pero no olvides que *pEntero es un operador aplicado a un objeto detipo "puntero a int". Es decir, *pEntero es una expresin, no un objeto.

    Declarar un puntero no crear un objeto del tipo al que apunta. Por ejemplo:int *pEntero; no crea un objeto de tipo inten memoria. Lo que crea es unobjeto quepuedecontener la direccin de memoria de un entero.

    Podemos decir que existe fsicamente un objeto pEntero, y tambin que eseobjetopuede(aunque esto no es siempre cierto) contener la direccin de un

    objeto de tipo int.

    Como todos los objetos, los punteros tambin contienen "basura" cuando sondeclarados. Es costumbre dar valores iniciales nulos a los punteros que noapuntan a ningn sitio concreto:

    i nt *pEnt er o = 0; / / Tambi n podemos asi gnar el val or NULLchar *pCaract er = 0;

    NULL es una constante, que est definida como cero en varios ficheros decabecera, como "cstdio" o "iostream", y normalmente vale 0L. Sin embargo,hay muchos textos que recomiendan usar el valor 0 para asignar a punteros

    nulos, al menos en C++.

    Correspondencia entre a r r a y s y punteros

    En muchos aspectos, existe una equivalencia entre arrays y punteros. Dehecho, cuando declaramos un arrayestamos haciendo varias cosas a la vez:

    Declaramos un puntero del mismo tipo que los elementos del array.

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    7/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 7

    Reservamos memoria para todos los elementos del array. Los elementosde un arrayse almacenan internamente en la memoria del ordenador enposiciones consecutivas.

    Se inicializa el puntero de modo que apunte al primer elemento delarray.

    Las diferencias entre un arrayy un puntero son dos:

    Que el identificador de un array se comporta como un punteroconstante, es decir, no podemos hacer que apunte a otra direccin dememoria.

    Que el compilador asocia, de forma automtica, una zona de memoriapara los elementos del array, cosa que no hace para los elementos

    apuntados por un puntero corriente.

    Ejemplo:

    i nt vector[ 10] ;i nt *punt er o;

    punt er o = vect or; / * Equi val e a punt er o = &vect or[ 0] ; ( 1)est o se l ee como "di r ecci n del pr i mer el ement o de

    vector" */( *punt er o)++; / * Equi val e a vect or [ 0] ++; ( 2) */puntero++; / / puntero equi val e a asi gnar a punt ero=punt ero+1 ( 3)

    En (1) se asigna a puntero la direccin del array, o ms exactamente, ladireccin del primer elemento del array vector.

    En (2) se incrementa el contenido de la memoria apuntada porpuntero, que esvector[0].

    En (3) se incrementa el puntero, esto significa que apuntar a la posicin dememoria del siguiente elemento int, y no a la siguiente posicin de memoria.Es decir, el puntero no se incrementar en una unidad, como tal vez seralgico esperar, sino en la longitud de un int, ya que puntero apunta a unobjeto de tipo int.

    Anlogamente, la operacin:

    punter o = punter o + 7;

    No incrementar la direccin de memoria almacenada en puntero en sieteposiciones, sino en 7*sizeof(int).

    De forma anloga, el siguiente ejemplo tambin es vlido:

    i nt vect or[ 10] ;

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    8/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 8

    i nt *punt er o;

    puntero = &vect or[ 5] ;puntero[ - 2] = punt ero[ 2] = 100;

    Evidentemente, nunca podremos usar un ndice negativo con un array, ya queestaramos accediendo a una zona de memoria que no pertenece al array, peroeso no tiene por qu ser cierto con punteros.

    En este ltimo ejemplo,punteroapunta al sexto elemento de vector, de modoque puntero[-2] apunta al cuarto, es decir, vector[3] y puntero[2] apunta aloctavo, es decir, vector[7].

    Operaciones con punteros

    La aritmtica de punteros es limitada, pero en muchos aspectos muyinteresante; y aunque no son muchas las operaciones que se pueden hacer conlos punteros, cada una tiene sus peculiaridades.

    Asignacin

    Ya hemos visto cmo asignar a un puntero la direccin de una variable.Tambin podemos asignar un puntero a otro, esto har que los dos apunten ala misma direccin de memoria:

    i nt *q, *p;

    i nt a;

    q = &a; / * q apunt a a l a di r ecci n de a */p = q; / * p apunt a al mi smo si t i o, es deci r ,

    a l a di r ecci n de a */

    Slo hay un caso especial en la asignacin de punteros, y es cuando se asignael valor cero. Este es el nico valor que se puede asignar a cualquier puntero,independientemente del tipo de objeto al que apunte.

    Operaciones aritmticas

    Podemos distinguir dos tipos de operaciones aritmticas con punteros. En unode los tipos uno de los operando es un puntero, y el otro un entero. En el otrotipo, ambos operando son punteros.

    Ya hemos visto ejemplos del primer caso. Cada unidad entera que se suma oresta al puntero hace que este apunte a la direccin del siguiente objeto o alanterior, respectivamente, del mismo tipo.

    El valor del entero, por lo tanto, no se interpreta como posiciones de memoriafsica, sino como posiciones de objetos del tipo al que apunta el puntero.

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    9/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 9

    Por ejemplo, si sumamos el valor 2 a un puntero a int, y el tipo int ocupacuatro bytes, el puntero apuntar a la direccin ocho bytes mayor a la original.Si se tratase de un puntero a char, el puntero avanzar dos posiciones dememoria.

    Las restas con enteros operan de modo anlogo.

    Con este tipo de operaciones podemos usar los operadores de suma, resta,preincremento, postincremento, predecremento y postdecremento. Adems,podemos combinar los operadores de suma y resta con los de asignacin: +=y -=.

    En cuanto al otro tipo de operaciones aritmticas, slo est permitida la resta,ya que la suma de punteros no tiene sentido. Si la suma o resta de un puntero

    y un entero da como resultado un puntero, la resta de dos punteros dar comoresultado, lgicamente, un entero. Veamos un ejemplo:

    i nt vect or[ 10] ;i nt *p, *q;

    p = vector ; / * Equi val e a p = &vector [ 0] ; */q = &vector[ 4] ; / * apunt amos al 5 el ement o */cout

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    10/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 10

    Usaremos estos punteros en situaciones donde podemos referirnos a distintostipos de objetos, ya que podemos hacer que apunten a objetos de cualquiertipo.

    Por supuesto, para eso tendremos que hacer un castingcon punteros, sintaxis:

    ( *)

    Por ejemplo:

    #i ncl ude usi ng namespace st d;

    i nt main() {char cadena[10] = "Hol a";

    char *c;i nt *n;voi d *v;

    c = cadena; / / c apunta a cadenan = ( i nt *) cadena; / / n tambi n apunta a cadenav = ( voi d *) cadena; / / v t ambi ncout

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    11/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 11

    st r uct st Est r uct ur a {i nt a, b;

    } est r uct ur a, *e;

    i nt main() {est r uct ur a. a = 10;est r uct ur a. b = 32;e = &est r uct ur a;

    cout

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    12/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 12

    Aparentemente, y en la mayora de los casos, cadena1 y cadena2 sonequivalentes, sin embargo hay operaciones que estn prohibidas con losarrays, ya que son punteros constantes.

    Apuntadores y Funciones:

    Cuando C pasa argumentos a funciones, los pasa por valor, es decir, si elparmetro es modificado dentro de la funcin, una vez que termina la funcinel valor pasado de la variable permanece inalterado.

    Hay muchos casos que se quiere alterar el argumento pasado a la funcin yrecibir el nuevo valor una vez que la funcin ha terminado. Para hacer loanterior se debe usar una llamada por referencia, en C se puede simularpasando un puntero al argumento. Con esto se provoca que la computadora

    pase la direccin del argumento a la funcin.

    Para entender mejor lo anterior consideremos la funcin swap() queintercambia el valor de dos argumentos enteros:

    voi d swap( i nt *px, i nt *py);mai n(){i nt x, y;x = 10;y = 20;pr i nt f ( " x=%d\ t y=%d\ n", x, y) ;

    swap( &x, &y) ;pr i nt f ( " x=%d\ t y=%d\ n", x, y) ;}voi d swap( i nt *px, i nt *py){i nt t emp;t emp = *px; / * guar da el val or de l a di r ecci n x */*px = *py; / * pone y en x */*py = t emp; / * pone x en y */}

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    13/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 13

    Objetos dinmicos

    El uso principal y ms potente de los punteros es el manejo de la memoriadinmica.

    La memoria se clasifica en muchas categoras, por ahora nos centraremos enalgunas de ellas. Cuando se ejecuta un programa, el sistema operativo reservauna zona de memoria para el cdigo o instrucciones del programa y otra paralos objetos que se usan durante la ejecucin. A menudo estas zonas son lamisma, y componen lo que se denomina memoria local. Tambin hay otraszonas de memoria, como la pila, que se usa, entre otras cosas, paraintercambiar datos entre las funciones. El resto, la memoria que no se usa porningn programa es lo que se conoce como almacenamiento libre o free store.Nuestro programa puede hacer uso de esa memoria durante la ejecucin, de

    modo que la cantidad de espacio de memoria usado por el programa no estlimitada por el diseo ni por las declaraciones de objetos realizadas en elcdigo fuente. Por eso se denomina a este tipo, memoria dinmica, ya quetanto la cantidad de memoria como su uso se deciden durante la ejecucin, yen general, cambia a lo largo del tiempo, de forma dinmica. Para ello,normalmente se usar memoria del montn, y no se llama as porque sea depeor calidad, sino porque suele haber un buen montn de memoria de estetipo.

    C++ dispone de dos operadores para manejar (reservar y liberar) la memoriadinmica, son newy delete.

    Reserva de memoria

    new devuelve un puntero de tipo void *, lo que significa que sepuede asignar a cualquier tipo de puntero. Convierte automticamente elpuntero devuelto al tipo adecuado, por lo que el programador no tiene quepreocuparse de hacer la conversin de forma explcita.

    char *p;p = new char ; / / r eser va espaci o para un carcter

    El operador new tambin se encarga de averiguar cul es el tamao en bytes

    del tipo de datos para el cual se desea reservar memoria (recordemos que lacardinalidad de un tipo nos permite saber la memoria necesaria para sualmacenamiento). Observar en el ejemplo anterior que se indica el que sequiere reservar memoria para un dato de tipo char y no cual es el tamao enbytes que se quiere reservar.

    Tras una llamada con xito, new devuelve un puntero al primer bytede la regin de memoria dispuesta del montn. Si no hay suficiente memorialibre para satisfacer la peticin, se produce un fallo de asignacin y newdevuelve un NULL.

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    14/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 14

    Nota: cuando se reserva memoria para una variable de ese tipo se indica eltipo de datos de la variable annima (a la que apunta el puntero) y no elnombre del tipo puntero.

    t ypedef char *TPChar;TPChar p;p = new char ; / / Corr ectop = new TPChar ; / / I NCORRECTO

    Liberacin de memoria

    El operador delete es complementario de new. Una vez que la memoriaha sido liberada, puede ser reutilizada en una posterior llamada a new.

    El prototipo de delete es:

    del ete ;

    Aqu, p es un puntero a memoria que ha sido previamente asignado con new.Por ejemplo:

    char *p;p = new char; / / r eser va espaci o para un car cterdel et e p; / / l i ber a l a memori a pr evi ament e r eser vada

    Hay una regla de oro cuando se usa memoria dinmica: toda la memoria quese reserve durante el programa hay que liberarla antes de salir del programa.No seguir esta regla es una actitud muy irresponsable, y en la mayor parte delos casos tiene consecuencias desastrosas. No confes de lo que diga elcompilador, de que estas variables se liberan solas al terminar el programa, no

    siempre es verdad.

    Ejemplo:

    i nt main( ){

    i nt *a;

    a = new i nt ; / / vari abl e di nmi ca*a = 10;a = new i nt ; / / nueva vari abl e di nmi ca,

    / / se pi er de el punt er o a l a ant er i or*a = 20;

    NOTA: Es muy importante no llamar NUNCA a deletecon un argumento no vlido; se

    daar el Sistema de asignacin. El operador deletep NO asigna el valor nulo alpuntero pdespus de liberar la memoria a la que ste apuntaba.

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    15/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 15

    del et e a; / / sl o l i ber amos l a l t i ma r eser vadar et ur n 0;

    }

    En este ejemplo vemos cmo es imposible liberar la primera reserva dememoria dinmica. Lo correcto, si no la necesitbamos habra sido liberarlaantes de reservar un nuevo bloque usando el mismo puntero, y si lanecesitamos, habra que guardar su direccin, por ejemplo usando otropuntero.

    Arreglos Dinmicos

    El manejo de arreglos de forma esttica conlleva muchas veces a desperdiciode la memoria cuando se declara un arreglo muy grande para cantidad dedatos que se va a manejar o en caso contrario quedarse corto en la declaraciny no contar con espacio para almacenar la data completa. Es por ello que losarreglos dinmicos vienen a ofrecer una posible solucin a este problema.

    Para manejar un arreglo de forma dinmica en C++ se requiere declarar einicializar un puntero al tipo de dato que deseo utilizar, luego proceder asolicitar como entrada de datos en tiempo de ejecucin, el tamao del arreglopara reservar el espacio correspondiente. La manipulacin posterior es similara la de un arreglo que se ha declarado de forma esttica.

    En el siguiente ejemplo se maneja de forma dinmica un vector de nmerosaleatorios:

    i nt *dat os; / / punt er o a i ntcout Num;dat os =new i nt [ Num] ; / / Reserva de memor i a para el arr egl oi f ( dat os ! = NULL){f or( i nt i =0; i

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    16/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 16

    Sabemos que un arreglo se comporta muy parecido a un puntero, por lo tantoTabla apunta al primer elemento de un arreglo de punteros:

    int n = 134;t abl a = new int* [n ] ;

    Cada elemento del arreglo anterior puede ser a su vez un puntero al primerelemento de otro arreglo:

    int m = 231;for( int i = 0; i < n; i ++)

    t abl a[ i ] = new int[ m] ;

    Ahora tabla apunta a un arreglo de dimensiones nxm, podemos acceder a cadaelemento de la misma forma que accedemos a arreglos normales:

    t abl a[ 21] [ 33] = 123;

    Una de las grandes diferencias con los arreglos normales es que antes definalizar el programa es necesario liberar la memoria dinmica usada, primerola asociada a cada elemento de Tabla[i]:

    for( int i = 0; i < n; i ++) delete[ ] t abl a[ i ] ;

    y despus la del arreglo de punteros a int Tabla:

    delete[ ] t abl a;

    El cdigo completo queda de la siguiente forma:

    #include

    void main( ) {int **t abl a;int n = 134;int m = 231;int i ;

    / / Ar r ay de punt eros a int:t abl a = new int* [n ] ;/ / n ar rays de m i nt sfor( i = 0; i < n; i ++)

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    17/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 17

    t abl a[ i ] = new int[ m] ;t abl a[ 21] [ 33] = 123;cout

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    18/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 18

    f or ( i = 0; i < pos; i ++)

    Temp_ar r [ i ] = ar r [ i ] ;

    f or ( i = pos; i < si ze- 1; i ++)

    Temp_ar r [ i ] = ar r [ i +1] ;

    si ze- =1;del et e[] arr ; / / l i ber a l as cel das vi ej asarr = Temp_ar r ;

    }

    Ejemplo: cuando se redimensiona solo indicando la cantidad de celdas que se

    quiere tenga el nuevo arreglo

    voi d r edi mensi onar ( i nt * dat os, i nt & si ze, i nt n)

    i f ( n! =si ze){

    i f ( n!=0){

    i nt * nuevos_dat os;nuevos_dat os= new i nt [ n] ;i f ( si ze>0)

    {i nt mi ni mo;

    i f ( si ze

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    19/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 19

    En muchas ocasiones se necesitan estructuras que puedan cambiar de tamaodurante la ejecucin del programa. Por supuesto, podemos crear arraysdinmicos, pero una vez creados, su tamao tambin ser fijo, y para hacer

    que crezcan o disminuyan de tamao, deberemos reconstruirlos desde elprincipio. Las estructuras dinmicas nos permiten crear estructuras de datosque se adapten a las necesidades reales a las que suelen enfrentarse nuestrosprogramas. Pero no slo eso, como veremos, tambin nos permitir crearestructuras de datos muy flexibles, ya sea en cuanto al orden, la estructurainterna o las relaciones entre los elementos que las componen.

    Una lista enlazadas estn compuestas de otras pequeas estructuras a las quellamaremos nodoso elementos, que agrupan los datos con los que trabajarnuestro programa y adems uno o ms punteros autoreferenciales, es decir,punteros a objetos del mismo tipo nodo.

    Una estructura bsica de un nodo para crear listas de datos seria:

    st r uct nodo {i nt dat o;st r uct nodo *ot r onodo;

    };

    El campo "otronodo" puede apuntar a un objeto del tipo nodo. De este modo,cada nodo puede usarse como un ladrillo para construir listas de datos, y cadauno mantendr ciertas relaciones con otros nodos.

    Para acceder a un nodo de la estructura slo necesitaremos un puntero a unnodo.

    Definicin:

    La forma ms simple de estructura dinmica es la lista abierta. En estaforma los nodos se organizan de modo que cada uno apunta al siguiente,y el ltimo no apunta a nada, es decir, el puntero del nodo siguiente valeNULL.

    En las listas abiertas existe un nodo especial: el primero. Normalmentediremos que nuestra lista es un puntero a ese primer nodo y llamaremos

    a ese nodo la cabecera de la lista. Eso es porque mediante ese nicopuntero podemos acceder a toda la lista.

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    20/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 20

    Cuando el puntero que usamos para acceder a la lista vale NULL, diremosque la lista est vaca.

    El nodo tpico para construir listas tiene esta forma:

    st r uct nodo {i nt dat o;st r uct nodo *si gui ent e;

    };

    En el ejemplo, cada elemento de la lista slo contiene un dato de tipo

    entero, pero en la prctica no hay lmite en cuanto a la complejidad de

    los datos a almacenar.

    Declaraciones de tipos para manejar listas

    Normalmente se definen varios tipos que facilitan el manejo de las listas, en C,la declaracin de tipos puede tener una forma parecida a esta:

    t ypedef st r uct _nodo {i nt dat o;st r uct _nodo *si gui ent e;

    } t i poNodo;

    t ypedef t i poNodo *pNodo;

    t ypedef t i poNodo *Li st a;

    tipoNodo es el tipo para declarar nodos, evidentemente.

    pNodo es el tipo para declarar punteros a un nodo.

    Lista es el tipo para declarar listas, como puede verse, un puntero a un nodo y

    una lista son la misma cosa. En realidad, cualquier puntero a un nodo es una

    lista, cuyo primer elemento es el nodo apuntado.

    Es muy importante que nuestro programa nunca pierda el valor del puntero

    al primer elemento, ya que si no existe ninguna copia de ese valor, y se

    pierde, ser imposible acceder al nodo y no podremos liberar el espacio de

    memoria que ocupa.

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    21/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 21

    Operaciones bsicas con listas

    Con las listas tendremos un pequeo repertorio de operaciones bsicas que sepueden realizar:

    Creacin de una lista enlazada Aadir o insertar elementos. Buscar o localizar elementos. Borrar elementos. Moverse a travs de una lista, anterior, siguiente, primero.

    Cada una de estas operaciones tendr varios casos especiales, por ejemplo, noser lo mismo insertar un nodo en una lista vaca, o al principio de una lista novaca, o la final, o en una posicin intermedia.

    Creacin de una lista enlazada

    El procedimiento de creacin de una lista enlazada es muy simple e inicializaun puntero del tipo TLista a NULL. Por ejemplo podra ser:

    Insertar elementos en una lista abierta

    Veremos primero los casos sencillos y finalmente construiremos un algoritmogenrico para la insercin de elementos en una lista.

    1. Insertar un nodo al comienzo de una lista

    2. Insertar un nodo al final de la lista

    3. Insertar un nodo despus de un determinado nodo existente (porejemplo, para mantener una lista ordenada).

    Insertar un elemento en una lista vaca

    Este es, evidentemente, el caso ms sencillo. Partiremos de que ya tenemos elnodo a insertar y, por supuesto un puntero que apunte a l, adems el punteroa la lista valdr NULL:

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    22/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 22

    El proceso es muy simple, bastar con que:

    1. nodo->siguiente apunte a NULL.2. Lista apunte a nodo.

    Insertar un elemento en la primera posicin de una lista

    Podemos considerar el caso anterior como un caso particular de ste, la nica

    diferencia es que en el caso anterior la lista es una lista vaca, pero siempre

    podemos, y debemos considerar una lista vaca como una lista.

    De nuevo partiremos de un nodo a insertar, con un puntero que apunte a l, y

    de una lista, en este caso no vaca:

    El proceso sera el siguiente:

    1. Hacemos que nodo->siguiente apunte a Lista.2. Hacemos que Lista apunte a nodo.

    El algoritmo es el siguiente:

    ALGORITMO InsertarAlPrincipio(ES TpLista lista; E Elem Tdato)VARIABLESTpLista ptr // Puntero auxiliar

    INICIOASIGNAR(ptr) // Nuevo nodoptr->Dato = Elemptr->sig = listalista = ptr

    FIN InsertarAlPrincipio

    *************************************************************voi d I NSERTAR_I NI ( pNodo &Li st a, DATO El em){ pNodo NUEVO;

    NUEVO=new( t i poNodo) ;

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    23/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 23

    i f ( NUEVO){ NUEVO- >Dat o=El em;

    NUEVO- >Si g=NULL;i f ( Li st a==NULL) Li st a=NUEVO; / / Li st a Vaci ael se

    { NUEVO- >Si g=Li st a;Li st a=NUEVO; } }el se

    cout siguiente sea nodo.

    El Algoritmo es el siguiente:

    ALGORITMO InsertarAlFinal(ES TpLista lista; E Elem Tdato)

    VARIABLESTpLista ptr, nuevonodo // Puntero auxiliar

    INICIOASIGNAR(nuevoNodo) // Nuevo nodonuevoNodo->Dato = ElemennuevoNodo->sig = NULOptr=listaMIENTRAS (ptr->sig != NULO) HACER

    ptr = ptr->sigFINMIENTRASptr->sig = nuevoNodo

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    24/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 24

    FIN InsertarAlFinal

    ***********************************

    voi d I NSERTAR_FI N( pNodo &Li st a, DATO El em){ pNodo A = Li st a, NUEVO;

    NUEVO = new ( t i poNodo) ;NUEVO- >Dat o = El em;NUEVO- >Si g = NULL;i f ( Li st a == NULL) Li st a = NUEVO;el se{whi l e (A- >Si g ! = NULL) A=A- >Si g;

    A- >Si g = NUEVO;}

    }

    Insertar un elemento a continuacin de un nodo existente en la lista

    De nuevo podemos considerar el caso anterior como un caso particular deeste. Ahora el nodo "anterior" ser aquel a continuacin del cual insertaremosel nuevo nodo:

    Suponemos que ya disponemos del nuevo nodo a insertar, apuntado por nodo,y un puntero al nodo a continuacin del que lo insertaremos.

    El proceso a seguir ser:

    1. Hacer que nodo->siguiente seale a anterior->siguiente.2. Hacer que anterior->siguiente seale a nodo.

    Ejemplo1: Insertar despus de un nodo dado su Posicin en la lista

    voi d I NSERTAR_NODO( pNodo &Li st a, DATO X, i nt POS)

    { i nt i ;pNodo A= Li st a, NUEVO;NUEVO = new( t i poNodo) ;i f NUEVO

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    25/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 25

    { NUEVO - >I nf o = X;NUEVO - >Si g = NULL;i f ( POS==1 | | Li st a==NULL)

    { NUEVO- >Si g = Li st a;Li st a = NUEVO; }

    el se{ i =1;

    whi l e( i Si g != NULL){ i ++;

    A=A- >Si g; }i f ( A- >Si g != NULL){ NUEVO- >Si g = A- >Si g;

    A- >Si g= NUEVO;}el se A- >Si g=NUEVO; } }

    Ejemplo2: Insertar Ordenadamente

    ALGORITMO InsertarOrdenada(ES TpLista lista; E Elem Tdato)

    VARIABLES

    TpLista nuevoNodo, ptr

    INICIO

    SI lista == NULO O lista->Dato >= Elem ENTONCES

    InsertarAlPrincipio(lista, Elem)

    SINO

    ASIGNAR(nuevoNodo)

    nuevoNodo->Dato = Elem

    nuevoNodo->sig = NULO

    ptr = lista

    MIENTRAS ptr->sig != NULO Y (Elem > ptr->sig->Dato ) HACER

    ptr = ptr->sig

    FINMIENTRAS

    nuevoNodo->sig = ptr->sig

    ptr->sig = nuevoNodo

    FINSI

    FIN InsertarOrdenada

    ************************************************

    voi d I nsert ar( Li sta &l i sta, i nt v)

    { pNodo nuevo, ant er i or ;nuevo = new t i poNodo; / / Cr ear un nodo nuevonuevo- >val or = v;i f ( L i staVaci a( l i sta) | | ( l i sta- >val or > v) / / Si l a l i sta est vac a

    { nuevo- >Si g = l i st a;l i st a = nuevo; }

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    26/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 26

    el se{ant er i or = l i st a; / / Buscar el nodo de val or menor a vwhi l e( ant er i or - >Si g && ant eri or- >Si g- >val or Si g;nuevo- >Si g = anter i or- >Si g;

    ant er i or- >Si g = nuevo;}

    }

    Localizar elementos en una lista abierta

    Muy a menudo necesitaremos recorrer una lista, ya sea buscando un valorparticular o un nodo concreto. Las listas abiertas slo pueden recorrerse en unsentido, ya que cada nodo apunta al siguiente, pero no se puede obtener, porejemplo, un puntero al nodo anterior desde un nodo cualquiera si no seempieza desde el principio.

    Para recorrer una lista procederemos siempre del mismo modo, usaremos unpuntero auxiliar como ndice:

    1. Asignamos al puntero ndice el valor de Lista.

    2. Abriremos un bucle que al menos debe tener una condicin, que elndice no sea NULL.

    3. Dentro del bucle asignaremos al ndice el valor del nodo siguiente alndice actual.

    Procedimiento que permite localizar un nodo y retornar su direccin:pNodo BUSCAR_DI R( pNodo Li st a, DATO el em)

    { pNodo A=Li st a;

    i f ( Li st a! =NULL)

    { whi l e( A- >Dat o!=el em && A- >Si g!=NULL)

    A=A- >Si g;

    i f ( A- >Dat o==el em) r etur n A;

    el se ret ur n NULL;

    }

    el se

    { cout

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    27/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 27

    st r uct _nodo *si gui ent e;} t i poNodo;

    t ypedef t i poNodo *pNodo;t ypedef t i poNodo *Li st a;. . .pNodo i ndi ce;. . .i ndi ce = Li st a;whi l e( i ndi ce) {

    cout dato dato dato se producir un error.

    En general eso ser cierto, no puede accederse a punteros nulos. Pero en estecaso, ese acceso est dentro de una condicin y forma parte de una expresin"and". Recordemos que cuando se evala una expresin "and", se comienzapor la izquierda, y la evaluacin se abandona cuando una de las expresionesresulta falsa, de modo que la expresin "indice->dato

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    28/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 28

    Eliminar el primer nodo de una lista abierta

    Es el caso ms simple. Partiremos de una lista con uno o ms nodos, yusaremos un puntero auxiliar, nodo:

    1. Hacemos que nodo apunte al primer elemento de la lista, es decir aLista.

    2. Asignamos a Lista la direccin del segundo nodo de la lista:Listasiguiente.

    3. Liberamos la memoria asignada al primer nodo, el que queremos

    eliminar.

    Si no guardamos el puntero al primer nodo antes de actualizar Lista, despusnos resultara imposible liberar la memoria que ocupa. Si liberamos la memoriaantes de actualizar Lista, perderemos el puntero al segundo nodo.

    Si la lista slo tiene un nodo, el proceso es tambin vlido, ya que el valor de

    Listasiguiente es NULL, y despus de eliminar el primer nodo la lista quedar

    vaca, y el valor de Lista ser NULL.

    De hecho, el proceso que se suele usar para borrar listas completas es eliminar

    el primer nodo hasta que la lista est vaca.

    Algoritmo para borrar el primer nodo de una Lista

    ALGORITMO EliminarPrimero(ES TpLista lista)

    VARIABLES

    TpLista ptr

    INICIO

    SI lista != NULO ENTONCES // Si no, no hay que eliminar

    ptr = lista

    lista = lista->sig

    LIBERAR(ptr)

    FINSI

    FIN EliminarPrimero

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    29/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 29

    **************************************

    void Eiminarprimero(Lista &lista, Tdato & Elem )

    { pNodo nodo;

    if lista!=NULL

    {nodo = lista;

    lista = lista->Sig;

    Elem=nodo->Dato;

    delete nodo; }

    }

    Eliminar un nodo cualquiera de una lista abierta

    En todos los dems casos, eliminar un nodo se puede hacer siempre del mismo

    modo. Supongamos que tenemos una lista con al menos dos elementos, y un

    puntero al nodo anterior al que queremos eliminar. Y un puntero auxiliar nodo.

    El proceso es parecido al del caso anterior:

    1. Hacemos que nodo apunte al nodo que queremos borrar.2. Ahora, asignamos como nodo siguiente del nodo anterior, el siguiente al

    que queremos eliminar: anterior->siguiente = nodo->siguiente.3. Eliminamos la memoria asociada al nodo que queremos eliminar.

    Si el nodo a eliminar es el ltimo, es procedimiento es igualmente vlido, ya

    que anterior pasar a ser el ltimo, y anterior->siguiente valdr NULL.

    Algoritmo para Borrar un nodo cualquiera

    ALGORITMO Borrar(ES TpLista lista; E Elem Tdato)

    VARIABLES

    TpLista ptr, ant=NULO

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    30/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 30

    INICIO

    SI lista != NULO ENTONCES // Sino, no hay que hacer nada

    ptr = lista

    MIENTRAS ptr != NULO Y ptr->Dato != Elem HACER

    ant = ptr

    ptr = ptr->sig

    FINMIENTRAS

    SI ptr != NULO ENTONCES // Encontrado

    SI ant == NULO ENTONCES // Es el primer elemento

    lista = lista->sig

    SINO

    ant->sig = ptr->sig

    FINSILIBERAR(ptr)

    FINSI

    FINSI

    FIN Borrar

    *************************************************************voi d Borr ar( Li sta &l i sta, i nt v)

    { pNodo ant er i or , nodo;nodo = l i st a;

    ant er i or = NULL;whi l e( nodo && nodo- >dato != v)

    { ant er i or = nodo;nodo = nodo- >Si g;

    }

    i f ( ! nodo | | nodo->dat o ! = v)ret ur n;

    el se { i f ( ! ant er i or ) / / Pr i mer el ement ol i st a = nodo->Si g;

    el se / / un el ement o cual qui er aant er i or- >Si g = nodo->Si g;

    del et e nodo; }

    }

    Moverse a travs de una lista abierta

    Slo hay un modo de moverse a travs de una lista abierta, hacia delante.

    An as, a veces necesitaremos acceder a determinados elementos de una listaabierta. Veremos ahora como acceder a los ms corrientes: el primero, elltimo, el siguiente y el anterior.

    Mostrar la lista

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    31/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 31

    voi d Most r ar Li st a( pNodo l i st a){ pNodo nodo = l i st a;i f ( Li s taVaci a( l i sta) )

    cout dat o;nodo = nodo- >Si g;

    }coutSi g;i f ( nodo==P) r etur n nodo- >Si g;

    el se r etur n NULL;}

    }

    Elemento anterior a uno cualquiera

    Ya hemos dicho que no es posible retroceder en una lista, de modo que para

    obtener un puntero al nodo anterior a uno dado tendremos que partir del

    primero, e ir avanzando hasta que el nodo siguiente sea precisamente nuestro

    nodo.

    pNodo ANTERI OR( pNodo Li st a, pNodo P){ pNodo A=Li st a;

    i f ( Li st a==NULL | | P==NULL | | Li st a==P) r etur n NULL;el se{ whi l e( A- >Si g!=P && A- >Si g!=NULL) A=A- >Si g;i f ( A- >Si g==P) r et ur n A;

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    32/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 32

    el se r etur n NULL;}

    }

    ltimo elemento de una lista

    Para obtener un puntero al ltimo elemento de una lista partiremos de un nodo

    cualquiera, por ejemplo el primero, y avanzaremos hasta que su nodo

    siguiente sea NULL.

    pNodo ULTI MO ( pNodo Li st a)

    { pNodo A=Li st a;

    i f ( Li st a==NULL ) r etur n NULL;

    el se

    {whi l e( A- >Si g!=NULL) A=A- >Si g;

    r et ur n A; }}

    Saber si una lista est vaca

    Basta con comparar el puntero Lista con NULL, si Lista vale NULL la lista est

    vaca.

    i nt Li st aVaci a( Li s ta l i s ta)

    { r eturn ( l i st a == NULL) ; }

    Borrar una lista completaEl algoritmo genrico para borrar una lista completa consiste simplemente en

    borrar el primer elemento sucesivamente mientras la lista no est vaca.

    ALGORITMO BorrarLista(ES TpLista lista)

    VARIABLES

    TpLista ptr

    INICIO

    MIENTRAS lista != NULO HACER

    ptr = lista

    lista = lista->sig

    LIBERAR(ptr)

    FINMIENTRAS

    FIN BorrarLista

    *********************************************

    voi d Borr arLi sta(Li sta &l i st a)

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    33/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 33

    { pNodo nodo;whi l e( l i s ta)

    { nodo = l i st a;

    l i sta = l i sta- >Si g;del ete nodo;

    }}

    Ejercicio de aplicacin.

    Se crea una lista de nelementos y la llena con valores aleatorios usando unafuncin random(). Posteriormente entra en un ciclo donde se insertanelementos en posiciones especficas de la lista, mostrando en cada paso elresultado de cada operacin.

    En el programa se define una funcin que permite insertar un nodo en una

    posicin especfica de la lista. La funcin (INSERTAR_NODO) recibe comoparmetros la direccin de la lista, el elemento a insertar y la posicin dondese debe insertar.

    El programa no verifica si una posicin especifica esta fuera del alcance de lalista, por ejemplo, si se tiene una lista de 5 elementos y se intenta unelemento en la posicin 8.

    #i ncl ude#i ncl ude#i ncl ude#i ncl udet ypedef i nt t i po_i nf o;

    st r uct t _nodo{ t i po_ i nf o I nf o;

    t _nodo * Si g;};t ypedef st r uct t _nodo t i po_nodo;t ypedef t i po_nodo* pt_nodo;voi d I NSERTAR_I NI ( pt _nodo &L,t i po_i nf o El em){ pt _nodo Aux;

    Aux=new( t i po_nodo) ;Aux- >I nf o=El em;Aux- >Si g=NULL;

    i f ( L==NULL) L=Aux;el se{ Aux- >Si g=L;

    L=Aux; }}voi d I NSERTAR_NODO( pt_nodo &Li st a,t i po_i nf o El em, i nt i nd){ i nt I ;

    pt _nodo Act ;Act=Li st a;i f ( i nd==1)

    I NSERTAR_I NI ( Li st a, El em) ;

    voi d MOSTRAR_LI STA( pt_nodo Li s){ pt _nodo P;

    P=Li s;whi l e( P!=NULL){ cout

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    34/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    AERS..Pg. 34

    el se{ f or ( i =1; i Si g;

    I NSERTAR_I NI ( ( Act - >Si g) , El em) ; }}

    cout RESP;

    }

    }

    EJERCICIOS PROPUESTOS

    1. Escribir una funcin que cuente (CONTAR(Lista, valor)) el nmero de veces queaparece un valor en una lista, modificando la funcin que determina si un datoexiste o no en la lista.

    2. Desarrolle una funcin que permita intercambiar dos nodos de una lista

    simplemente enlazada dadas las posiciones de los mismos.3. Escribir una funcin que permita eliminar el penltimo Nodo de una Lista Enlazada.

    4. Escribir una funcin que permita detectar si una lista tiene valores repetidos.

    5. Escribir una funcin que recibe dos listas L1 y L2, remueve el nodo frontal de lasegunda lista y lo inserta al inicio de la primera lista.

    6. Escribir una funcin DivAlterna() que divida una lista en dos sub-listas, pero laslistas pequeas deben ser construidas tomando en forma alterna los nodos de lalista original. Si la lista original fuera {7,10,12,8,17}, se obtienen dos listas{7,12,17} y {10,8}.

    7. Escribir un algoritmo que permita sumar dos polinomios P1 y P2 almacenados en

    listas simples enlazadas.8. Desarrolle un programa que lleve el registro de todos los estudiantes de la

    asignatura computacin III, utilizando listas enlazadas. Los estudiantes aprobados

    deben insertarse por el principio de la lista y los reprobados por el final. Los datos

    requeridos por cada estudiante son: cedula, nombre y nota definitiva. El programa

    debe permitir realizar las operaciones de: agregar estudiante, buscar estudiante

    por cedula, eliminar estudiante, total estudiantes aprobados, total estudiantes

    reprobados.

    9. Disear un programa que maneje N cantidad de datos de tipo entero en dos listascon insercin por el principio. Debe existir un ciclo de carga para la primera lista yotro para segunda. Una vez cargados los datos en ambas listas, el programa debe

    comparar las dos listas para verificar si ambas listas son iguales en tamao ycontenido. Una vez realizada la verificacin, el programa debe mostrar: si las listasson iguales en tamao y contenido, si las listas son iguales en tamao pero; no encontenido, o no tienen ni el mismo tamao ni el mismo contenido.

    10.Crear una funcin que almacene N cantidad de datos de tipo real en una lista. Unavez cargados los datos en la lista, la funcin debe calcular el promedio de todos losdatos. Posteriormente, debe cargar los datos menores o igual al promedio en unasegunda lista, y los mayores en una tercera lista. Al finalizar este proceso, lafuncin debe mostrar lo siguiente: a) Los datos cargados en la lista principal, b) Elpromedio, c) Los datos cuyo valor sea igual o menor al promedio d) los datos quesean mayores al promedio.

  • 7/25/2019 Memoria Dinamica, Punteros, Listas Simples (Alicia Ramos)

    35/35

    Apuntes sobre punteros y listas enlazadas Computacin III

    11.Se tiene un arreglo de 12 listas ( 1 x mes) que guarda la temperatura promedio/diade una ciudad durante un ao. Escriba una funcin que recibe el arreglo, busca ydevuelve la temperatura promedio mxima y el da y mes que ocurri.

    12.Disear un programa que permita: pasar los datos de un archivo lista_mus2.txt

    a una lista enlazada, mostrar los datos cargados en la lista y permitir buscar los

    datos de un intrprete en particular. Donde el campo Datos de cada nodo estaraconformado por los siguientes campos: fecha, hora, tamao del archivo (mp3),

    intrprete y titulo.

    13.Un sistema de control dedepsitos de un banco tienela estructura que semuestra.

    Disee un algoritmo, usandolistas de registros, quepermita consultar el saldo delas cuentas de un clienteutilizando la cedula

    CLIENTES OPERACIONESCUENTA CEDULA CUENTA COD MONTO

    1 100 7777 1 100 D 20000101 1234 100 R 15000

    102 9876 200 R 12000

    200 7777 101 D 30000

    100 R 10000

    N : :

    Para el diseo se debe tener en cuenta: La operaciones puede ser D/R Deposito/Retiro, que se representan en el

    cdigo de la operacin (COD). El saldo de la cuenta es SALDO = Depsitos- Retiros.

    Un cliente puede tener Varias cuentas y una cuenta puede tener variasoperaciones de Deposito/Retiro.