La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

Estructura de Datos En C++

Presentaciones similares


Presentación del tema: "Estructura de Datos En C++"— Transcripción de la presentación:

1 Estructura de Datos En C++
Dr. Romeo Sánchez Nigenda. Oficina: 1er. Piso del CIDET. Oficina con Dr. Oscar Chacón Horas de Tutoría: 10am-11am Martes y Jueves, 3:30pm-4:30pm Miércoles, 2:00pm-4:00pm Viernes. Website: Sesiones: 48

2 Objetivo General: Conocerá y manejará las estructuras internas de información
Temario: Conceptos Básicos La Pila Colas Recursión Listas Árboles Ordenamiento Búsqueda Administración de Almacenamiento Total a calificar: 110 puntos. 40% Tareas 30% Examen Parcial 30% Examen Final 10% Participación

3 Material de apoyo: Software: Estructura de Datos con C y C++.
Yedidyah Langsam, Moshe J. Augenstein, Aaron M. Tenenbaum, Brooklyn College Segunda Edición, Prentice-Hall. Algorithms. Third Edition. Parts 1-4, Fundamentals Data Structures Sorting Searching Robert Sedgewick. Estructura de Datos. Román Martínez, Elda Quiroga. Thomson Learning. Cualquier libro de Estructura de Datos! Software: Compiladores GCC (GNU Compiler Collection) IDEs (Integrated Development Environment):

4 3. Listas Objetivo: El alumno manejará estructuras de datos lineales y dinámicas, y entenderá las ventajas de utilizarlas para optimizar el uso de espacio en memoria. Temario: Definición y conceptos utilizados Operaciones con listas Listas circulares Listas doblemente ligadas Aplicaciones

5 Listas Cuáles son las desventajas de usar almacenamiento secuencial para presentar filas y colas? Una lista vinculada (linked list) es una estructura dinámica de nodos de datos los cuales se representan como una secuencia. En su forma más simple, cada nodo se compone: De un área de datos o información De una referencia (link) al siguiente nodo en la secuencia Se puede acceder a la lista vinculada por medio de una variable apuntador externa, que contenga la dirección del primer elemento en la lista. El último nodo en la lista apunta al valor null para señalar el término de la secuencia. inf sig inf sig inf sig inf sig cabeza null

6 Listas Cada registro de una lista vinculada es a menudo llamado un elemento o nodo El campo de cada nodo que contiene la dirección al siguiente nodo es usualmente llamado el siguiente link o siguiente puntero (next) Los campos remanentes contienen los datos, información, o valores La cabeza (head) de la lista es su primer elemento La cola (tail) de la lista se puede referir al resto de los elementos después de la cabeza, o al último nodo

7 Listas Características:
La estructura permite inserción y remoción de elementos eficientemente de cualquier posición en la secuencia El principal beneficio entonces de una lista sobre arreglos es que sus elementos no necesitan reacomodarse cada vez que se actualiza la lista Una lista sin nodos se denomina lista vacía, el apuntador externo a la lista es null Sin embargo, listas simples no permiten acceso randomizado o indexación, por lo que operaciones básicas como obtener el último nodo en la lista o encontrar un nodo puede requerir escanear la mayoría o todos sus elementos

8 Listas: Operaciones básicas
Inserción en la parte delantera de la lista inf sig inf sig inf sig cabeza 6 3 8 null inf sig & Se obtiene memoria para el nuevo nodo: Se establecen los valores (datos) del nodo: Se establece el link (sig) del nodo al primer elemento en la lista: P Nodo vacío inf sig & P 12 P->sig = cabeza inf sig & P 12 inf sig inf sig inf sig cabeza 6 3 8 null

9 Operaciones básicas: Inserción
Se actualiza el apuntador externo cabeza al nuevo nodo insertado: El valor de P es irrelevante antes y después de la inserción del elemento a la lista: El algoritmo básico de inserción queda entonces: p = creaNodo (); info (p) = 12 //Datos nuevos next (p) = cabeza cabeza = p cabeza = P P inf sig inf sig inf sig inf sig 12 6 3 8 null cabeza inf sig inf sig inf sig inf sig cabeza 12 6 3 8 null Qué pasa cuando la lista está vacía?

10 Operaciones básicas: Remoción
inf sig inf sig inf sig inf sig cabeza 12 6 3 8 null Se hace referencia al primer nodo en la lista a través de un apuntador: P = cabeza La cabeza de la lista debe apuntar al siguiente nodo en la secuencia: cabeza = P->sig Se guardan los valores a retornar en una variable: x = P->info P inf sig inf sig inf sig inf sig 12 6 3 8 null cabeza inf sig P 12 inf sig inf sig inf sig cabeza 6 3 8 null

