Está en la página 1de 29

Punteros Todo lo que deberas s el de MP supiese explicar.

Por: Adri Ciurana Lanau

Punteros
1.-Qu son? 2.-Qu nos permiten? 3.-Paso por referencia 4.-Creacin de registros 5.-Listas dinmicas -Qu es? -Recorrer una lista -Aadir Elemento -Eliminar Elemento 5.1.-FIFO (First In First Out, o cola) -Qu es? -Recorrer una Cola -Aadir Elemento -Eliminar Elemento 5.2.- LIFO (Last In Fist Out, o pila) -Qu es? -Recorrer una pila -Aadir Elemento -Eliminar Elemento 6.-Diferencias entre Colas y pilas

1.-Qu Son?
Los punteros son variables que en vez de almacenar datos directamente, almacenan direcciones de memoria. Declaracin en Pseudocdigo: puntero: punter a TIPO Ej: p: punter a tNode Declaracin en C: TIPO *puntero; Ej: struct tNode *p; Cuando decimos que un puntero esta apuntando a algo, se refiere a que ese puntero guarda la direccin de memoria de ese elemento. Para entenderlo de forma mas sencilla vamos ha hacer un ejemplo. Memoria #99 10 variable
Puntero

Aqu vemos como un puntero apunta a una variable entera, pero realmente cuando decimos que una cosa apunta a otra, nos estamos refiriendo a que almacena su direccin en la memoria. Por lo que el valor realmente del puntero es Puntero=#99 (direccionamiento indirecto). Obtener direccin en la memoria de un elemento: Cuando tenemos una variable (de cualquier tipo), simplemente si queremos saber su direccin en la memoria, debemos introducir & delante de la misma variable. Entonces si hago &variable, esto me devuelve la posicin en memoria de este elemento y no su contenido. Ej: &variable nos devuelve #99

Interpretacin del contenido de un elemento como un direccionamiento indirecto: Primero y antes de todo, definiremos que es un direccionamiento indirecto, pues simplemente se trata de interpretar que lo que guarda una variable es una direccin de memoria. Ej: variable2=&variable /*variable2 ahora valdria #99*/ *variable2=variable /*Ahora interpretaramos que aquello que guardaba la variable2, es una direccin de memoria y que queremos ver el contenido de dicha direccin de memoria*/

2.-Qu nos permiten?


Con esa relacin entre un puntero y una variable, podemos realizar un sinfn de operaciones, por ejemplo modificar valores en un procedimiento. (paso por referencia). O crear un seguido de nodos que nos permitirn avanzar nodo a nodo, para as crear listas dinmicas.

3.-Paso por referencia


El paso por referencia tcnicamente en pseudocdigo se declara de la siguiente forma: Procedimiento proceso(var variable) Con eso permitimos que los cambios en que la variable se modifique dentro de la funcin o procedimiento, despus de haber salido de ella misma, sigan aplicados. Es decir que despus de haber salido de la funcin aquella variable no valdr lo mismo que cuando entro. En pseudocdigo, no tiene ninguna relacin con punteros pero en cambio en C, no existe ninguna forma de indicar que esa variable todos los cambios que se le apliquen se sigan aplicando fuera, por lo que se hace una especie de parche. En vez de pasar la propia variable, se pasa su direccin en memoria &variable, y luego se asigna un puntero que apunta a esa variable TIPO *puntero. Esto se hace de la siguiente forma: Void proceso(int *variable2) *variable2=.

Con eso indicamos que pasaremos una direccin de memoria y el puntero *variable deber apuntarla. Cuando queramos utilizar dicha funcin: proceso(&variable); Pasaremos la direccin de memoria de la variable.

Con lo que realmente hacemos esto: Pasamos &variable que vale #99, indicamos que un puntero apunte a #99, y para modificar los datos indicamos que variable2 guarda una direccin de memoria y que nos lo interprete como tal *variable2 (direccionamiento indirecto).

4.-Creacin de registros
El uso de registros es constante para crear listas dinmicas en punteros, por lo que antes de entrar en tema, explicaremos que son los registros. Un registro no es ms que una variable con muchas subvariables, por decirlo de alguna manera es como un contenedor que engloba un conjunto de variables. En pseudocdigo se indica de la siguiente forma: Alumno =registro ( nombre: cadena Id: enter Email: cadena ) Y en C de la siguiente manera: Struct Alumno { Char nombre; Int id; Char email; }; Pero an no vemos que posible relacin puede tener un registro con las listas dinmicas. Pues es simplemente que en un registro podemos poner un puntero a un mismo registro.

