pilas 3.1 lista listafelipealanis.org/itd/estructuras de datos/2x u3.pdfal final, la pila polish...

27
Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango 1 3.1 Pilas Consideremos un programa como el siguiente: El Sistema Operativo controla la ejecución de los programas siguiendo unas reglas básicas: El programa main (C++) se ejecuta en primer lugar. Luego se ejecuta la primera instrucción dentro de main. Al terminar la ejecución de una instrucción, se continúa a la siguiente. Una instrucción puede ser el nombre de un subprograma. Al iniciar la ejecución de una instrucción se anota su nombre en una lista. Si esa lista contiene nombres de instrucciones aun no terminadas, estos se conservan y el nuevo nombre se añade al final de la lista. Mientras una instrucción se encuentra en ejecución, su nombre se mantiene anotado en la lista. Cuando una instrucción termina, su nombre se remueve de la lista. Si una instrucción se borra de la lista, la instrucción que queda ahora al final es la que continuará su ejecución. #include <iostream> using namespace std; void SubProg1(); void SubProg2(); void SubProg3(); void SubProg4(); int main() { system("cls"); SubProg4(); SubProg1(); system("pause"); } void SubProg4() { printf("A"); }; void SubProg2() { printf("B"); }; void SubProg3() { printf("C"); }; void SubProg1() { printf("D"); SubProg3(); SubProg2(); }; Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango 2 Lista Lista Lista Lista ** Vacía ** main main system main Lista Lista Lista Lista Main SubProg4 main SubProg4 printf main SubProg4 main Lista Lista Lista Lista Main SubProg1 main SubProg1 printf main SubProg1 main SubProg1 SubProg3 Lista Lista Lista Lista main SubProg1 SubProg3 printf main SubProg1 SubProg3 main SubProg1 main SubProg1 SubProg2 Lista Lista Lista Lista main SubProg1 SubProg2 printf main SubProg1 SubProg2 main SubProg1 main Lista Lista Lista main system main ** Vacía **

Upload: vulien

Post on 17-Apr-2018

226 views

Category:

Documents


2 download

TRANSCRIPT

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

1

3.1 Pilas Consideremos un programa como el siguiente: El Sistema Operativo controla la ejecución de los programas siguiendo unas reglas básicas: • El programa main (C++) se ejecuta en primer lugar. • Luego se ejecuta la primera instrucción dentro de main. • Al terminar la ejecución de una instrucción, se continúa a la siguiente. • Una instrucción puede ser el nombre de un subprograma. • Al iniciar la ejecución de una instrucción se anota su nombre en una lista. • Si esa lista contiene nombres de instrucciones aun no terminadas, estos se

conservan y el nuevo nombre se añade al final de la lista. • Mientras una instrucción se encuentra en ejecución, su nombre se mantiene

anotado en la lista. • Cuando una instrucción termina, su nombre se remueve de la lista. • Si una instrucción se borra de la lista, la instrucción que queda ahora al final es

la que continuará su ejecución.

#include <iostream> using namespace std; void SubProg1(); void SubProg2(); void SubProg3(); void SubProg4(); int main() { system("cls"); SubProg4(); SubProg1(); system("pause"); } void SubProg4() { printf("A"); }; void SubProg2() { printf("B"); }; void SubProg3() { printf("C"); }; void SubProg1() { printf("D"); SubProg3(); SubProg2(); };

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

2

Lista Lista Lista Lista

** Vacía **

� main

� main system

� main

Lista Lista Lista Lista Main SubProg4

� main SubProg4 printf

� main SubProg4

� main

Lista Lista Lista Lista Main SubProg1

� main SubProg1 printf

� main SubProg1

� main SubProg1 SubProg3

Lista Lista Lista Lista main SubProg1 SubProg3 printf

� main SubProg1 SubProg3

� main SubProg1

� main SubProg1 SubProg2

Lista Lista Lista Lista main SubProg1 SubProg2 printf

� main SubProg1 SubProg2

� main SubProg1

� main

Lista Lista Lista main system

� main � ** Vacía **

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

3

� La lista que acabamos de usar es una PILA.

� Cabe aclarar que no se guardan en la pila los nombres de los subprogramas sino direcciones de memoria donde continuará la ejecución una vez terminado el código equivalente al subprograma.

� El ejemplo de las páginas previas es una herramienta didáctica.

� La aplicación de pilas que acabamos de conocer es una de las más importantes. � Las pilas son estructuras UEPS o LIFO. � Mas tarde estudiaremos otras aplicaciones de las pilas. � Se puede crear una pila con un “arreglo dinámico”, si:

� Cada nuevo elemento de la lista se añade al final del arreglo y,

� Cuando se deba eliminar un dato, sea el de la última posición. � Otro enfoque de la misma solución es, en vez de llamar a variable “long”,

llamarla “top” y entenderla como un apuntador a la siguiente dirección disponible del vector.

Diferentes estados de una pila en un vector (el tamaño físico del vector es 5).

Top � 4 4 E 4 3 3 D 3 2 Top � 2 C 2 1 B 1 B 1

Top � 0 A 0 A 0

Pila Vacía

Pila Típica

Pila Llena

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

4

Diferentes estados de la misma pila, si las direcciones del vector fueran desde 1 hasta 5

5 5 Top � E 5 4 4 D 4 3 3 C 3 2 Top � B 2 B 2 1 A 1 A 1

Top �

Pila Vacía

Pila Típica

Pila Llena

Clase Pila

Métodos

Seudocódigo

Observaciones

Constructor top 0

push

vector[ top ] dato top++

Guardar un dato en la pila

pop

top - - resulta vector[ top ]

Elimina un dato De la pila

vacia si top == 0 resulta true

llena

si top == max resulta true

vector Top

0 1 2 3 4 5 6 . . . . . . . max-1

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

5

Ejercicios:

a) Escriba la clase Pila.

#define TamVector 1000 class Pila { private: int top; char vector[TamVector]; public: Pila() {top=0;}; void push(char x) {vector[top]=x;top++;}; char pop() {top--;return vector[top];}; bool vacia() {return (top= =0);}; bool llena() {return (top= =TamVector);}; };

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

