Listas Posicionales • Definición: Una lista posicional es una colección de elementos homogéneos, con una relación lineal entre ellos, en la que se puede acceder a los elementos mediante su posición. • Se puede insertar y suprimir en cualquier posición. • En realidad, las pilas y colas vistas en secciones anteriores son listas, con algunas restricciones. Programación Modular 1 Listas posicionales Operaciones sobre listas: Crear ¿Esta vacía? Insertar un elemento en una posición Eliminar el elemento de una posición Consultar el elemento de una posición Longitud Destruir Programación Modular 2 Listas posicionales Interfaz INTERFAZ CLASE CListaPos TIPOS TipoElem ..... MÉTODOS Crear() Insertar(N pos;TipoElem elem) El tipo se definirá más tarde Eliminar(N pos) Consultar(N pos;S TipoElem elem) N Longitud() Destruir() FIN CListaPos Programación Modular 3 Listas posicionales Implementación Estáticas • Utilizaremos arrays para crear la lista de elementos. • Al insertar un elemento en la posición “i”, desplazamos los siguientes una posición a la derecha. • Al eliminar el elemento de la posición “i”, desplazamos los siguientes una posición a la izquierda. Programación Modular 4 Listas posicionales Implementación A D V K 1 2 3 4 5 6 lista.Insertar(3, ‘C’) A D C V K 1 2 3 4 5 6 Programación Modular 5 Listas posicionales Implementación A D V K R O 1 2 3 4 5 6 lista.Eliminar(3) A D K R O 1 2 3 4 5 6 Programación Modular 6 Listas posicionales Implementación Dinámicas • Utilizaremos punteros para crear la lista enlazada de elementos. • Las definiciones de tipos y la implementación de las operaciones se han visto. Programación Modular 7 Tablas • Definición: Una tabla es una colección de elementos homogéneos (del mismo tipo), especialmente diseñada para el acceso rápido a la información. • Se puede acceder a cualquier elemento de la tabla a través de un campo clave. Programación Modular 8 Tablas Operaciones sobre tablas: Crear ¿Esta vacía? Insertar un elemento Eliminar un elemento Buscar un elemento por clave Destruir Programación Modular 9 Tablas INTERFAZ CLASE Tabla TIPOS TipoClave // Definicion de tipos TipoElemento Los tipos se definirán ALGORITMOS más tarde TipoClave Clave(E TipoElemento e) MÉTODOS Crear() B TablaVacia() B TablaLlena() Insertar(E TipoElemento elem;S B ok) Eliminar(E TipoClave clave; S B ok) Buscar(E TipoClave cl; S TipoElemento el; S B ok) Destruir() FIN Tabla Programación Modular 10 Tablas NIVEL DE UTILIZACIÓN •Estructura muy utilizada. •Ejemplo: Manejo de tablas de dispersión con el método de encadenamiento para el tratamiento de sinónimos. –Utilizaríamos un array de listas como tabla de dispersión. –Las listas tienen como elementos cadenas de caracteres. Programación Modular 11 Tablas Eficiencia de los métodos según la implementación Estática no ordenada Estática ordenada Lista enlazada no ordenada Lista enlazada ordenada Insertar Eliminar Buscar Constante Lineal Lineal Lineal Lineal Lineal Constante Lineal Lineal Lineal Lineal Lineal Programación Modular 12 Árboles binarios. Conceptos • Definición: es un conjunto finito de elementos que está vacío o está partido en tres subconjuntos disjuntos. – El primer subconjunto contiene un único elemento llamado la raíz del árbol binario. – Los otros dos subconjuntos son a su vez árboles binarios, llamados subárboles izquierdo y derecho. • El subárbol izquierdo o derecho puede estar vacío. • Cada elemento de un árbol binario se denomina nodo. Programación Modular 13 Árboles binarios. Conceptos • Un método convencional para representar gráficamente un árbol binario es: • Consta de 9 nodos. A B D • A es el nodo raiz. C E G • El subárbol izquierdo tiene como nodo raiz B. • El subárbol derecho tiene C como raiz. • La ausencia de ramas indica un árbol vacío. F H I Programación Modular 14 Árboles binarios. Conceptos • Si A es la raíz de un árbol binario y B es la raíz de su subárbol izquierdo o derecho, se dice que A es el padre de B y B es el hijo izquierdo o derecho de A. • Un nodo que no tiene hijos se denomina nodo hoja. • Un nodo n1 es un antecesor de un nodo n2 (y n2 es un descendiente de n1) si n1 es el padre de n2 o el padre de algún antecesor de n2. • Un nodo n2 es un descendiente izquierdo de un nodo n1 si n2 es el hijo izquierdo de n1 o un descendiente del hijo izquierdo de n1. Un descendiente derecho se puede definir de forma similar. • Dos nodos son hermanos si son los hijos izquierdo y derecho del mismo padre. Programación Modular 15 Árboles binarios. Conceptos • Árbol estrictamente binario: árbol binario en que cada nodo no-hoja tiene subárboles izquierdo y derecho no vacíos. • Nivel de un nodo en un árbol binario: La raíz tiene nivel 0, y el nivel de cualquier otro nodo en el árbol es uno más que el nivel de su padre. • Profundidad de un árbol binario: máximo nivel de cualquier hoja del árbol. la longitud del camino más largo desde la raiz hasta una hoja. • Árbol binario completo de profundidad d: árbol estrictamente binario con todas sus hojas con nivel d. Programación Modular 16 Árboles binarios. Conceptos Un árbol binario contiene m nodos en el nivel L. Contiene como máximo 2m nodos en el nivel L+1. Un árbol binario completo de profunfidad d contiene exactamente 2L nodos en cada nivel L, entre 0 y d Puede contener como máximo 2L nodos en el nivel L El número total de nodos en un árbol binario completo de profundidad d es: tn = 20 + 21 + 22 + ... + 2d = 2d+1 - 1 Programación Modular 17 Árboles binarios. Conceptos Árbol ternario: conjunto finito de elementos que está vacío o está partido en cuatro subconjuntos disjuntos. – El primer subconjunto contiene un único elemento llamado la raíz del árbol. – Los otros tres subconjuntos son a su vez árboles. Árbol n-ario: conjunto finito de elementos que está vacío o está partido en n+1 subconjuntos disjuntos. – El primer subconjunto contiene un único elemento llamado la raíz del árbol. – Los otros n subconjuntos son a su vez árboles. Programación Modular 18 Árboles binarios. Interfaz Operaciones sobre árboles: Devolver el contenido del nodo raíz Crear árbol vacío Devolver el subárbol derecho Construir árbol con raíz, izquierdo y derecho Devolver el subárbol derecho ¿Está vacío? Destruir Programación Modular 19 Árboles binarios. Interfaz INTERFAZ CLASE ArbolBin TIPOS TipoElemento = (* Cualquier tipo de datos *) TipoRecorrido = (preorden, inorden, postorden) MÉTODOS Crear() Construir(E TipoElemento x,E ArbolBin hijoizq, hijoder) B ArbolVacio() TipoElemento Raíz() ArbolBin Izq() ArbolBin Der() Destruir() Imprimir(E TipoRecorrido rec) Programación Modular 20 Árboles binarios. Utilización NIVEL DE UTILIZACIÓN • • Estructura de datos muy útil cuando se deben tomar decisiones de “dos caminos” Muy utilizado en aplicaciones relacionadas con expresiones aritméticas. * (12-3)*(4+1) Ejemplos: + 5 - 5+2 2 12 + 3 4 1 Programación Modular 21 Árboles binarios. Utilización Ejemplo: Diseñemos un algoritmo para evaluar una expresión aritmética que está almacenada en un árbol binario. TIPOS TipoDecision = (Operador, Operando) REGISTRO TipoElemento CASO TipoDecision contenido SEA Operador: C oper Operando: R val FINCASO FINREGISTRO Programación Modular 22 Árboles binarios. Utilización ALGORITMO R Eval(E ArbolBin arbol) VARIABLES TipoElemento dato R result INICIO dato = Info(arbol) SI dato.contenido == Operando ENTONCES result = dato.val SINO CASO dato.oper SEA '+': result = Eval(Izq(arbol)) '-': result = Eval(Izq(arbol)) '*': result = Eval(Izq(arbol)) '/': result = Eval(Izq(arbol)) FINCASO FINSI DEVOLVER result FIN + * / Eval(Der(arbol)) Eval(Der(arbol)) Eval(Der(arbol)) Eval(Der(arbol)) Programación Modular 23 Árboles binarios. Implementación IMPLEMENTACIÓN CLASE ArbolBin TIPOS REGISTRO NodoABin TipoElemento dato NodoABin *izq, *der FINREGISTRO ATRIBUTOS NodoABin *nrz //puntero al nodo raíz del árbol MÉTODOS Crear() INICIO nrz = NULO FIN Programación Modular 24 Árboles binarios. Implementación B ArbolVacio() INICIO DEVOLVER (nrz == NULO) FIN Construir(E TipoElemento x, E ArbolBin hijoizq, hijoder) INICIO Asignar(nrz) nrz->dato = x nrz->izq = hijoizq.nrz nrz->der = hijoder.nrz FIN Programación Modular 25 Árboles binarios. Implementación TipoElemento Raíz() VARIABLES TipoElemento r INICIO SI NO ArbolVacio() ENTONCES r = nrz->dato FINSI DEVOLVER r FIN Raíz Programación Modular 26 Árboles binarios. Implementación ArbolBin Izq() VARIABLES ArbolBin i INICIO SI NO ArbolVacio() ENTONCES i.nrz = nrz->izq FIN DEVOLVER i FIN Izq Programación Modular 27 Árboles binarios. Implementación ArbolBin Der() VARIABLES ArbolBin d INICIO SI NO ArbolVacio() ENTONCES d.nzr = nrz->der FIN DEVOLVER d FIN Der Programación Modular 28 Árboles binarios. Implementación ALGORITMO LiberarMemoria(ES NodoABin a) INICIO SI a <> NULO ENTONCES LiberarMemoria(a->izq) LiberarMemoria(a->der) Liberar (a) FINSI FIN LiberarMemoria Destruir() INICIO LiberarMemoria(nrz) FIN Destruir FIN ArbolBin Programación Modular 29 Árboles binarios. Recorridos Consideraciones acerca de la operación de recorrido. • Recorrer un árbol es "visitar" todos sus nodos para llevar a cabo algún proceso como por ejemplo imprimir los elementos que contiene. • ¿Cómo recorrer los elementos de un árbol? ¿en qué orden?. Programación Modular 30 Árboles binarios. Recorridos • Para recorrer un árbol binario, podemos hacerlo de tres formas distintas: a) Recorrido InOrden. 1) Recorrer el subárbol izquierdo en InOrden Pasos: 2) "Visitar" el valor del nodo raiz y procesarlo 3) Recorrer el subárbol derecho en InOrden b) Recorrido PreOrden. 1) "Visitar" el valor del nodo raiz y procesarlo Pasos: 2) Recorrer el subárbol izquierdo en PreOrden 3) Recorrer el subárbol derecho en PreOrden c) Recorrido PostOrden. 1) Recorrer el subárbol izquierdo en PostOrden Pasos: 2) Recorrer el subárbol derecho en PostOrden 3) "Visitar" el valor del nodo raiz y procesarlo Programación Modular 31 Árboles binarios. Recorridos ALGORITMO Rec_InOrden(E ArbolBin arbol) INICIO SI (arbol <> NULO) ENTONCES Rec_InOrden(arbol.Izq()) RecNodo(arbol.Raíz()) Rec_InOrden(arbol.Der()) FINSI FIN Rec_InOrden Algoritmo Rec_PreOrden(E ArbolBin arbol) INICIO SI (arbol <> NULO) ENTONCES RecNodo(arbol.Raíz()) Rec_PreOrden(arbol.Izq()) Rec_PreOrden(arbol.Der()) FINSI FIN Rec_PreOrden Programación Modular 32 Árboles binarios. Recorridos ALGORITMO Rec_PostOrden(E ArbolBin arbol) INICIO SI (arbol <> NULO) ENTONCES Rec_PostOrden(arbol.Izq()) Rec_PostOrden(arbol.Der()) RecNodo(arbol.Raíz()) FINSI FIN Rec_PostOrden ALGORITMO Recorrer(E ArbolBin arbol, E TipoRecorrido rec) INICIO CASO rec SEA inorden: Rec_InOrden(arbol) preorden: Rec_PreOrden(arbol) postorden: Rec_PostOrden(arbol) FINCASO FIN Recorrer Programación Modular 33 Árboles binarios. Recorridos Ejemplo: P S F Y B H R Z T G W • El recorrido InOrden mostraría: BFGHPRSTWYZ • El recorrido PreOrden: PFBHGSRYTWZ • El recorrido PostOrden: BGHFRWTZYSP Programación Modular 34 Árboles binarios de búsqueda. Definición La estructura lista enlazada es lineal La estructura árbol ¿Búsqueda? ¿Búsqueda más eficiente? Siempre que los datos se distribuyan de forma adecuada Árbol binario de búsqueda Programación Modular 35 Árboles binarios de búsqueda. Definición • Definición: árbol binario en el que el subárbol izquierdo de cualquier nodo (si no está vacío) contiene valores menores que el que contiene dicho nodo, y el subárbol derecho (si no está vacío) contiene valores mayores. E Ejemplo: B A H D C I F G Programación Modular 36 Árboles binarios de búsqueda. Interfaz INTERFAZ CLASE ABBusqueda TIPOS // DEFINICIÓN DE TipoClave // DEFINICIÓN DE TipoElemento MÉTODOS Crear() Destruir() Insertar(E TipoElemento dato) Suprimir(E TipoClave C) Buscar(E TipoClave C, S TipoElemento dato, S B EnArbol) Programación Modular 37 Árboles binarios de búsqueda. Utilización • Aplicaciones en las que estén implicas operaciones de búsqueda de elementos • Ejemplo: procesamiento de índices de palabras de libros: se puede usar un árbol binario de búsqueda para construir y manipular un índice de este tipo de una manera fácil y eficiente. Programación Modular 38 Árboles binarios de búsqueda. Utilización • Supongamos que tenemos construido un árbol binario de búsqueda que contiene un índice de palabras de un determinado libro. • Queremos realizar actualizaciones sobre él a partir de datos dados por teclado. • Estos datos serán: - InsertarP. Insertar una nueva palabra con sus páginas. - Código operación. - SuprimirP. Suprimir una palabra del índice. - AñadirP. Añadir más páginas a una palabra. - FinalizarP. Finalizar la actualización. - Palabra. - Páginas Caso de operación InsertarP o AñadirP Programación Modular 39 Árboles binarios de búsqueda. Utilización TIPOS TipoCódigo=(Insertar, Suprimir, Añadir, Eliminar) TipoClave = ARRAY [1..30] DE $ REGISTRO TipoPaginas N total N num [1..10] FINREGISTRO REGISTRO TipoElemento TipoClave clave TipoPaginas pag FINREGISTRO Programación Modular 40 Árboles binarios de búsqueda. Utilización ALGORITMO ActualizarIndice(ES ABBusqueda indice) VARIABLES TipoCódigo codigo TipoElemento elem N pag TipoClave palabra B encontrada INICIO leerCódigo(codigo) MIENTRAS (codigo <> FinalizarP) HACER CASO MAY(codigo) SEA InsertarP: leer(elem.clave) elem.pag.total = 0 leer(pag) Programación Modular 41 Árboles binarios de búsqueda. Utilización MIENTRAS (pag <> 0) HACER INC(elem.pag.total) elem.pag.num[elem.pag.total] = pag leer(pag) FINMIENTRAS indice.Insertar(elem) SuprimirP: leer(palabra) indice.Suprimir(palabra) AñadirP: leer(palabra) indice.Buscar(palabra,elem,encontrada) Programación Modular 42 Árboles binarios de búsqueda. Utilización SI (NO encontrada) ENTONCES escribir("palabra no está en indice") SINO leer(pag) MIENTRAS (pag <> 0) HACER INC(elem.pag.total) elem.pag.num[elem.pag.total] = pag leer(pag) FINMIENTRAS indice.Suprimir(palabra) indice.Insertar(elem) FINSI FINCASO leerCódigo(codigo) FINMIENTRAS FIN Programación Modular 43 Árboles binarios de búsqueda. Implementación IMPLEMENTACIÓN CLASE ABBusqueda TIPOS REGISTRO NodoArbol NodoArbol *izq,der TipoElemento elem TipoClave clave FINREGISTRO ATRIBUTOS NodoArbol *nrz MÉTODOS Crear() INICIO nrz = NULO FIN Programación Modular 44 Árboles binarios. Implementación ALGORITMO LiberarMemoria(ES NodoArbol *a) INICIO SI a <> NULO ENTONCES LiberarMemoria(a->izq) LiberarMemoria(a->der) Liberar (a) FINSI FIN LiberarMemoria Destruir() INICIO LiberarMemoria(nrz) FIN Destruir Programación Modular 45 Árboles binarios de búsqueda. Implementación Buscar(E TipoClave C, S TipoElemento dato, S B EnArbol) VARIABLES NodoArbol *aux = nrz INICIO EnArbol = FALSO MIENTRAS (aux<>NULO) Y (NO EnArbol)) HACER SI (aux->clave == c) ENTONCES EnArbol == VERDADERO dato = arbol->elem SINOSI (aux->clave > c) ENTONCES aux = aux->izq EN OTRO CASO aux = aux->der FINSI FINSI FINMIENTRAS FIN Buscar Programación Modular 46 Árboles binarios de búsqueda. Implementación Consideraciones acerca de la operación de inserción. A D B B A F C E Entrada: ABCDEFG C D G E B Entrada: DBFACEG G G C Los mismos datos, insertados en orden diferente, producirán árboles con formas o distribuciones de elementos muy distintas. F D A F E Entrada: BADCGFE Programación Modular 47 Árboles binarios de búsqueda. Implementación Insertar(E TipoElemento dato) VARIABLES NodoArbol *nuevonodo,*pav = nrz, *pret = NULO TipoClave clavenueva INICIO Asignar(nuevonodo) nuevonodo->izq = NULO nuevonodo->der = NULO nuevonodo->elem = dato clavenueva = dato.clave MIENTRAS (pav <> NULO) HACER pret = pav SI (pav->elem.clave > clavenueva) ENTONCES pav = pav->izq SINO pav = pav->der FINSI FINMIENTRAS Programación Modular 48 Árboles binarios de búsqueda. Implementación SI (pret == NULO) ENTONCES arbol = nuevonodo EN OTRO CASO SI (pret->elem.clave > clavenueva) ENTONCES pret->izq = nuevonodo SINO pret->der = nuevonodo FINSI FINSI FIN Insertar Programación Modular 49 Árboles binarios de búsqueda. Implementación Consideraciones acerca de la operación de suprimir. • Pasos: 1) Encontrar el nodo a suprimir. Equivalente a Buscar 2) Eliminarlo del árbol. 3 casos padre de x ex-padre de x Caso 1 x Programación Modular 50 Árboles binarios de búsqueda. Implementación ex-padre de x padre de x Caso 2 x ex-hijo de x hijo de x J J Q B R L K P R L Z N M Eliminar Q P B K N z Caso 3 M Programación Modular 51 Árboles binarios de búsqueda. Implementación ALGORIMTO SuprimirNodo(ES NodoArbol *na) VARIABLES NodoArbol *temp,*ant INICIO temp = na SI (na->der == NULO) ENTONCES na = na->izq SINO SI (na->izq == NULO) ENTONCES na = na->der SINO temp = na->izq ant = na MIENTRAS (temp->der <> NULO HACER anterior = temp temp = temp->der FINMIENTRAS 0 ó 1 hijo 1 hijo 2 hijos Programación Modular 52 Árboles binarios de búsqueda. Implementación na->elem = temp->elem SI (anterior == na) ENTONCES anterior->izq = temp->izq EN OTRO CASO anterior->der = temp->izq FINSI FINSI FINSI Liberar(temp) FIN SuprimirNodo Programación Modular 53 Árboles binarios de búsqueda. Implementación Suprimir(E TipoClave c) VARIABLES NodoArbol *pav, *pret INICIO pav = nrz pret = NULO MIENTRAS pav <> NULO Y pav->elem.clave <> c HACER pret = pav SI (pav->elem.clave > c) ENTONCES pav = pav->izq SINO pav = pav->der FINSI FINMIENTRAS Programación Modular 54 Árboles binarios de búsqueda. Implementación SI (pav <> NULO) ENTONCES SI (pav == nrz) ENTONCES SuprimirNodo(nrz) SINO SI (pret->izq == pav) ENTONCES SuprimirNodo(pret->izq) SINO SuprimirNodo(pret->der) FINSI FINSI FINSI FIN Suprimir Programación Modular 55 Bibliografía • Walls and mirrors. Modula-2 edition . Hellman, Veroff.. Ed. Benjamin/Cummings Series. 1988. • Pascal y Estructuras de Datos. Dale, N. y Lilly, S. Ed. MacGraw Hill 1989. • Estructuras de Datos en Pascal. Tanenbaum, A. y Augenstein, M. Prentice Hall. 1983 • Fundamentos de Programación. Algoritmos y Estructuras de Datos. Joyanes, L. McGraw Hill. 2ª Ed. 1996. Programación Modular 56