Pseudocdigo: Alumno =registro ( nombre: cadena Id: enter Email: cadena Siguiente: punter a Alumno ) En C: Struct Alumno { Char nombre; Int id; Char email; Struct Alumno *siguiente; };

Por lo que este registro tiene un puntero llamado siguiente que apuntar a otro registro del mismo tipo (tipo alumnos).

5.-Listas Dinmicas
-Qu Son?
Las listas dinmicas son aquellas listas en que desconoces el nmero de elementos que puedes incluir como mximo en ella, es decir desconoces el nmero de elementos que tendrs. Por lo que para ello es necesario utilizar punteros (Si, chicos una putada no?). Tipos de listas dinmicas: En el fondo clasificar los tipos de listas que hay es algo til pero no quiere decir que solo hayan dos tipos, al ser realizado con punteros podemos hacer virgueras como rboles, grafos, listas que se aaden como pilas y se borran como colas, etc. Pero de hecho las que ms se utilizan se resumen a dos tipos: -Colas (FIFO) -Pilas (LIFO)

En Pseudocdigo: Nodo= registro( numero: entero Siguiente: punter a Nodo ) Lista = registro( primero: punter a Nodo )

En C: Struct Nodo{ Int Numero; Struct Nodo *Siguiente; }: Struct Lista{ Struct Nodo *Primero; };

-Cmo recorrerlas?
Para recorrer toda una pila necesitamos simplemente un puntero auxiliar para indicar en que punto de la pila estamos. Para ello podemos utilizar el puntero actual y el anterior. Podemos distinguir dos fines para recorrer una cola: -Aadir un elemento. -Eliminar un elemento. PD: En este caso es lo mismo pero si hacemos funcionamientos en que se aada un elemento como una pila y se borre como una cola es bien distinto. Cuando queremos recorrer una lista hacemos lo siguiente: Pseudocdigo: Anterior,Actual: punter a Nodo Anterior NUL Actual Lista.primero /*Nos posicionamos en el inicio de la lista*/ Mientras(Actual!=NUL) /*Con esto indicamos que la lista no es nula*/

/*Operaciones que queremos realizar*/ Anterior Actual Actual Actual Siguiente Fimientras En C: Struct Nodo *Anterior,*Actual; Anterior=NULL; Actual=Lista.primero; While(Actual!=NULL){ /*Operaciones que queremos realizar*/ Anterior=Actual; Actual=Actual->Siguiente; }

-Aadir elemento en una Lista


Para aadir un elemento a una cola, debemos distinguir diferentes casos: 1.-nico elemento de la lista. 2.-Primer elemento de la lista. 3.-Elemento entre el medio de la lista. 4.-ltimo de la lista. 5.-Agrupando Casos

Utilizaremos las operaciones assignar(puntero) (asigna a puntero NUL si no hay memoria disponible), alliberar(puntero) para crear elementos en la memoria dinmica donde apuntar el puntero. Para aadir elementos a una lista utilizaremos el anterior siempre, ya que eso nos indicar siempre que caso es.

1.-nico elemento de la lista:


Eso nos indica que esta lista antes es nula, que no existe ningn valor anteriormente. Por lo que anteriormente no vala nada (NUL) y el primero tampoco. Entonces si la lista es nula, el anterior tambin lo ser: Pseudocdigo: P: punter a Nodo Assignar(p) Si(p!=NUL) /*Comprovamos que nos ha asignado memoria*/ p num numero p Siguiente=NUL /*Con esto evitamos que nos recorra ms*/ Si(Anterior=NUL AND Lista.primero=NUL) /*Comprovamos anterior es nulo*/ Lista.primero p Fisi Fisi En C: Struct Nodo *p; p=(Struct Nodo*)malloc(sizeof(Struct Nodo)); /*Simplemente dice que guarde una parte de la memoria dinamica del tamao de struct nodo, y que p apunte a ella*/ if(p!=NUL){ p num= numero; p Siguiente=NULL; if(anterior==NULL && Lista.primero==NULL){ Lista.primero=p } } Y as simplemente asignamos p como el primer elemento de la lista.