6

b) Escriba un programa que compruebe si cierta frase es un palíndroma. PALINDROMAS:

Anilina Dábale arroz a la zorra el abad

NO SON PALINDROMAS: Estructuras de Datos Dábale el abad arroz a la zorra

#include <iostream> using namespace std; #include "pila.h" int main() { char frase[200]; cout << "Escribe una frase: ";gets(frase); Pila x1,x2,x3; for(int i=0;frase[i]!=0;i++) if (frase[i]!=32) {x1.push(frase[i]); x2.push(frase[i]);}; while (!x1.vacia()) x3.push(x1.pop()); bool palindroma=true; while (!x2.vacia()) if (x3.pop()!=x2.pop()) palindroma=false; if (palindroma) cout << "ES PALINDROMA\n"; else cout << "**NO** ES PALINDROMA\n"; system("pause"); return 0; }

Elimine el constructor de pilas.h y consulte el valor de top de cada pila. ¿Podrá hacerlo de esta manera?: cout << x1.top << x2.top << x3.top << endl; system("pause");

Ignora los espacios. Añada lo suficiente para que también ignore la H, acentos y para que no importa si algunas letras están escritas con mayúsculas o minúsculas.

Se invierte el contenido de la pila 1 Se compara lo

que contienen las pilas 2 y 3

¿Hay datos?

Retirar dato

while

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

7

c) Escriba un programa que verifique que una expresión aritmética se encuentre agrupada correctamente. Los símbolos de agrupación a considerar son paréntesis, corchetes y llaves. No se requiere revisar la validez de la expresión desde otro punto de vista, solo de la agrupación. Expresiones Válidas Expresiones Inválidas (a+b)*(c-d) (a+b[3] (a+b)*x[1]+y[2] )x+y[3]( xzy-(*a){ [ ] } a+b[3)+c{1} ((a+b)/(c-d)+x)/{((x+1)/2)/(z-3)} (a[1)+1]*2 a*(b[3]+c{3}) ) { } ( ( ) [ ]

#include <iostream> using namespace std; #include "pila.h" #define PARIZQ '(' // PARentesis #define PARDER ')' #define CORIZQ '[' // CORchetes #define CORDER ']' #define LLAIZQ '{' // LLAves #define LLADER '}' int main() { char expresion[100]; cout << "Expresión con Paréntesis: ";gets(expresion); Pila x; bool correcta=true; for(int i=0;expresion[i]!=0;i++) if (expresion[i]==PARIZQ) x.push(PARDER); else if (expresion[i]==CORIZQ) x.push(CORDER); else if (expresion[i]==LLAIZQ) x.push(LLADER); else if ((expresion[i]==PARDER)or(expresion[i]==CORDER) or(expresion[i]==LLADER)) if (x.vacia()) correcta=false; else if (expresion[i]!=x.pop()) correcta=false; if (!x.vacia()) correcta=false; if (correcta) cout << "EXPRESIÓN VALIDA\n"; else cout << "EXPRESIÓN INVÁLIDA\n"; system("pause"); return 0; }

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

8

Conversión de Expresiones Aritméticas a la Forma Sufija Forma infija Forma sufija equivalente a+b ab+ a+b*c abc*+ (a+b)*c ab+c* (a+b)^2*(c-d) ab+2^cd-* Jerarquía de operadores (cierto lenguaje) de mayor a menor:

1) ^ potencia 2) * / multiplicación y división 3) + - suma y resta

• Las expresiones en la forma sufija se evalúan de izquierda a derecha. • El primer operador que se encuentre, se aplica a los 2 operandos previos. • El resultado obtenido se convierte en un operando y se inicia de nuevo desde la

izquierda la búsqueda de un operador. Compilación: Evaluación:

(a+b)*(c+d) ab+cd+*

a b + c d + *

R1 c d + *

R1 R2 *

Lenguajes de Alto Nivel

Expresiones Infijas

El operador entre los operandos

Pueden usarse

paréntesis

Lenguaje Máquina

Expresiones Sufijas

El operador sucede a los operandos

No hay paréntesis

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

9

Algoritmo para la conversión de una expresión infija a la forma sufija

a) Se usarán dos pilas, llamadas pila de operadores y pila polish. b) La expresión infija se encontrará en un string. c) Si la expresión contiene paréntesis, debe estar correctamente agrupada. d) Los elementos de la expresión solo pueden ser de un carácter de longitud y sin espacios.

Al final, la pila polish contendrá la expresión sufija, en orden inverso, para obtenerla en el orden correcto, hay que transferir uno a uno los elementos a la pila de operadores (luego se retiran para obtenerla en el orden esperado). Referencias: 1. Un operando es una variable o una constante. 2. Se asumirá que es el primer operador que llega verificando si la pila de

operadores está vacía, o si en el tope de ella hay un paréntesis izquierdo. 3. El último que entró, es decir, el que corresponde con el paréntesis derecho que

ha llegado. Ejercicio: Escriba un programa en C++. Siga las reglas que se indican al inicio

para que no se complique innecesariamente. Nota: Este algoritmo no considera casos de operadores unitarios.

Se repetirá el siguiente procedimiento para cada elemento de la expresión infija: � Se toma un elemento de la expresión infija � Si es un operando1 se guarda en la pila polish. � Si es operador o paréntesis, se tomará en cuenta lo siguiente:

� Si es el primer operador que llega2 o es un paréntesis izquierdo, se guarda en la pila de operadores.

� Si el elemento que llega es un paréntesis derecho, se transfieren uno a uno los operadores de la pila de operadores hacia la pila polish hasta que se encuentre un paréntesis izquierdo3, luego se desechan ambos paréntesis.

� Si no se trata de ninguno de los dos casos anteriores, se comparará la jerarquía del operador que está en la cima de la pila de operadores con la del operador que quiere entrar: � Si la jerarquía del operador que llega es mayor que la jerarquía

del operador que está en la cima, se almacena el operador que llega, en la pila de operadores.

