3.1 Pilasfelipealanis.org/ITD/Estructuras de Datos/4x U3.pdf · La lista que acabamos de usar es...
Transcript of 3.1 Pilasfelipealanis.org/ITD/Estructuras de Datos/4x U3.pdf · La lista que acabamos de usar es...
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 tiempo de 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