2.-Primer elemento de la lista:


Si queremos insertar un elemento en una lista que contiene datos, pero queremos hacerlo en la primera posicin. Sabemos que Anterior=NUL, pero que la Lista.primero no lo ser.

Pseudocdigo: P: punter a Nodo Assignar(p) Si(p!=NUL) /*Comprovamos que nos ha asignado memoria*/ p num numero p Siguiente NUL Si(Anterior=NUL AND Lista.primero!=NUL) /*Comprovamos anterior es nulo*/ p Siguiente Lista.primero ista.primero p Fisi Fisi En C: Struct Nodo *p; p=(Struct Nodo*)malloc(sizeof(Struct Nodo)); /*Simplemente dice que guarde una parte de la memoria dinamica del tamao de struct nodo, y que p apunte a ella*/ if(p!=NUL){ p num= numero; p Siguiente=NULL; if(anterior==NULL && Lista.primero!=NULL){ p Siguiente=Lista.primero Cola.primero=p } } Lo que estamos haciendo es lo siguiente: Primero asignamos p, luego indicamos que el siguiente del mismo es el elemento que actualmente es el primero de la lista, y luego indicamos que ahora l es el primero de la cola.

3.-Elemento entre el medio de la lista:


Si queremos insertar un elemento en el medio de la lista, sabemos que el Anterior!=NUL, y el Anterior Siguiente (equivalente a Actual)!=NUL Pseudocdigo: P: punter a Nodo Assignar(p) Si(p!=NUL) /*Comprovamos que nos ha asignado memoria*/ p num numero p Siguiente NUL Si(Anterior!=NUL AND Anterior Siguiente!=NUL) /*Comprovamos anterior no es nulo*/ p Siguiente Anterior Siguiente Anterior Siguiente p Fisi Fisi En C: Struct Nodo *p; p=(Struct Nodo*)malloc(sizeof(Struct Nodo)); /*Simplemente dice que guarde una parte de la memoria dinamica del tamao de struct nodo, y que p apunte a ella*/ if(p!=NUL){ p num= numero; p Siguiente=NULL; if(anterior!=NULL && Anterior Siguiente!=NULL){ p Siguiente=Anterior Siguiente Anterior Siguiente=p } }

4.-ltimo de la lista:
Si queremos insertar un elemento al final de la lista sabemos que el Anterior!=NUL y el Anterior Siguiente =NUL (equivalente a Actual) Pseudocdigo: P: punter a Nodo Assignar(p) Si(p!=NUL) /*Comprovamos que nos ha asignado memoria*/ p num numero p Siguiente NUL Si(Anterior!=NUL AND Anterior Siguiente =NUL) /*Comprovamos anterior no es nulo*/ Anterior Siguiente p Fisi Fisi En C: Struct Nodo *p; p=(Struct Nodo*)malloc(sizeof(Struct Nodo)); /*Simplemente dice que guarde una parte de la memoria dinmica del tamao de struct nodo, y que p apunte a ella*/ if(p!=NUL){ p num= numero p Siguiente=NULL; if(anterior!=NULL && Anterior Siguiente =NULL){ Anterior Siguiente=p } } De modo que anterior Siguiente ser p.

5.-Agrupando Casos:
Podemos agrupar los casos para que sea mas compacto el aadir. Pseudocdigo: P: punter a Nodo Assignar(p) Si(p!=NUL) p num numero p Siguiente NUL Si(Anterior=NUL) /*Casos 1 y 2*/ p Siguiente Lista.primero Lista.primero p Sino /*Casos 3 y 4*/ p Siguiente Anterior Siguiente Anterior Siguiente p Fisi Fisi En C: Struct Nodo *p; p=(Struct Nodo*)malloc(sizeof(Struct Nodo)); if(p!=NULL){ p num=numero; p Siguiente=NULL; If(Anterior==NULL){ p Siguiente=Lista.primero Lista.primero=p } else { p Siguiente=Anterior Siguiente: Anterior Siguiente=p; } }