� En caso contrario, se transfiere el operador que está en la cima de la pila de operadores hacia la pila polish y de nuevo se hace la comparación entre el operador que llega y el que ahora queda en la cima de la pila de operadores.

� Una vez que ya no haya elementos en la expresión infija, se transfieren

uno a uno los operadores de la pila de operadores hacia la pila polish.

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

10

3.2 Colas � Estructuras muy importantes. � Una aplicación que fácilmente se puede identificar: impresión en una red.

• Un usuario de la red desea imprimir un documento. • La impresora está disponible. • El documento es de tamaño importante. • Casi simultáneamente otros tres usuarios desean imprimir pero la impresora

está ocupada. • ¿A cual de los tres se le asignará la impresora? • ¿Cuándo se le asignará?

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

11

Otros caso de impresión: • En un ambiente monousuario (multitarea o no), las colas de impresión evitan

“cuellos de botella”. • Es más rápido el envío de datos hacia la impresora que la impresión misma. • El usuario puede dejar sin atender el equipo mientras imprime.

Otra aplicación: Un sistema operativo multitarea debe distribuir el tiempode operación del CPU para atender las tareas que corren “simultáneamente” durante la operación regular del equipo, por ejemplo:

� Antivirus � Reproductor de CD � Microsoft Word

Tareas “simultáneas”

Cola de impresión

Las colas son estructuras de datos PEPS (Primeras Entradas, Primeras Salidas) o FIFO (First Input, First Output).

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

12

3.2.1 Cola con corrimiento. � Las colas en los sistemas son como las de un Banco o del cine. � Solo que no atienden personas, sino procesos o tareas. � Una cola con corrimiento guarda en un vector los datos de los procesos en

el orden que serán atendidos cuando sea posible. � Una cola siempre inicia vacía y su tamaño cambia continuamente. � Respuesta: “Dinámico”. � Cada dato que se va a colocar en espera se añadirá al final del arreglo. � Los datos que ya no tienen que esperar en la cola (por ejemplo, tareas de

impresión cuya atención se inició) deben ser eliminados del arreglo. � En una cola típica, el dato del frente (posición 0 del arreglo) es el que se

elimina. Los siguientes son dos arreglos dinámicos en cierto momento (el primero es una cola de impresión y el segundo una aplicación cualquiera no especificada).

3 uni-1.doc ejemp5.pas uni-2.doc

0 1 2 . . . 99

numdatos vector

6 w x d g b k

0 1 2 3 4 5 6 7 . . . . . . max-1

numdatos vector

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

13

Método

Objetivo y Observaciones

Seudocódigo

Constructor

� Se asegura que la cola esté vacía.

� Equivale a ModifTam(0)

numdatos ←←←← 0

Entra

� Añade un nuevo dato a la cola.

� Equivale a Añadir(dato)

vector[numdatos] ←←←← dato numdatos++

Sale

� Recupera el dato al que toca turno y lo retira de la cola.

� Equivale a Eliminar(0)

Resulta vector[0] Para i ←1 hasta numdatos-1 ejecutar vector[ i – 1 ] ← vector[ i ] numdatos--

Vacia � Indica si la cola no

tiene ningún dato en espera.

Si numdatos=0 Resulta TRUE

Llena � Indica si no hay

capacidad en la cola para un dato más.

si numdatos=max Resulta TRUE

Ejercicio

Escribir un programa que realice lo siguiente: • Tomar una frase del teclado. • Guardar cada uno de los caracteres en una cola llamada x1. • Repetir cierto número de veces las dos secuencias siguientes:

• Hasta que x1 quede vacía, ejecutar: • Tomar de la cola x1 un valor e imprimirlo. • Hacer un retraso de 1 seg. y guardar el dato en otra cola llamada x2.

• Hasta que x2 quede vacía, ejecutar: • Tomar un valor de la cola x2 e imprimirlo. • Hacer un retraso de 1 segundo y guardar el dato en x1.

0 1 2 3 4 5 6 . . . . . . . . . max-1

numdatos vector

Clase Cola

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

14

// cola.h #define MaxCola 100 class Cola { private: int numdatos; char vector[MaxCola]; public: Cola(); void entra(char); char sale(); bool vacia(); bool llena(); }; Cola::Cola() { numdatos=0; }; void Cola::entra(char x) { vector[numdatos]=x; numdatos++; } char Cola::sale() { char temp=vector[0]; for(int i=1;i<numdatos;i++) vector[i-1]=vector[i]; numdatos--; return temp; } bool Cola::vacia() { return (numdatos==0); }; bool Cola::llena() { return (numdatos==MaxCola); };

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

15

// marquesina.cpp #include <iostream> using namespace std; #include "cola.h" void delay(int); int main() { char frase[50]; cout << "Escribe una frase: ";gets(frase); int veces; cout << "Número de Veces: ";cin>>veces; Cola x1,x2; for(int i=0;frase[i]!=0;i++) x1.entra(frase[i]); char letra; for(int i=0;i<veces;i++) { while (!x1.vacia()) { delay(1); letra=x1.sale(); cout<<letra; x2.entra(letra); }; cout << endl; while (!x2.vacia()) { delay(1); letra=x2.sale(); cout<<letra; x1.entra(letra); }; cout << endl; }; system("pause"); return 0; } void delay(int seconds) { time_t start_time, cur_time; time(&start_time); do time(&cur_time); while((cur_time - start_time) < seconds); };

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

16

3.2.2 Cola Simple

desventaja

movimiento innecesario

apuntadores frente atrás

numdatos

0 1 2 3 4 5 6 . . . . . . . . . max-1

0 2 A B C

Contendrá la dirección del dato al que le

tocará el siguiente turno

Contendrá la dirección del último dato que

entró a la cola

0 1 2 3 4 5 6 . . . . . . . . . max-1

frente atrás vector

Nueva estructura de los datos de la clase Cola

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

17

Métodos de la clase Cola

Métodos

Seudocódigo

constructor atrás ← −−−−1 frente ← 0

entra Mover atrás a la siguiente dirección vector[atrás] ←←←← dato

sale Resulta vector[frente] Mover frente a la siguiente dirección

vacia Si frente>atrás Resulta TRUE