11 Operaciones básicas: Remoción
inf sig P 12 inf sig inf sig inf sig cabeza 6 3 8 null En este momento se considera que P ya ha sido removido de la lista, pues a pesar que conserva un apuntador a un nodo en la lista, no es posible acceder a P a través del apuntador externo cabeza. El siguiente paso sería liberar la memoria que P usa: liberaNodo(P) El algoritmo de remoción es básicamente opuesto al de inserción: P = cabeza Cabeza = next(P) X = info(P)

12 Operaciones Básicas: Travesar
inf sig inf sig inf sig inf sig cabeza 12 6 3 8 null Se obtiene un apuntador al primer elemento (cabeza) de la lista: P = cabeza MIENTRAS que el apuntador no sea nulo (null), se lee el campo de información: X = P -> info Se actualiza la variable apuntador al siguiente elemento en la lista: P = P -> sig P inf sig inf sig inf sig inf sig 12 6 3 8 null cabeza inf sig inf sig inf sig inf sig 12 6 3 8 null cabeza P P P P

13 Operaciones Básicas: Implementación
Definición de un nodo simple usando estructuras en C: struct nodo{ int info; struct nodo * sig; }; typedef struct nodo *NODEPTR; Inicialización de una lista vacía, usando un apuntador externo: NODEPTR cabeza=NULL; Asignación de Memoria NODEPTR creaNodo(void){ NODEPTR p = (NODEPTR) malloc (sizeof(struct nodo)); return(p); } void liberaNodo(NODEPTR p){ free(p); Liberación de Memoria

14 Operaciones Básicas: Implementación
void traversaLista(NODEPTR cabeza){ NODEPTR p = cabeza; while(p!=NULL){ cout<<"Elem: "<<p->info<<endl; p=p->sig; } inf sig inf sig inf sig inf sig 12 6 3 8 null cabeza P P P P

15 Operaciones Básicas: Implementación
void insertaNodo(NODEPTR * cabeza, int valor){ NODEPTR p =creaNodo(); p->info=valor; p->sig = *cabeza; *cabeza=p; } int borraNodo(NODEPTR * cabeza){ int value = -1; if(*cabeza!=NULL){ NODEPTR p = *cabeza; *cabeza= p->sig; value = p->info; liberaNodo(p); } return value; NODEPTR cabeza=NULL; insertaNodo(&cabeza,1); traversaLista(cabeza); borraNodo(&cabeza);

16 Operaciones Básicas: Implementación
Inserta después de un nodo P: inf sig inf sig inf sig cabeza 6 3 8 null P void insertaDespuesNodo(NODEPTR * P, int valor){ NODEPTR q =creaNodo(); q->info=valor; q->sig=(*P)->sig; (*P)->sig=q; } inf sig q inf sig valor q inf sig inf sig 3 8 null P inf sig valor q inf sig inf sig inf sig 3 valor 8 null P q

17 Operaciones Básicas: Implementación
Elimina después de un nodo P: inf sig inf sig inf sig cabeza 6 3 8 null P int deleteDespuesNodo(NODEPTR * P){ q=(*P)->sig; valor = q->info; (*P)->siq=q->sig; liberaNodo(q); } inf sig 8 null inf sig 3 null P inf sig 8 null

18 Listas Implementando Colas
inf sig inf sig inf sig cabeza cola 6 3 8 null P Se consideran dos apuntadores, uno al principio de la lista para remover elementos. El segundo al final de la lista para insertar (FIFO). Pseudocódigo para remover un elemento: remueve(Cola q){ if(!colaVacia(q)){ p = q.cabeza x = info(p) // Almacena 6 en X para retornarlo q.cabeza = next(P) //cabeza apunta ahora al segundo nodo if(q.cabeza==NULL){ q.cola=NULL //Si eliminamos el ultimo, actualiza cola } liberaNodo(p);

19 Listas Implementando Colas
inf sig inf sig inf sig cabeza cola 6 3 8 null P Pseudocódigo para insertar un elemento: inserta(Cola q, Elemento x){ p = creaNodo() info(p) = x // Almacena el valor del nuevo elemento en el nodo next(p) = NULL //Nuevo elemento es el último if(q.cola==NULL){ q.cabeza = p; //Cola vacia, entonces p es el primero }else{ next(q.cola) = p //El siguiente de cola apunta al nuevo } q.cola = p //Cola se actualiza al ultimo elemento

20 Ejemplo: Remueve X elementos
inf sig inf sig inf sig inf sig cabeza 6 X 8 X null Pseudocódigo para remover X elementos: q = NULL P = cabeza While(P!=NULL){ If(info(p) == X){ if(q==NULL){ cabeza = next(P) P=cabeza; }else{ p = next(P); deleteDespuesNodo(q) } } else{ q=p; p = next(p)

21 Listas Circulares inf sig inf sig inf sig inf sig 12 6 3 8 apunta
Una convención es que el apuntador externo apunte al último nodo en la lista, para así también acceder al primer nodo con el campo sig del último nodo. Ejemplo: Pilas como listas circulares, donde el primer nodo es el tope de la Pila. La pila está vacía si: apunta = NULL int estaVacia(NODEPTR apunta) { return (apunta == NULL); }

22 Listas Circulares: Pilas
apunta Último nodo inf sig inf sig inf sig 12 6 3 apunta inf sig inf sig inf sig inf sig X 12 6 3 P Operación Push void push(NODEPTR * apunta, int x) { NODEPTR p = creaNodo(); p->info = x; if (estaVacia(*apunta)) { (*apunta) = p; } else { p->sig = (*apunta)->sig; } (*apunta)->sig = p; PUSH

23 Listas Circulares: Pilas
Último Nodo Insertado inf sig inf sig inf sig inf sig 12 6 3 8 apunta Operación Pop int pop(NODEPTR * apunta) { if (estaVacia(*apunta)) { cout << “Pila vacia!" << endl;exit(1); } NODEPTR p = (*apunta)->sig; int x = p->info; if (p == (*apunta)) (*apunta) = NULL; else (*apunta)->sig = p->sig; liberaNodo(p); return x;

24 Listas Circulares Último Nodo Insertado Primer Nodo Insertado inf sig
12 6 3 8 apunta Operación Traversal void traversaPila(NODEPTR apunta) { NODEPTR p = apunta; NODEPTR q, ultimo; if (!estaVacia(apunta)) { ultimo = q = p->sig; cout << "Elem: " << q->info << endl; q = q->sig; while (q != ultimo) { } Colas Circulares: Remove(){ P = q.front; X=info(p) q.Front = next(p) If(q.Front == null) q.rear = null; freeNode(p); Return x; } Insert(q,x){ P=creaNodo() Info(p) = x Next(p) = null; If(q.rear == null) q.Front = p Else Next(q.rear) = p; q.Rear = p;

25 Listas Doblemente Vinculadas
Aunque las listas circulares tienen ventajas sobre las listas lineales, todavía tienen algunas limitaciones importantes: No se puede recorrer la lista hacia atrás No puede suprimirse un nodo dado solo un apuntador hacia dicho nodo En una lista doblemente vinculada, cada nodo posee dos apuntadores, uno a su antecesor y otro a su sucesor Pueden ser lineales o circulares, y pueden o no tener un nodo de encabezado

26 Ejemplos de Listas Doblemente Vinculadas
prev inf sig prev inf sig prev inf sig Null 12 14 10 Null Lista doblemente vinculada prev inf sig prev inf sig prev inf sig 12 14 10 Lista circular doblemente vinculada sin encabezado prev inf sig prev inf sig prev inf sig prev inf sig 12 14 10 Lista circular doblemente vinculada con encabezado

27 Implementación de Listas Doblemente Vinculadas
Definición: struct nodod{ int info; struct nodod *prev, *sig; }; typedef struct nodod * NODODOBLEPTR; prev inf sig

28 Implementación de Listas Doblemente Vinculadas
prev inf sig prev inf sig prev inf sig Null 12 14 10 Null Borra el nodo dado: int deleteNodoListaDoble(NODODOBLEPTR p){ if((p)==NULL){ cout<<"Error en borrado!"<<endl; exit(1); } NODODOBLEPTR l,r; int x = p->info; l = p->prev; r = p->sig; if(l!=NULL) l->sig = r; if(r!=NULL) r->prev = l; free(p); return x;

29 Implementación de Listas Doblemente Vinculadas
void insertaNodoDerecha(NODODOBLEPTR p, int x){ if(p==NULL){ cout<<"Error en insercion!"<<endl; exit(1); } NODODOBLEPTR q,r; q = creaNodoDoble(); q->info = x; r = p->sig; if(r!=NULL){ r->prev = q; q->sig = r; q->prev = p; p->sig = q;


Descargar ppt "Estructura de Datos En C++"

Presentaciones similares


Anuncios Google