El caso 1 y 2, tcnicamente son iguales, porque si es el caso 1, Lista.primero ser nulo y no cambiaremos nada, y si es el caso 2, Lista.primero ser el primero de la cola. El caso 3 y 4, ms de lo mismo, si se trata del caso 4 Anterior Siguiente no valdr nada, por lo que no cambiaremos nada, y si es el caso 3, Anterior Siguiente si valdr algo.

-Eliminar elemento en una lista:


Bueno, antes hemos visto como aadir un elemento a una lista, ahora veremos el otro caso como eliminarlo. Para eliminar un elemento a una lista, debemos distinguir diferentes casos: 1.-nico elemento de la lista. 2.-Primer elemento de la lista. 3.-Elemento entre el medio de la lista. 4.-ltimo de la lista. 5.-Agrupando Casos

1.-nico elemento de la lista:


Para eliminar el nico elemento de una cola sabemos que el Anterior=NUL y el Anterior Siguiente (equivalente a Actual)=NUL, ya que nos pondremos en la cabeza de la lista. En este caso usaremos P como el puntero al elemento a eliminar en vez de usarlo para el elemento a aadir.

Pseudocdigo: P: punter a Nodo Si(Anterior=NUL AND Lista.primero Siguiente=NUL) p Lista.primero Lista.primero NUL Fisi Alliberar(p); En C: Struct Nodo *p; If(Anterior==NULL && Lista.primero Siguiente==NUL){ P=Lista.primero Lista.primero=NUL } Free(p);

2.-Primer elemento de la lista:


Para eliminar el primer elemento de una lista sabemos que el Anterior=NUL y que el Anterior Siguiente (equivalente a Actual) !=NUL. Pseudocdigo: P: punter a Nodo Si(Anterior=NUL AND Lista.primero Siguiente!=NUL) p Lista.primero Lista.primero p Siguiente Fisi Alliberar(p); En C: Struct Nodo *p; If(Anterior==NULL && Lista.primero Siguiente!=NULL){ P=Lista.primero; Lista.primero=NUL; } Free(p);

3.-Elemento entre el medio de la lista:


Para eliminar el elemento que esta entre medio de una lista sabemos que el Anterior!=NUL y que el Anterior Siguiente Siguiente(equivalente a Actual Siguiente)!=NUL Pseudocdigo: P: punter a Nodo Si(Anterior!=NUL AND Anterior Siguiente Siguiente!=NUL) p Anterior Siguiente Anterior Siguiente p Siguiente Fisi Alliberar(p); En C: Struct Nodo *p; If(Anterior!=NULL && Anterior Siguiente Siguiente!=NULL){ P=Anterior Siguiente; Anterior Siguiente=p Siguiente; } Free(p);

4.-Ultimo elemento de la lista:


Para eliminar el elemento que esta al final de una lista sabemos que el Anterior!=NUL y que el Anterior Siguiente Siguiente (equivalente a Actual Siguiente)=NUL. Pseudocodigo: P: punter a Nodo Si(Anterior!=NUL AND Anterior Siguiente Siguiente=NUL) p Anterior Siguiente Anterior Siguiente NUL Fisi Alliberar(p); En C: Struct Nodo *p; If(Anterior!=NULL && Anterior Siguiente Siguiente==NULL){ P=Anterior Siguiente; Anterior Siguiente=NULL; } Free(p);

5.-Agrupando Casos:
Podemos agrupar los casos de eliminar de la siguiente forma: Pseudocdigo: P: punter a Nodo Si(Anterior=NUL) P Cola.primero Cola.primero p Siguiente Sino P Anterior Siguiente Anterior Siguiente p Siguiente Fisi Alliberar(p); En C: Struct Nodo *p; If(Anterior==NULL){ P=Cola.primero; Cola.primero= p Siguiente; } else { P=Anterior Siguiente; Anterior Siguiente=p Siguiente } Free(p);

5.1.-FIFO

-Qu son?
Las FIFO o colas, son aquellas en que el primer elemento en entrar es el primero en salir, eso lo podemos asociar a cualquier accin en la vida normal como ir a comprar unas entradas, hacer cola en la discoteca. (Caso concreto Lista). Para crear una cola dinmica utilizamos los siguientes registros: En Pseudocdigo: Nodo= registro( numero: entero Siguiente: punter a Nodo ) Cola = registro( primero: punter a Nodo )