llena si atrás=max-1 Resulta TRUE

Resumen:

Ejercicio

Escriba la clase Cola en C++ bajo el criterio de cola simple. Pruébela con la aplicación marquesina.cpp, solo asegúrese de que el número de veces de impresión multiplicado por la longitud de la frase exceda el valor de MaxCola para que pueda comprobar lo que se explica a continuación.

1 2 B C

0 1 2 3 4 5 6 . . . . . . . . . . max-1

La “A” sigue estando en la dirección 0, pero la ocultamos para evitar

distracción.

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

18

“agota”

ventaja¿Cuál?

¿Cómo aprovechar esa ventaja?

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

19

3.2.3 Cola Circular

C D E

Mejor usar un vector circular.

Se hace una conexión lógica entre la última dirección del vector y la primera

3 4 2 5 1 6 0 7

Frente Atrás

0 1 2 3 4 5

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

20

En una cola simple atrás -1 y frente 0

En un vector circular atrás Max-1 y frente 0

Métodos

Seudocódigo

constructor atrás ← Max−−−−1 frente ← 0

entra Mover atrás a la siguiente dirección vector[atrás] ←←←← dato

sale Resulta vector[frente] Mover frente a la siguiente dirección

vacia Si frente>atrás Resulta TRUE

llena si atrás=max-1 Resulta TRUE

A continuación probaremos los métodos de la cola simple (con

la única modificación del constructor).

Estado Inicial de la Cola

3 4 2 5 1 6 0 7

Frente Atrás

Observe que podría quedar −−−−1 igual que en la cola simple, es decir sin incorporar ningún cambio

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

21

La cola está llena evidentemente …

Añadir E,F,G,H

D E 3 4

C F 2 5 1 6

B 0 7 G

A H

Frente Atrás

Añadir A, B, C, D

Atrás

D 3 4

C 2 5

1 6

B 0 7

A Frente

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

22

¿En que posiciones se encuentran “frente” y

“atrás”?

¿En que posiciones estaban cuando la cola estaba vacía?

Retiremos 8 datos uno a uno, ¿en que posiciones quedarán “frente” y “atrás”?

Añadir I

D E 3 4

C F 2 5 1 6

B 0 7 G

I H Frente Atrás

Sale un dato

D E 3 4

C 2 5 F 1 6

B 0 7 G

H Frente Atrás

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

23

La secuencia se controla bien con los apuntadores ….

Solo resta determinar los estados vacia y llena

clase Cola “circular”

Método

Seudocódigo

constructor

Atrás Max-1 Frente 0 Contador 0

entra

Mover atrás a la siguiente dirección ( significa sumar 1, excepto cuando atrás=Max-1, en tal caso Atrás0 ) vector[atrás] ←←←← dato contador++

sale

Resulta vector[frente] Mover frente a la siguiente dirección ( significa sumar 1, excepto cuando frente=Max-1, en tal caso frente0 ) Contador--

vacia

Si Contador = 0 Resulta TRUE

llena

Si Contador=Max Resulta TRUE

Ejercicio: Escriba la clase Cola “circular”.

vector frente atrás contador

0 1 2 3 4 5 …. Max-1

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

24

3.3 Listas Encadenadas

3.3.1 Listas Simples

Vectores

Lista Lineal (Los datos se organizan en una sola ruta) Lista Secuencial (los datos adyacentes en forma lógica se encuentran también físicamente juntos) Estructura estática (espacio reservado durante la compilación). Tiende al desperdicio de memoria ya que el espacio se libera hasta que termina el ámbito donde se declaró.

Listas Encadenadas

Lista Lineal Lista NO SECUENCIAL Estructura dinámica (sin necesidad de que se cierre el ámbito donde se reservó cierto espacio, puede liberarse esa memoria ocupada de manera que pueda ser utilizada de nuevo por el mismo u otro proceso, posteriormente).

• Manejo Estático referencia directa a los datos. o Variable = dato

0006 000A 000C 000E 0010 0012

i

123

short int i; i=123;

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

25

• Manejo Dinámico de la memoria referencia indirecta a los datos.

o Variable � dirección = dato

Características de las Listas Encadenadas 1. Cada elemento de la lista es independiente (NODO).

• NODO = lugar en la memoria, reservado durante la ejecución, para un dato.

• Apuntador = Variable que contiene la dirección de nodo. • Los Nodos son Independientes entre sí ya que se reservan

uno a uno. Pregunta: ¿Los elementos de un vector son independientes?, ¿pueden desprenderse físicamente de él?.

2. Los NODOS de una lista simple son estructuras con dos datos miembros.

• La primera parte es el lugar que corresponde al dato en sí. • La segunda contendrá la dirección de OTRO NODO (el siguiente

en la lista).

Información Dirección del Nodo siguiente

000A 000C 000E 0010 0012

p

0010

123

short int *p; p = new int; *p=123; delete p;

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

26

3. El último nodo de la lista no tendrá un nodo siguiente.

• Se guarda en el campo del “nodo sucesor” un valor que indique el final de la lista (dirección inválida).

4. Variable CABEZA DE LISTA.

• La dirección del 2º nodo se conserva en el primer nodo, la del último en el penúltimo, etc.

• ¿Dónde se guardará la dirección del primer nodo? o En una VARIABLE tipo apuntador llamada CABEZA DE

LISTA.

X

L

Y

B

R

Cabeza de Lista

Representación común de una lista encadenada simple

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

27

Otras dos representaciones (los valores numéricos decimales encima de cada nodo representan una supuesta

dirección de memoria):

Y

150

2 0 0

R

123

F IN

X

410

5 4

6

L

546

1 5 0

B

200

1 2 3

410

Cabeza de Lista

Cabeza de Lista

R

123

F

I

N

X

410

5 4

6

Y

150

2 0 0

L

546

1 5

0

B

200

1 2 3

410

Memoria reservada Memoria disponible durante compilación para manejo dinámico durante la ejecución (montón –heap-)

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

28

Algoritmos Generales para la Operación de una Lista Encadenada

Simple

a) El nuevo nodo debe ser el primero de la lista: � Guardar en el campo sucesor del nuevo nodo la dirección que se