En C: Struct Nodo{ Int Numero; Struct Nodo *Siguiente; }: Struct Cola{ Struct Nodo *Primero; }; Podemos apreciar que realmente estamos usando dos punteros, el siguiente unir todos los nodos entre si para poder recorrer su informacin. Y el primero indicar el punto de inicio de la cola. Es punto de fin es tan fcil como detectar que el siguiente de un nodo no existe.

-Cmo recorrerlas?
Se recorre exactamente igual que una lista genrica, avanzars desde el primer elemento al ltimo.

-Aadir elemento en una Cola


Para aadir un elemento a una cola, debemos distinguir diferentes casos: 1.-nico elemento de la cola. 2.-ltimo de la cola. 3.-Agrupando Casos Utilizaremos las operaciones assignar(puntero) (asigna a puntero NUL si no hay memoria disponible), alliberar(puntero) para crear elementos en la memoria dinmica donde apuntar el puntero. Para aadir elementos a una cola utilizaremos el anterior siempre, ya que eso nos indicar siempre que caso es.

1.-nico elemento de la cola:


Eso nos indica que esta cola antes es nula, que no existe ningn valor anteriormente. Por lo que anteriormente no vala nada (NUL) y el primero tampoco. Entonces si la cola es nula, el anterior tambin lo ser: Pseudocdigo: P: punter a Nodo Assignar(p) Si(p!=NUL) /*Comprobamos que nos ha asignado memoria*/ p num numero p Siguiente NUL /*Con esto evitamos que nos recorra ms*/ Si(Anterior=NUL AND Cola.primero =NUL) /*Comprobamos anterior es nulo*/ Cola.primero p Fisi Fisi

En C: Struct Nodo *p; p=(Struct Nodo*)malloc(sizeof(Struct Nodo)); /*Simplemente dice que guarde una parte de la memoria dinamica del tamao de struct nodo, y que p apunte a ella*/ if(p!=NUL){ p num= numero; p Siguiente=NULL; if(anterior==NULL && Cola.primero ==NULL){ Cola.primero=p } } Y as simplemente asignamos p como el primer elemento de la cola.

2.-ltimo de la cola:
Si queremos insertar un elemento al final de la cola sabemos que el Anterior!=NUL y el Anterior Siguiente Siguiente=NUL (equivalente a Actual Siguiente) Pseudocdigo: P: punter a Nodo Assignar(p) Si(p!=NUL) /*Comprovamos que nos ha asignado memoria*/ p num numero P Siguiente NUL Si(Anterior!=NUL AND Anterior Siguiente =NUL) /*Comprovamos anterior no es nulo*/ Anterior Siguiente p Fisi Fisi En C: Struct Nodo *p; p=(Struct Nodo*)malloc(sizeof(Struct Nodo)); /*Simplemente dice que guarde una parte de la memoria dinamica del tamao de struct nodo, y que p apunte a ella*/ if(p!=NUL){ p num= numero p Siguiente=NULL;

if(anterior!=NULL && Anterior Siguiente =NULL){ Anterior Siguiente=p } } De modo que anterior Siguiente ser p.