encuentra en la variable cabeza de lista. � Guardar en la variable cabeza de lista la dirección del nuevo nodo.

b) El nuevo nodo debe ser el último de la lista: � Guardar NULL en el campo sucesor del nuevo nodo. � Localizar la dirección del último nodo. � Guardar en el campo sucesor del último nodo la dirección del nuevo nodo.

c) El nuevo nodo debe quedar entre dos nodos ya existentes: � Denominemos temp1 y temp2 a los nodos que serán adyacentes al

nuevo nodo. � Guardar en el campo sucesor del nuevo nodo la dirección del temp2. � Guardar en el campo sucesor de temp1 la dirección del nuevo nodo.

Insertar

• Se solicita primero al Sistema Operativo, una dirección de memoria disponible.

• Se guarda el nuevo dato en el campo "info" del nuevo nodo.

• De acuerdo al uso que le demos a la lista, se aplicará uno de los 3 siguientes casos.

a) Borrar el primer nodo: � Guardar en cabeza de lista la dirección que se encuentra en el campo

sucesor del primer nodo. b) Eliminar el último nodo:

� Guardar NULL en el campo sucesor del penúltimo nodo. c) Eliminar un nodo que se encuentra entre otros dos:

� Siendo temp1 y temp2 los nodos adyacentes: hay que guardar en el campo sucesor del temp1 la dirección del temp2.

Eliminar

• Cada aplicación determinará cual nodo se eliminará. • Puede presentarse uno de los tres casos siguientes.

• Una vez eliminado (“desprendido de la lista”) un nodo, hay que avisar al S.O. su dirección de memoria, para que pueda ser aprovechado posteriormente.

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

29

Primera Aplicación de Listas Encadenadas

Pilas Pila = Lista en la que se retiran los datos por el mismo extremo por donde se

acumulan. Se resuelve muy fácilmente con una lista encadenada, haciendo que cada nodo que entre quede como el primero de la lista, y siempre que se deba retirar un dato, sea el que se encuentre apuntado por la cabeza de la lista.

Notas � Las listas encadenadas siempre inician vacías (cabeza de lista fin). � Algunos algoritmos de los que hemos analizado requieren que se haga un

recorrido de la lista. Recorrer la lista = visitar todos o algunos de los nodos. Ejemplo: Algoritmo para imprimir todos los nodos de una lista

1.- Asignar a una variable, podemos llamarla temp, la dirección del primer nodo. 2.- Si la variable contiene FIN, termina el algoritmo. 3.- Ir al Nodo correspondiente a temp e imprimir su información. 4.- Asignar a temp, la dirección del nodo siguiente. 5.- Ir al paso 2.

Entra A A Entra B B

A

C

B

A

Retirar un dato

Entra C B

A

Retirar otro dato A

Retirar otro dato

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

30

Datos de la Clase Pila con un vector

Datos de la Clase Pila con una Lista Encadenada

vector top

0 1 2 3 4 5 6 . . . . . . max-1

Cabeza de Lista

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

31

Pila en una lista enlazada class Pila { private: struct Nodo { char info; Nodo *sucesor; }; Nodo *cabeza; public: Pila(); void push(char x); char pop(); bool vacia(); bool llena(); ~Pila(); }; Pila::Pila() { cabeza=NULL; }; void Pila::push(char x) { Nodo *temp; temp=new Nodo; temp->info = x; temp->sucesor = cabeza; cabeza = temp; }; char Pila::pop() { Nodo *temp=cabeza; char result=cabeza->info; cabeza=cabeza->sucesor; delete temp; return result; };

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

32