3.-Agrupando Casos:
Podemos agrupar los casos para que sea mas compacto el aadir. Pseudocdigo: P: punter a Nodo Assignar(p) Si(p!=NUL) p num numero p Siguiente NUL Si(Anterior=NUL) /*Caso 1*/ Cola.primero p Sino /*Casos 2/ Anterior Siguiente p Fisi Fisi En C: Struct Nodo *p; p=(Struct Nodo*)malloc(sizeof(Struct Nodo)); if(p!=NULL){ p num=numero; p Siguiente=NULL; If(Anterior==NULL){ P Siguiente=Cola.primero Cola.primero=p } else { p Siguiente=Anterior Siguiente Anterior Siguiente=p; } }

-Eliminar elemento en una Cola:


Bueno, antes hemos visto como aadir un elemento a una cola, ahora veremos el otro caso como eliminarlo. Para eliminar un elemento a una cola, debemos distinguir diferentes casos: 1.-nico elemento de la cola. 2.-ltimo de la lista. 3.-Agrupando Casos

1.-nico elemento de la cola:


Para eliminar el nico elemento de una cola sabemos que el Anterior=NUL y el Anterior Siguiente Siguiente (equivalente a Actual Siguiente)=NUL, ya que nos pondremos en la cabeza de la cola. En este caso usaremos P como el puntero al elemento a eliminar en vez de usarlo para el elemento a aadir.

Pseudocdigo: P: punter a Nodo Si(Anterior=NUL AND Cola.primero Siguiente=NUL) p Cola.primero Cola.primero NUL Fisi Alliberar(p); En C: Struct Nodo *p; If(Anterior==NULL && Cola.primero Siguiente==NULL){ P=Cola.primero Cola.primero=NUL } Free(p);

2.-Ultimo elemento de la cola:


Para eliminar el elemento que esta al final de una cola sabemos que el Anterior!=NUL y que el Anterior Siguiente Siguiente (equivalente a Actual)=NUL. Pseudocdigo: P: punter a Nodo Si(Anterior!=NUL AND Anterior Siguiente Siguiente=NUL) p Anterior Siguiente Anterior Siguiente NUL Fisi Alliberar(p); En C: Struct Nodo *p; If(Anterior!=NULL && Anterior Siguiente Siguiente==NULL){ P=Anterior Siguiente; Anterior Siguiente=NULL; } Free(p);

3.-Agrupando Casos:
Podemos agrupar los casos de eliminar de la siguiente forma: Pseudocdigo: P: punter a Nodo Si(Anterior=NUL) P Cola.primero Cola.primero NUL Sino P Anterior Siguiente Anterior Siguiente NUL Fisi Alliberar(p); En C: Struct Nodo *p; If(Anterior==NULL){ P=Cola.primero; Cola.primero= NULL; } else { P=Anterior Siguiente; Anterior Siguiente= NULL; } Free(p);

5.1.-LIFO

-Qu son?
Las LIFO o pilas, son aquellas en que el primer elemento en entrar es el ultimo en salir, eso lo podemos asociar a cualquier accin en la vida normal como ir a apelotonar libros, platos, etc. (Caso concreto listas). Para crear una pila dinmica utilizamos los siguientes registros: En Pseudocdigo: Nodo= registro( numero: entero Siguiente: punter a Nodo ) Pila = registro(top: punter a Nodo )

En C: Struct Nodo{ Int Numero; Struct Nodo *Siguiente; }: Struct Pila{ Struct Nodo *Top; }; Podemos apreciar que realmente estamos usando dos punteros, el siguiente unir todos los nodos entre si para poder recorrer su informacin. Y el top indicar el punto de arriba del todo de la pila. Es punto de fin es tan fcil como detectar que el siguiente de un nodo no existe.

-Recorrer una Pila:


Para recorrer una pila, hacemos exactamente lo mismo que cuando recorres una lista genrica, pero recorre del ltimo elemento al primero.

-Aadir Elemento a pila:


En este caso de las pilas solo hay un caso es lo que se le llama normalmente push de pila. Cuando aades un elemento a la pila simplemente subes el top al nuevo elemento. Pseudocdigo: P: punter a Nodo Asignar(p); Si(p!=NUL) p num numero P Siguiente Pila.Top Pila.Top p Fisi En C: Struct Nodo *p; P= (Struct Nodo*)malloc(sizeof(Struct Nodo)); If(p!=NULL){ p num=numero; P Siguiente=Pila.Top; Pila.Top= p; }

-Eliminar Elemento a pila:


En este caso de las pilas para eliminar un elemento tambin solo hay un caso que se le llama normalmente pop de pila. Cuando eliminar un elemento de la pila bajas el top. Pseudocdigo: P: punter a Nodo Si(Pila.Top!=NUL) P Pila.Top Pila.Top p Siguiente Fisi Alliberar(p) En C: Struct Nodo *p; P= (Struct Nodo*)malloc(sizeof(Struct Nodo)); If(Pila.Top!=NULL){ P=Pila.Top; Pila.Top= p Siguiente; } Free(p);

6.-Diferencias entre una Cola y una Pila:


1.- Los enlaces entre los nodos de la pila son de arriba abajo y los de la Cola de derecha a izquierda. 2.- El top se situa en el elemento final de la pila y en cambio en la cola el primero se situa en el primer elemento de la cola. 3.- Se recorren a la inversa (la pila de top a primero y la cola de primero a ultimo). Representacin grafica: -Pila:

-Cola:

También podría gustarte