bool Pila::vacia() { return (cabeza==NULL); }; bool Pila::llena() { return (false); }; Pila::~Pila() { // cout << "Ejecutando el destructor... "; // system("pause"); Nodo *temp; while (cabeza!=NULL) { // cout << "Borrando un nodo... "; // system("pause"); temp=cabeza; cabeza=cabeza->sucesor; delete temp; }; };

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

33

Pila en una lista enlazada class Pila { private: struct Nodo { char info; Nodo *sucesor; }; Nodo *cabeza; public: Pila(); void push(char x); char pop(); bool vacia(); bool llena(); ~Pila(); }; Pila::Pila() { cabeza=NULL; }; void Pila::push(char x) { Nodo *temp; temp=new Nodo; temp->info = x; temp->sucesor = cabeza; cabeza = temp; }; char Pila::pop() { Nodo *temp=cabeza; char result=cabeza->info; cabeza=cabeza->sucesor; delete temp; return result; };

Guardar temporalmente la dirección del primer nodo, para liberarla (con delete) antes de cerrar el ámbito.

Pruebe este header file (llámelo pila.h) con las aplicaciones de pilas que ya escribimos, por ejemplo la de revisión de agrupación de paréntesis. Renombre el antiguo pila.h para que lo conserve.

Para construir una lista encadenada se requiere una estructura con 2 datos miembros al menos (el dato y un apuntador a otro nodo)

Apuntador al primer nodo de la lista

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

34

bool Pila::vacia() { return (cabeza==NULL); }; bool Pila::llena() { return (false); }; Pila::~Pila() { // cout << "Ejecutando el destructor... "; // system("pause"); Nodo *temp; while (cabeza!=NULL) { // cout << "Borrando un nodo... "; // system("pause"); temp=cabeza; cabeza=cabeza->sucesor; delete temp; }; };

Retire los // para que compruebe el funcionamiento del destructor.

Asumiremos aquí que siempre va a haber espacio.

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

35

Segunda Aplicación de Listas Encadenadas

Colas

Cola = Lista cuyos elementos se acumulan y retiran por extremos opuestos.

Al entrar nuevos datos, se guardan al final. Se retiran del inicio. Se incorpora el uso de un apuntador al final de la Lista (lo llamaremos ultimo).

1. ¿Para qué se requiere el apuntador “último”?

2. Si la condición es que se añadan y retiren los datos por extremos opuestos …

¿Por que no añadirlos al inicio de la lista y retirarlos del final?

A

B

C

D

E

Cabeza

Ultimo

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

36

Clase Cola usando una Lista Encadenada

constructor cabeza y ultimo inician en NULL.

entra() � Guardar el nuevo dato en el campo info de un nuevo nodo. � Guardar NULL en el campo sucesor del nuevo nodo. � Guardar en el sucesor del ultimo nodo la dirección del nuevo nodo.

� Excepto si la lista está vacía. En tal caso, la dirección del nuevo nodo se debe guardar en la variable cabeza.

� Guardar en la variable ultimo la dirección del nuevo nodo.

sale()

� Recuperar el dato contenido en el primer nodo. � Guardar en la variable cabeza la dirección que está en el campo sucesor

del primer nodo. � Caso especial: Si solo resta un nodo en la lista, a la variable ultimo

deberá asignarse NULL.

� Liberar el nodo.

vacia() Si cabeza de lista contiene el valor NULL.

llena() Si no hay memoria suficiente para otro nodo.

Cabeza Ultimo

Cabeza Ultimo

Cabeza

Ultimo

Cabeza Ultimo

Cabeza Ultimo

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

37

class Cola { private: struct Nodo { char info; Nodo *sucesor; }; Nodo *cabeza,*ultimo; public:

Cola(); void entra(char x); char sale(); bool vacia(); bool llena(); ~Cola();

}; Cola::Cola()

{ cabeza=NULL; ultimo=NULL; };

void Cola::entra(char x) { Nodo *temp; temp=new Nodo; temp->info = x; temp->sucesor = NULL; if (cabeza==NULL) cabeza=temp; else ultimo->sucesor=temp; ultimo=temp; }; char Cola::sale() { Nodo *temp=cabeza; char result=cabeza->info; cabeza=cabeza->sucesor; if (cabeza==NULL) ultimo=NULL; delete temp; return result; }; bool Cola::vacia()

{ return (cabeza==NULL); };

bool Cola::llena() { return (false); };

Cola::~Cola() { Nodo *temp; while (cabeza!=NULL) { temp=cabeza; cabeza=cabeza->sucesor; delete temp; }; };

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

38

Tercera Aplicación de Listas Encadenadas

Lista Ordenada y

Colas de Prioridades � Cuando usamos una L. E. para pilas o colas:

1. El orden en que los nodos se colocan en la lista, no depende del valor del dato sino de la secuencia de entrada a la lista.

2. El proceso que se sigue durante las altas y las bajas, siempre es el mismo.

� Al añadir datos a una lista que debe permanecer ordenada el nodo para el nuevo dato puede quedar en cualquier parte de la lista.

Procedimiento para Añadir 1. Solicitar un nuevo nodo y guardar el dato en el campo info. 2. Determinar en que parte de la lista debe quedar. Algoritmo:

� Recorrer la lista hasta encontrar un nodo con un dato mayor o igual que el que se va a añadir.

� Use dos variables: temp2 para guardar la dirección del nodo localizado (dato mayor) y temp1 para el nodo anterior.

� El nuevo nodo quedará entre ambos nodos. � Es posible que temp2 valga NULL. � Es posible que no haya un nodo anterior y por lo tanto temp1 también

valga NULL. 3. Enlazar el nuevo nodo.

� Si temp1 contiene NULL, el nuevo nodo deberá quedar al inicio de la lista. � No importa que temp2 valga NULL, basta aplicar el procedimiento para

enlazar un nodo “entre” dos nodos y se obtiene el resultado esperado. Tome como base la siguiente lista para probar el algoritmo anterior.

Cabeza

ALMONTE

CASAS

FUENTES

PEREZ

TORRES

Ejercicio: Escriba un programa con un menú de 2 opciones: (Añadir datos e Imprimir el contenido de la lista).

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

39

#include <iostream> using namespace std; int main()

{ struct Nodo { char info[51]; Nodo *sucesor; }; int opcion; Nodo *cabeza,*temp,*nuevo,*temp1,*temp2; cabeza=NULL; do {

cout << "\nLista Ordenada\n"; cout << "1.- Altas\n" << "2.- Imprimir\n"; cout << "0.- Terminar\n\n"; cout << "Opcion: ";scanf("%d",&opcion); cout << endl;

switch (opcion) { case 0:break; case 1: nuevo=new Nodo; cout<<"Nuevo Dato: ";cin >> nuevo->info; temp1=NULL; temp2=cabeza; while ((temp2!=NULL)and (strcmp(temp2->info,nuevo->info)<0)) { temp1=temp2; temp2=temp2->sucesor; }; if (temp1==NULL) cabeza=nuevo; else temp1->sucesor=nuevo; nuevo->sucesor=temp2; break; case 2: temp=cabeza; while (temp!=NULL) { cout << temp->info << endl; temp=temp->sucesor; } system("pause"); break; } } while (opcion!=0); return 0; }

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

40

Eliminación de Datos de Lista Ordenada Debe considerarse la posibilidad de eliminar cualquier nodo de la lista ordenada, sin importar en donde se encuentra. � Se usan 2 variables temporales tipo apuntador: nodoant y temp. � Temp señala siempre al nodo que se “visita” (empezando en el primer nodo) y

nodoant al nodo anterior (empezando en NULL). � Recorrido.

� Cuando temp llegue a NULL o el nodo temp contenga un dato mayor al que buscamos eliminar, significa que la búsqueda terminó y el dato no está en la lista.

� Por el contrario, si encontramos en un nodo el dato a eliminar, hay que aplicar el algoritmo siguiente: � Si nodoant=NULL, aplicar el procedimiento para eliminar el primer

nodo. � Si nodoant!=NULL aplicar el algoritmo para eliminar un nodo entre

otros dos (si se trata de eliminar el último nodo incluso). Este razonamiento asume que el dato que se pretende eliminar es un dato único en la lista…en caso de no serlo, este proceso de eliminación elimina el primero que se encuentre (estarán consecutivos).

Ejercicio: Complemente el programa para que se puedan efectuar bajas.

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

41

Colas de Prioridades

Estado de una Lista de pacientes esperando que se desocupe una sala de operaciones en cierto hospital: Paciente Edad Tipo de Cirugía Hugo Patito 7 Corregir pie plano Pato Donald 31 Cuerdas vocales Paco Patito 7 Corregir pie plano

Luis Patito 7 Corregir pie plano Cerdo Porky 29 Lipoescultura ¿En que lugar se debería colocar en espera a …. Tío Rico 50 Transplante de riñón …. si, como es evidente, es más importante ésta cirugía que las cinco que ya están en espera? ¿Podría colocarse al frente? En los bancos se presentan situaciones similares: los gerentes y ejecutivos de cuenta son atendidos antes que las personas que esperan. Esto es por razones lógicas ya que hacen muchas operaciones durante el día y no sería practico que tuvieran que esperar continuamente. Supongamos entonces que Tío Rico se coloca al frente … Paciente Edad Tipo de Cirugía Tío Rico 50 Transplante de riñón Hugo Patito 7 Corregir pie plano Pato Donald 31 Cuerdas vocales Paco Patito 7 Corregir pie plano

Luis Patito 7 Corregir pie plano Cerdo Porky 29 Lipoescultura

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

42

… transcurre el tiempo y siguen ocupadas las salas … los pacientes siguen en espera … y llega: Ciro Peraloca 50 Transplante de riñón Si seguimos el mismo razonamiento, lo colocaríamos al frente, porque es una cirugía importante como la de Tío Rico … por lo tanto … quedaría adelante del Tío Rico … ¿sería correcto? Como se puede ver, hay casos de colas en las que se requiere que los datos tengan asociado otro dato: se le llama PRIORIDAD …. La prioridad determina el orden dentro de la cola: � El dato del frente será el de mayor prioridad (valor numérico

menor). � El dato de atrás será el de prioridad menor (valor numérico mayor).

Una cola de prioridades ordena una lista en base a la prioridad de los

datos.

Pregunta:

¿Que debe pasar con los datos que tienen la misma prioridad, como en el caso de Tío Rico y Ciro? ….

Respuesta:

Deben quedar juntos pero adelante el que entró primero

(por esta razón es una COLA). No olvidar que en una cola siempre se eliminará el dato de adelante.

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

43

� Cada nodo debe contener al menos dos miembros “info”, uno para

el dato en sí (que en este caso es una estructura con 3 datos) y otro para la prioridad del dato en la cola.

Como la prioridad es el valor que determina principalmente el orden de la lista, nuestro ejemplo, ya con prioridades, quedaría: Paciente Edad Tipo de Cirugía Prioridad Tío Rico 50 Transplante de riñón 4 Ciro Peraloca 50 Transplante de riñón 4 Cerdo Porky 29 Lipoescultura 8

Hugo Patito 7 Corregir pie plano 10 Pato Donald 31 Cuerdas vocales 10 Paco Patito 7 Corregir pie plano 10 Luis Patito 7 Corregir pie plano 10

¿Que algoritmo usaríamos para encontrar lugar para el siguiente paciente? Pata Daisy 26 Transplante de córnea 4

… Recorrer la lista mientras la prioridad de los datos de la lista sea MENOR O IGUAL que la del nodo que va a entrar … Observe que es básicamente el mismo algoritmo que el de una lista encadenada ordenada, excepto porque en este caso si tiene impacto que se verifique una prioridad menor o una menor o igual …

Valor Prioridad El miembro INFO de Cada Nodo debe ser así:

Podríamos representar los nodos de la siguiente manera:

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

44

¿en donde quedaría el nuevo paciente si se hiciera como en el programa que hicimos de una lista ordenada? Paciente Edad Tipo de Cirugía Prioridad Pata Daisy 26 Transplante de córnea 4

Tío Rico 50 Transplante de riñón 4 Ciro Peraloca 50 Transplante de riñón 4 Cerdo Porky 29 Lipoescultura 8

Hugo Patito 7 Corregir pie plano 10 Pato Donald 31 Cuerdas vocales 10 Paco Patito 7 Corregir pie plano 10

Luis Patito 7 Corregir pie plano 10

Lo correcto desde luego es:

Paciente Edad Tipo de Cirugía Prioridad Tío Rico 50 Transplante de riñón 4 Ciro Peraloca 50 Transplante de riñón 4 Pata Daisy 26 Transplante de córnea 4

Cerdo Porky 29 Lipoescultura 8 Hugo Patito 7 Corregir pie plano 10 Pato Donald 31 Cuerdas vocales 10

Paco Patito 7 Corregir pie plano 10 Luis Patito 7 Corregir pie plano 10 Dos preguntas finales: • De los 8 pacientes de esta lista, ¿quién llegó primero? • Considerando solo a los 4 últimos, ¿quién llegó primero?

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

45

Listas con nodo cabecera En algunos casos es deseable que una lista encadenada contenga un nodo extra al inicio. Ese nodo puede contener información de diferente tipo que los demás. Ejemplos: 1. La lista contiene datos relativos a los componentes de un objeto.

2. Una lista de la que se desea conocer en cualquier momento el número total de nodos, o el número de nodos que cumplan con algún criterio.

Cabeza

Vectores

Pilas

Colas

Listas Enlazadas

4

Cabeza

Vectores

Pilas

Colas

Listas Enlazadas

Curso Est Datos

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

46

3. La lista es una cola y se guarda la dirección del último nodo en el nodo

cabecera. 4. Más de uno de los casos anteriores combinados en el mismo nodo.

Como se ve, los nodos cabecera pueden ser de un tipo distinto de los nodos regulares, solo hay que cuidar que: 1. El campo sucesor del nodo cabecera sea del tipo apuntador de los nodos

regulares. 2. La variable cabeza de lista sea de tipo apuntador del nodo cabecera. Ejercicio: Escriba un programa para una lista ordenada usando nodos cabecera (aunque no guarde ningún dato en ese nodo)

Cabeza

Vectores

Pilas

Colas

Listas Enlazadas

4 Curso

Est Datos

B

C

D

E

Cabeza

Algunos programadores prefieren nodos cabecera aunque no guarden información alguna en ellos porque los algoritmos se simplifican ya que todos los nodos tienen un nodo anterior.

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

47

Recuperación de espacio en listas encadenadas � Usualmente pensamos en Listas Encadenadas en RAM. � Se puede aplicar el concepto a un archivo de acceso directo.

Ejemplo: � Pensemos en un programa que haga lo siguiente: � Guardar en un archivo de acceso directo los datos de los aspirantes a

ingresar a una escuela. � Los datos de cada nueva solicitud se añadirán al archivo a una

nueva dirección. � Obtener en cualquier momento una Lista ordenada alfabéticamente

por el nombre del aspirante.

Solución: � Usar una lista simple. � Cada registro (estructura) del archivo será un nodo de la lista. � Guardar los registros empezando con la dirección 1. � El registro 0 contendrá la dirección del primer nodo de la lista

(cabeza).

Los siguientes aspirantes hicieron su solicitud en el orden indicado: Mickey Mouse, Johnny Bravo, Winnie the Pooh, Fenomenoide, Alvin y las ardillas, Batman, Robin, Pato Donald, Goofy, Kalimán

Archivo luego de las altas (las direcciones a propósito ocultas):

0

1 Mickey Mouse

2 Johnny Bravo

3 Winnie the Pooh

4 Fenomenoide

5 Alvin y las ardillas

6 Batman

7 Robin

8 Pato Donald

9 Goofy

10 Kalimán

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

48

paso a paso:

0 -1 0 1

1 Mickey Mouse -1

0 2

1 Mickey Mouse -1

2 Johnny Bravo 1

0 2

1 Mickey Mouse 3

2 Johnny Bravo 1

3 Winnie the Pooh -1

4 Fenomenoide 2

0 4

1 Mickey Mouse 3

2 Johnny Bravo 1

3 Winnie the Pooh -1

5 Alvin y las ardillas 4

4 Fenomenoide 2

0 5

1 Mickey Mouse 3

2 Johnny Bravo 1

3 Winnie the Pooh -1

6 Batman 4

5 Alvin y las ardillas 6

4 Fenomenoide 2

0 5

1 Mickey Mouse 3

2 Johnny Bravo 1

3 Winnie the Pooh -1

7 Robin 3

6 Batman 4

5 Alvin y las ardillas 6

4 Fenomenoide 2

0 5

1 Mickey Mouse 7

2 Johnny Bravo 1

3 Winnie the Pooh -1

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

49

0 5

1 Mickey Mouse 8

2 Johnny Bravo 10

3 Winnie the Pooh -1

4 Fenomenoide 9

5 Alvin y las ardillas 6

6 Batman 4

7 Robin 3

8 Pato Donald 7

9 Goofy 2

10 Kalimán 1

8 Pato Donald 7

7 Robin 3

6 Batman 4

5 Alvin y las ardillas 6

4 Fenomenoide 2

0 5

1 Mickey Mouse 8

2 Johnny Bravo 1

3 Winnie the Pooh -1

9 Goofy 2

8 Pato Donald 7

7 Robin 3

6 Batman 4

5 Alvin y las ardillas 6

4 Fenomenoide 9

0 5

1 Mickey Mouse 8

2 Johnny Bravo 1

3 Winnie the Pooh -1

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

50

Si se tuvieran que cancelar las solicitudes correspondientes a

Robin, Alvin y las ardillas, Johnny Bravo y Fenomenoide,

el contenido físico del archivo sería:

0 6

1 Mickey Mouse 8

2 Johnny Bravo 10

3 Winnie the Pooh -1

4 Fenomenoide 9

5 Alvin y las ardillas 6

6 Batman 9

7 Robin 3

8 Pato Donald 3

9 Goofy 10

10 Kalimán 1

Los estructuras en gris NO ESTÁN en uso pero ocupan espacio.

¿Como evitar el desperdicio?

Con una Lista de Espacio Disponible (también se les llama Listas Recolectoras de Basura)

Consiste en enlazar los nodos que van quedando libres en otra lista.

Podrán aprovecharse posteriormente para una nueva alta.

Se requiere otra cabeza de lista.

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

51

Únicamente se requiere enlazar los nodos por lo que se puede usar el algoritmo más sencillo:

• El último nodo borrado será el primero de la lista. • Cuando se requiera un nodo para otra alta, se aprovechará el

último que se borró.

Altas

a) Si la Lista de espacio disponible NO está vacía. • El primer nodo disponible se usará para la nueva alta. • El registro utilizado se debe dar de baja de la lista de espacio

disponible. • El tamaño ocupado por el archivo no aumentará. b) Si la Lista de espacio disponible está vacía. • Se usará el siguiente registro del archivo. • El archivo aumenta de tamaño.

Bajas • El registro que se dejará de usar, debe enlazarse a la lista de espacio

disponible. • El nodo disponible debe quedar señalado por la cabeza de lista de

espacio disponible y su sucesor será el que antes era el primer disponible.

Direcciones Iniciales Ambas listas deben iniciar vacías (dirección -1).

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

52

El contenido físico del archivo al eliminar de la lista en ese orden los estructuras:

Robin

Alvin y las ardillas Johnny Bravo Fenomenoide

0 6 4

1 Mickey Mouse 8

2 Johnny Bravo 5

3 Winnie the Pooh -1

4 Fenomenoide 2

5 Alvin y las ardillas 7

6 Batman 9

7 Robin -1

8 Pato Donald 3

9 Goofy 10

10 Kalimán 1

Los estructuras sombreados son los estructuras disponibles (eliminados).

Apuntes de Estructura de Datos Autor: Ing. Felipe Alanís González Instituto Tecnológico de Durango

53

3.3.2 Listas Dobles � Cada nodo debe contener un apuntador al nodo anterior. � Debe haber una variable que apunte al último nodo.

Nodos de una Lista Doble

Representación de una lista doble:

Ventaja: Los recorridos en sentido inverso se realizan con el mismo esfuerzo que los recorridos en el orden natural. Ejercicio: Escriba un programa para una lista doble ordenada.

B

G

M

R

X

Ultimo

Cabeza

Información Dirección del Dirección del Nodo Nodo Sucesor Predecesor