Estructuras de Datos Avanzadas Contenido del Tema TT EE M M A A 66 6.1. Introducción 6.2. Pilas 6.3. Colas 6.4. Listas 6.5. Arboles Binarios. Arboles Binarios de Búsqueda 6.6. Otras Estructuras. Metodología de Programación Introducción Objetivos • Especificación e Implementación de nuevas estructuras de datos Técnica: Abstracción de Datos • Tipos de Estructuras de Datos: 1) Datos organizados por Posición Pilas , Colas y Listas 2) Datos organizados por Valor Arboles Binarios Metodología de Programación 1 Introducción • Estudio de las Estructuras de Datos: Definición de la Estructura de Datos e identificación de su Conjunto de Operaciones Desarrollo de diversas Implementaciones Presentación de Aplicaciones Metodología de Programación Pilas Definición • Pila: Grupo Ordenado, (de acuerdo al tiempo que llevan en la pila) de Elementos Homogéneos (todos del mismo tipo). • Acceso a la Pila: añadir y eliminar elementos, SÓLO a través de la CABEZA de la Pila • Estructura LIFO (L Last Input First Output) Añadir Eliminar Metodología de Programación 2 Pilas. Operaciones Conjunto de Operaciones MÓDULO MPila DEFINICIÓN TIPOS TElemento= // cualquier tipo de datos TPila= // por definir PROC MeterPila(↓↑pila:TPila; ↓elem: TElemento) // Añade un elemento por la cabeza de la pila PROC SacarPila(↓↑pila:TPila;↑elem:TElemento) // Saca un elemento por la cabeza de la Pila Metodología de Programación Pilas. Operaciones Conjunto de Operaciones FUNC CrearPila():TPila // Crea una pila vacía FUNC PilaVacia (↓pila :TPila):LÓGICO // Nos dice si una pila está vacía FUNC PilaLlena(↓pila:TPila):LÓGICO // Nos dice si una pila está llena. PROC DestruirPila(↓↑ pila:TPila) // Destruye una pila previamente creada Fin Metodología de Programación 3 Pilas. Implementación Implementación 1) Con un Array • Array estructura adecuada Elementos Homogéneos • Elementos almacenados de forma Secuencial CONSTANTES MAXPILA ← 100 TIPOS TElemento = ENTERO TPila = ARRAY[1..MAXPILA]DE TElemento Metodología de Programación Pilas. Implementación Sólo es posible acceder a la Cabeza de la Pila ¿ Cómo es posible conocer la posición de la cabeza? 1) Variable entera “cabeza” Inconveniente: se ha de pasar como parámetro adicional a todas las operaciones sobre la pila 2) Extender el array, en pila[0] almacenaremos el índice del elemento que ocupa la cabeza actual Metodología de Programación 4 Pilas. Implementación CONSTANTES CABEZA ← 0 MAXPILA ← 100 TIPOS TPila = ARRAY[CABEZA..MAXPILA]DE TElemento 3 5 [0] [1] 3 ....... 2 [2] [3] [99] [100] 2 3 5 Metodología de Programación Pilas.Implementación • Inconveniente: Solo es posible implementar una pila de enteros (no de cualquier otro tipo de datos) • Solución: CONSTANTES MAXPILA ← 100 TIPOS TElemento= // cualquier tipo de datos TPila=REGISTRO Cabeza:NATURAL Elementos: ARRAY[1..MAXPILA] DE TElemento k 5 1 13 2 ! ! " " # # 8 k ......... MAXPILA Metodología de Programación 5 Pilas.Implementación IMPLEMENTACIÓN FUNC CrearPila():TPila VARIABLES pila:TPila INICIO pila.Cabeza ← 0 RESULTADO ← pila FIN FUNC PilaVacia(↓pila:TPila ):LÓGICO INICIO RESULTADO←pila.Cabeza=0 FUNC PilaLlena(↓pila:TPila ):LÓGICO INICIO RESULTADO ←(pila.Cabeza = MAXPILA) FIN PROC DestruirPila(↓↑pila:TPila) INICIO // No hay que hacer nada. FIN FIN Metodología de Programación Pilas.Implementación PROC SacarPila(↓↑pila:TPila; PROC MeterPila(↓↑pila:TPila; ↑elem:TElemento) INICIO INICIO elem ← pila.Elementos [pila.Cabeza] pila.Cabeza←pila.Cabeza-1 FIN /* precondición: la pila no ha de estar vacía ↓elem :TElemento) pila.Cabeza←pila.Cabeza+1 pila.Elementos [pila.Cabeza] ← elem FIN /* precondición: la pila no ha de estar llena */ */ Metodología de Programación 6 Pilas.Implementación PROC MeterPila (↓↑pila:TPila; ↓elem:TElemento; ↑llena : LÓGICO) Inicio llena ←PilaLlena(pila) SI (¬llena) ENTONCES pila.Cabeza ← pila.Cabeza + 1 pila.Elementos [pila.Cabeza] ← elem FINSI Fin /* Sin Prec ondición.Introduce un elemento en la pila si no está llena */ PROC SacarPila(↓↑pila:TPila ; ↑elem:TElemento; ↑vacia:LÓGICO) INICIO vacia ← PilaVacia(pila) SI ¬vacia ENTONCES elem ← pila.Elementos [pila.Cabeza] pila.Cabeza ←pila.Cabeza-1 FINSI FIN /* Sin precondición. Saca un elemento de la pila si no está vacía*/ Metodología de Programación Pilas.Implementación 2) Con una Lista Enlazada de Punteros • Comienzo de una lista enlazada Cabeza de la Pila TIPOS TElemento= // cualquier tipo de datos TPila = PUNTERO A TNodoPila TNodoPila = REGISTRO dato:TElemento sig: TPila FINREGISTRO ' ( ' ) ( * ) + * ( + ( , , - & $ % $ & % . . Metodología de Programación 7 Pilas.Implementación PROC MeterPila(↓↑pila:TPila; ↑elem: TElemento; ↑llena: LÓGICO) VARIABLES nuevonodo : TPila INICIO llena ← FALSO nuevonodo ← NUEVO(TNodoPila) nuevonodo^.dato ← elem nuevonodo^.sig ← pila pila ← nuevonodo FIN PROC SacarPila(↓↑pila:TPila; ↑elem :TElemento; ↑vacía: LÓGICO) VARIABLES ptr: TPila INICIO vacía ← PilaVacía(pila) SI ¬vacía ENTONCES elem ← pila^.dato ptr ← pila pila ← pila^.sig ELIMINAR(ptr) FINSI FIN Metodología de Programación Pilas.Implementación PROC CrearPila():TPila PROC DestruirPila(↓↑pila:TPila) INICIO Variables RESULTADO ← NULO Fin FUNC PilaVacia(pila :TPila ):LÓGICO INICIO RESULTADO ← (pila= NULO) FIN ptr: TPila Inicio MIENTRAS(pila≠ NULO)HACER ptr ← pila pila ← pila^.sig ELIMINAR(ptr) FINMIENTRAS FIN Metodología de Programación 8 Pilas. Aplicaciones Aplicaciones • Ejemplo1: Ejemplo1: Leer una secuencia de caracteres desde teclado e imprimirla al revés • Ejemplo2: Ejemplo2: Verificar si una cadena de caracteres está balanceada en paréntesis o no abc( mn))op) SI abc(defg( defg(ijk))(l( ijk))(l(mn op)qr abc( ghij((kl)m NO abc(def)) def))ghij kl)m • Ejemplo3: Ejemplo3: Reconocimiento del Lenguaje, L={W$W´ / W es una cadena de caracteres y W´es su inversa} (Suponemos que $ no está ni en W ni en W´) Metodología de Programación Pilas. Ejemplo1 ALGORITMO Inverso DESDE MPila IMPORTA TPila, CrearPila, MeterPila, SacarPila, Pilavacia, DestruirPila CONSTANTES ENTER ← CHR(13) TIPOS TElemento = CARÁCTER VARIABLES c : TElemento pila : TPila ll,v:LÓGICO INICIO pila ← CrearPila() LEER(c) MIENTRAS (c≠ENTER) ∧ (¬ll) HACER MeterPila(pila,c,ll) Leer(c) FINMIENTRAS SacarPila(pila,c,v) MIENTRAS (¬PilaVacia(pila))HACER SacarPila(pila,c,v) Escribir(c) FINMIENTRAS DestruirPila(pila) FIN Metodología de Programación 9 Pilas. Ejemplo2 ALGORITMO Balanceo DESDE MPila IMPORTA CrearPila, TPila, MeterPila, SacarPila, PilaVacia, DestruirPila CONSTANTES ENTER ← CHR(13) Tipos TElemento = CARÁCTER VARIABLES c : TElemento pila : TPila bien,ll, v : LÓGICO Inicio pila ← CrearPila() bien ← CIERTO LEER(c) MIENTRAS(bien ∧ (c≠ENTER)HACER SI c= ‘(’ ENTONCES MeterPila(pila,c,ll) bien ← ¬ll EN OTRO CASO SI c = ‘)’ ENTONCES SacarPila(pila,c,v) bien ← ¬v FINSI FINSI LEER(c) FINMIENTRAS SI bien ∧ PilaVacia(pila) ENTONCES Escribir(“cadena balanceada “) EN OTRO CASO Escribir(“cadena no balanceada”) FINSI DestruirPila(pila) FIN Metodología de Programación Pilas. Ejemplo3 Algoritmo Lenguaje_L DESDE MPila IMPORTA TPila, CrearPila, MeterPila, SacarPila, DestruirPila CONSTANTES ENTER ← CHR(13) TIPOS TElemento = CARÁCTER VARIABLES c1, c2 : TElemento pila : TPila bien, ll, v : LÓGICO Inicio pila ← CrearPila() ll ← FALSO LEER(c1) MIENTRAS (c1 ≠‘$’)∧(¬ll) HACER MeterPila(pila,c1,ll) LEER(c1) FINMIENTRAS Leer(c1) bien ← TRUE MIENTRAS (bien ∧ (c1 ≠ENTER)) HACER SacarPila(pila,c2,v) bien ← (¬v) ∧ (c1=c2) /* He podido sacar el elemnto y conicide */ SI (bien) ENTONCES Leer(c1) FINSI FINMIENTRAS SI (bien ∧ PilaVacia(pila))ENTONCES Escribir(“ Si pertenece”) EN OTRO CASO Escribir (“No pertenece”) FINSI DestruirPila(pila) FIN Metodología de Programación 10 Pilas. Aplicaciones • Aplicaciones complejas que se pueden solucionar con pilas: Expresiones Algebraicas Operadores: +, -, *, / Operandos: Letras mayúsculas • Notación Infija: Infija: • El operador binario está situado entre sus dos operandos A+ B • Inconveniente: Son necesarias reglas de precedencia y uso de paréntesis para evitar ambigüedades A+B*C Metodología de Programación Pilas. Aplicaciones Notación Prefija Notación Postfija • El operador binario esta situado justo antes de sus dos operandos +AB • Gramática: <expr_pref>::=<letra>|<operador> <expr_pref><expr_pref> <letra> ::= A| B ....|Z <operador> ::= + | - | * | / • Ejemplos: A+(B*C) +A*BC (A+B)*C *+ABC • El operador binario está situado justo después de sus dos operandos AB+ • Gramática: <exp_post>::=<letra>|<expr_post> <exp_post><operador> <letra> ::=A| B ....|Z <operador> ::= + | - | * | / • Ejemplos: A+(B*C) ABC*+ (A+B)*C AB+C* Metodología de Programación 11 Pilas. Aplicaciones • Ventaja: Usando expresiones prefijas y postfijas no son necesarias reglas de precedencia, ni uso de paréntesis. Las gramáticas que las generan son muy simples, y los algoritmos que las reconocen y evaluan muy fáciles • Ejemplo 4: Algoritmo que evalúa una expresión en notación Postfija 1)Usaremos una pila 2)La expresión postfija se almacenará en un array de caracteres y será correcta 3)Los operadores serán: +, -, * y / 4)Los operandos serán letras mayúsculas (a cada una le podemos asignar un valor) Metodología de Programación Pilas. Ejemplo4 CONSTANTES MAX ← 20 TIPOS TArray = ARRAY[1..MAX] DE CARÁCTER TElemento=ENTERO FUNC Operando(↓c:CARACTER) :ENTERO VARIABLES res:ENTERO INICIO CASO c SEA ‘A’ : res ‘B’ : res ‘C’ : res ‘D’ : res EN OTRO CASO res ← 0 FINCASO RESULTADO ← FIN ← ← ← ← 5 7 -1 11 res Metodología de Programación 12 Pilas. Ejemplo4 FUNC Eval_postfija(↓exp: TArray; ↓ultimo:NATURAL):ENTERO DESDE IMPORTA MPila DestruirPila TPila, CrearPila, MeterPila, SacarPila, Variables pila : TPila i, op1, op2, result : ENTERO c : CARÁCTER v,ll:LÓGICO FUNC es_operador(↓c:CARÁCTER):LÓGICO INICIO RESULTADO ← (c=`*´) ∨ (c=`/´) ∨ (c=`+´) ∨ (c=`-´} FIN Metodología de Programación Pilas. Ejemplo4 Inicio pila ← CrearPila() PARA i ← 1 HASTA ultimo HACER c ← exp[i] SI es_operador(c) ENTONCES SacarPila(pila,op2,v) SacarPila(pila,op1,v) CASO c SEA ‘+’ :MeterPila(pila,op1+op2,ll) ‘-’ : MeterPila(pila,op1-op2,ll) ‘*’ : MeterPila(pila,op1*op2,ll) ‘/’ : MeterPila(pila, op1/op2,ll) FINCASO EN OTRO CASO MeterPila(pila, Operando(c)) FINSI FINPARA SacarPila(pila,result) DestruirPila(pila) RESULTADO ← result Fin Metodología de Programación 13 Colas Definición • Cola: es un grupo ordenado (con respecto al tiempo que llevan en él) de elementos homogéneos (todos del mismo Tipo) • Acceso: los elementos se añaden por un extremo (final) y se sacan por el otro extremo (frente) • Estructura FIFO (First Input First Output) = > = ? > > ? @ > @ / / 0 0 1 1 2 2 3 3 1 4 1 4 5 5 6 6 7 7 8 9 8 9 : : ; ; : : < < Metodología de Programación Colas. Operaciones Conjunto de Operaciones MODULO MCola DEFINICIÓN TIPOS TElemento =// cualquier tipo de datos TCola= // por definir FUNC CrearCola(): TCola // Crea una cola vacia FUNC ColaVacia(↓cola:TCola): LÓGICO /* Operación lógica que nos dice contiene algún elemento o no*/ si la cola Metodología de Programación 14 Colas. Operaciones FUNC ColaLlena(↓cola:TCola):LÓGICO /* Operación lógica que nos dice si la cola está llena o no */ PROC MeterCola(↓↑cola: TCola; ↓elem: TElemento) // Introduce un elemento al final de la cola/ PROC SacarCola(↓↑cola: TCola; ↑elem: TElemento) // Saca un elemento del frente de la cola PROC DestruirCola(↓↑cola:TCola) // Destruye una cola previamente creada Fin Metodología de Programación Colas. Implementación Implementación 1) Con un Array • Se deja fijo el frente de la cola y se mueve el final a medida que se añaden nuevos elementos (Idem Pila) • Las operaciones Meter, Crear, ColaVacia y ColaLlena se implementan de una forma similar a sus análogas en Pilas • La operación de Sacar es mas complicada: cada vez que saquemos un elemento de la cola se han de desplazar el resto una posición en el array, para hacer coincidir el frente con la primera posición del array • Ventaja Simplicidad • Inconveniente Ineficiente (colas con muchos elementos o elementos grandes) Metodología de Programación 15 Colas. Implementación • Ejemplo: A B A C B D C E D E E E E E E E E E E E E E E E E E E E F Meter(Cola,”A”) Q L Meter(cola, “B”) G F H G I H J I K J L K L Q M L W Q O N P O P P P P P P P P P P P P P P P P P P P W X Q R N M S R W T S U T V U V V V V V V V V V V V V V V V V V V Y X Z Y [ Z \ [ ] \ ^ ] ^ V W Sacar(cola, elem) elem) A B Desplazar A W C B D C E D E E E E E E E E E E E E E E E E E E E W _ X _ X Y Y Z Z [ [ \ \ ] _ ] _ ^ ^ ` ` a a b b b b b b b b b b b b b b b b b b b b Metodología de Programación Colas. Implementación Solución: • Utilizar un indice para el frente y otro para el final y permitir que ambos fluctuen por el array • Ventaja: operación Sacar más sencilla • Inconveniente: Es posible que final sea igual a Maxcola (última casilla del array) y que la cola no esté llena Metodología de Programación 16 Colas. Implementación • Ejemplo: j Meter(Cola,”A”) h k j j c d c e d f e g f g g g g g g g g g g g g g g g g g g q j i h m l y n m e d k f e g f g g g g g g g g g g g g g g g g g g l n t p q m q | { z o l p o p o p p m l n m l n o l p o p r m s r o s t o t u t v u w v w w w w w w w w w w w w w w w w w w } | { ~ ~ } ~ ~ } } w z { | { z { l k j { o s g { z Sacar(cola,elem Sacar(cola,elem)) s r y x p r m j j d c x m i h c q g j Meter(cola, “B”) Meter(cola, “C”) l k h { } | ~ ~ ~ } ~ } } Metodología de Programación Colas. Implementación • Solución: • Tratar al array como una Estructura Circular, Circular donde la última posición va seguida de la primera Evitamos que el final de la cola alcance el final físico del array y no esté llena • Operación Meter Añade elementos a las posiciones del array e incrementa el índice final • Operación Sacar Más sencilla. Sólo se incrementa el índice frente a la siguiente posición Metodología de Programación 17 Colas. Implementación • Ejemplo: ¤ £ ¥ ¤ ¦ ¥ § ¦ ¥ § ¨ ¥ © ¨ ª £ ¦ ª « ¦ ¬ « ¨ ¬ ® ¨ £ ¤ £ ¢ ¥ ¤ ¦ ¥ § ¦ ¥ § ¨ ¥ © ¨ © © £ ¢ £ ® ª £ ¦ ª « ¦ ¬ « ¨ ¬ ­ ¨ ­ £ Meter(cola,”G”) ¡ ¡ Sacar(cola,elem Sacar(cola,elem)) ¡ ¡ Metodología de Programación Colas. Implementación ¿Como sabemos si la cola está vacía o llena? ¯ ­ Á À µ ´ ¶ µ · ¶ ¸ · ¹ ¸ · ¹ º · » º » Æ ´ ® à ¼ µ ¸ ¼ ½ ¸ ¾ ½ º ¾ Å Ã ³ ° ³ Meter(cola,”L”) Å Á È ² µ È Ë Ä ¹ ¸ · ¹ º · » º » ° ¼ µ ¸ ¼ ½ ¸ ¾ ½ º ¾ ¿ º ¿ ² Ê Ë Ë Ê Ì Í Ë Ì Î Í Ï Î Î Î Ï Ð Î Ñ Î Ñ © ± Ó Ò Ó Ò Ó Ó Ò Ü Û Ý Ü Û Ý Þ Û Þ × Ô Ø × Ø Ô Ô Ù Ô × Ù ß ß Ü Ü à à á á Þ Ú Ù Ô Û Ú Ü Û Ý Ü Û Ý Sacar(cola,elem Sacar(cola,elem)) Þ Û Ô Þ Ô Ô Ù Ù Õ Ô × Û Ú Ë ± Õ Ô Ú Ë Ë © » Â Ò Ù Ë Ï Ç » Ù Ï Ð Ä Ç Â ¸ · ® ¿ º Á · ¶ É Æ ´ ¿ µ ¶ µ ´ É µ ¯ ­ Á À ß Ù ß Ü Ü à á à á Þ Þ Þ Ö Ö Õ Õ â â â Ö Ö Õ ã â ä ã å ä æ å ç æ æ ç è æ é è æ é â æ â â â Õ Metodología de Programación 18 Colas. Implementación • Solución: • 1) Disponer de otra variable Contabilizará los elementos almacenados en la cola Variable=0 Cola vacía Variable=MaxCola Cola llena Inconveniente: añade más procesamiento a las operaciones Meter y Sacar • 2) Frente apunte a la casilla del array que precede a la del elemento frente de la cola Solución elegida Metodología de Programación Colas. Implementación • Ejemplo: ë ê ë ê ê ê ë ë û û ò ò ò ó ô ó õ ô ö õ ô ö ÷ ô ÷ í ï ï ò ò ø ø õ õ ù ù ú ú ÷ ÷ ï ó ò ô ó õ ô ö õ ô ö ÷ ô ÷ í í í ñ ï ì ñ ñ ï ì ñ Meter(cola,”G”) ì ï ò ð ð ò ø ø õ õ ù ù ú ú ÷ ÷ ê ê ð ð î î ì í î î í í í ¿Como saber si la cola está llena? Es necesario que la posición a la que apunta frente en cada momento este Reservada Cola Llena: final+ final+1 =frente ë ê ó ò ô ó õ ô ö õ ô ö ÷ ô ÷ ì ë ê ý ü ò ý ü ì ï ñ ï ì ñ ÿ ò ò ø ø õ õ ù ù ú ú ÷ ë ÷ ÿ ì ë ð ð þ î î þ í í Metodología de Programación 19 Colas. Implementación ¿Como saber si la cola está vacía? Cola Vacía: Frente = Final Sacar(cola,elem Sacar(cola,elem)) • Crear la cola (inicializarla vacía): frente =Maxcola (índice del array que precede al elemento frente de la cola) y final=Maxcola Cola Vacía correcto (frente = final) Metodología de Programación Colas. Implementación • Agrupamos en un registro los índices frente y final, junto con el array que contendrá los elementos de la cola CONSTANTES MAXCOLA ← 100 TIPOS TElemento = // Cualquier tipo de datos TCola = REGISTRO elementos:ARRAY[1..MAXCOLA]DE TElemento Frente,Final : [1.. MAXCOLA] FINREGISTRO Maxcola 5 1 13 2 ................... MaxCola Metodología de Programación 20 Colas. Implementación FUNC CrearCola():TCola VARIABLES cola: TCola INICIO cola.Frente ← MAXCOLA cola.Final ← MAXCOLA RESULTADO ← cola FIN PROC DestruirCola(↓↑cola :TCola) INICIO // No hay que hacer nada. FIN FUNC ColaLlena(↓cola:Tcola ):LÓGICO INICIO RESULTADO ← (cola.Final MOD MAXCOLA)+1 = cola.Frente FIN FUNC ColaVacia(↓cola:Tcola ):LÓGICO INICIO ← cola.Final = RESULTADO← cola.Frente FIN Metodología de Programación Colas. Implementación PROC MeterCola(↓↑cola:TCola; ↓elem:TElemento) VARIABLES fin:NATURAL INICIO fin ← (cola.Final MOD MAXCOLA) + 1 cola.Final ← fin cola.elementos[fin]←elem FIN PROC SacarCola(↓↑cola:TCola; ↑elem:TElemento) VARIABLES ini:NATURAL INICIO ini ← (cola.Frente MOD MAXCOLA) + 1 cola.Frente ← ini elem←cola.elementos[ini] FIN Metodología de Programación 21 Colas. Implementación 2) Con listas enlazadas con Punteros • Usamos dos variables de tipo puntero, frente y final, que apunten a los nodos que contienen los elementos frente y final ! ! " " # # $ % $ & % & $ " $ " ' ' % % ( ( ) ) • ¿Que sucedería si intercambiáramos las posiciones de frente y final en la lista enlazada? Metodología de Programación Colas. Implementación • Agrupamos las variables frente y final en un registro TIPOS TElemento = // cualquier tipo de datos TPuntero = PUNTERO A TNodo TNodo = REGISTRO valor : TElemento sig : TPuntero FINREGISTRO TCola = REGISTRO Frente : TPuntero Final : TPuntero FINREGISTRO , - * - + . * . / / 0 0 1 1 2 2 0 0 , + . . 3 3 1 1 4 4 5 5 Metodología de Programación 22 Colas. Implementación FUNC CrearCola(): TCola VARIABLES cola:TCola INICIO cola.Frente := NULO cola.Final := NULO RESULTADO ← cola FIN FUNC ColaVacia(↓cola: TCola):LÓGICO INICIO RESULTADO ← cola.Frente = NULO FIN PROC DestruirCola(↓↑cola: TCola) Variables nodo,sgte: TPuntero Inicio SI(cola.Frente≠NULO) ENTONCES sgte ← cola.Frente MIENTRAS (sgte≠NULO) HACER nodo ← sgte sgte ← sgte^.sig ELIMINAR(nodo) FINMIENTRAS FINSI cola.Frente ← NULO cola.Final ← NULO FIN Metodología de Programación Colas. Implementación PROC MeterCola(↓↑cola:TCola; ↓elem:TElemento) VARIABLES ptr: TPuntero Inicio ptr ← NUEVO(TNodo) ptr^.valor ← elem ptr^sig ← NULO SI ColaVacia(cola) ENTONCES cola.Frente ← ptr EN OTRO CASO cola.Final^.sig ← ptr FINSI cola.Final ← nuevonodo FIN PROC SacarCola (↓↑cola:TCola; ↑elem:TElemento) VARIABLES temp : TipoPuntero INICIO temp ← cola.Frente elem ← cola.Frente^.valor cola.Frente ← cola.Frente^.sig SI (cola.Frente=NULO) ENTONCES cola.Final ← NULO FINSI ELIMINAR(temp) FIN Metodología de Programación 23 Colas. Aplicaciones Ejemplo: Reconocimiento del lenguaje. L={W$W/W es una cadena que no contiene a$} Algoritmo Lenguaje_L DESDE MCola IMPORTA TCola, CrearCola, ColaVacia, SacarCola, MeterCola, DestruirCola CONSTANTES ENTER ← CHR(13) TIPOS TElemento = CARÁCTER VARIABLES bien : LÓGICO c1,c2 : TElemento cola : TCola INICIO cola ← CrearCola() LEER(c1) MIENTRAS (c1 ≠ ‘$’) HACER MeterCola(cola,c1) LEER(c1) FINMIENTRAS Metodología de Programación Colas. Aplicaciones Leer(c1) bien ← CIERTO MIENTRAS (bien ∧ (c1≠ENTER) HACER SI ColaVacia(cola) ENTONCES bien ← FALSE EN OTRO CASO SacarCola(cola,c2) SI (c1 ≠c2) ENTONCES bien ← FALSE EN OTRO CASO LEER(c1) FINSI FINSI FINMIENTRAS SI (bien ∧ ColaVacia(cola)) ENTONCES Escribir(“Pertenece”) EN OTRO CASO Escribir(“No pertenece”) FINSI DestruirCola(cola) FIN Metodología de Programación 24 Listas • Definición de lista • Implementación - Estática - Dinámica Metodología de Programación Listas • Definición: Una lista es una colección de elementos homogéneos (del mismo tipo), con una relación lineal entre ellos. • Los elementos pueden o no estar ordenados con respecto a algún valor y se puede acceder a cualquier elemento de la lista. • En realidad, las pilas y colas vistas en secciones anteriores son listas, con algunas restricciones. Metodología de Programación 25 Listas Operaciones sobre listas: Crear ¿Esta vacía? ¿Está llena? - De forma ordenada Insertar un elemento - De forma no ordenada Eliminar un elemento Imprimir Destruir Metodología de Programación Listas MÓDULO Mlistas DEFINICIÓN TIPOS =// cualquier tipo de datos = // por definir TElemento TLista FUNC CrearLista():TLista FUNC ListaVacia(↓lista:TLista): LÓGICO FUNC ListaLlena(↓lista:TLista): LÓGICO PROC InsertarLista(↓↑lista:TLista; ↓elem:TElemento) PROC EliminarLista(↓↑Lista:TLista; ↓elem:TElemento) PROC ImprimirLista(lista:TLista) PROC DestruirLista(↓↑lista: TLista) IMPLEMENTACIÓN .............. Fin Metodología de Programación 26 Listas • Implementación: – Representación secuencial – Representación enlazada - Dinámica - Estática Metodología de Programación Listas 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. Metodología de Programación 27 Listas Estáticas • Array de registros: • Elemento. • Enlace al siguiente elemento. • Los registros pueden almacenarse en cualquier orden físico y se enlazarán a través del campo enlace. Metodología de Programación Metodología de Programación 28 Listas • Inconveniente Variable estática Elección de Tamaño Máximo • Debemos escribir nuestros propios algoritmos de manejo de memoria No disponemos de NUEVO y ELIMINAR. ELIMINAR • En el array de registros coexistirán dos listas: - Nuestra lista enlazada de elementos. - Una lista enlazada con el espacio libre disponible. Metodología de Programación Listas Metodología de Programación 29 Listas Consideraciones • El cero (o cualquier otro valor distinto de [1..10]) hará las funciones de NULO en las listas enlazadas con punteros. • Cuando no existe ningún elemento en la lista (lista vacía) sólo existirá la lista libre, que enlaza todas las posiciones del array. • Si la lista se llena, no tendremos lista libre. • Para simular el manejo de memoria real mediante asignación dinámica de memoria, consideramos el array y la variable Libre como globales al módulo de implementación de la lista. Metodología de Programación MÓDULO Mlistas DEFINICIÓN CONSTANTES VALOR_NULO ← 0 // Hace las funciones de NULO MAX ← 100 TIPOS TLista = [0..Max] TElemento = // cualquier tipo de datos TNodo = REGISTRO elemento : TElemento sig : TLista FINREGISTRO FUNC CrearLista():TLista FUNC ListaVacia(↓lista:TLista): LÓGICO PROC ListaLlena(↓lista: TLista): LÓGICO PROC ImprimirLista(↓lista: TLista) PROC InsertarLista(↓↑lista:TLista; ↓elem:TElemento) PROC EliminarLista(↓↑lista:TLista; ↓elem:TElemento) PROC DestruirLista(↓↑lista:TLista) Metodología de Programación 30 IMPLEMENTACIÓN TIPOS TMemoria = ARRAY [1..MAX] DE TNodo VARIABLES memoria : TMemoria libre : TLista FUNC CrearLista():TLista INICIO RESULTADO ← VALOR_NULO FIN FUNC ListaVacia(↓lista:TLista): LÓGICO INICIO RESULTADO ← (lista = VALOR_NULO) FIN FUNC ListaLlena(↓lista:TLista):LÓGICO INICIO RESULTADO ← (libre = VALOR_NULO) FIN Metodología de Programación Para los procedimientos NUEVO y ELIMINAR, ELIMINAR necesitamos antes implementar las operaciones (NuevoNodo, EliminarNodo) equivalentes a las que usamos al trabajar con memoria dinámica. FUNC NuevoNodo(): Tlista VARIABLES ptr: TLista INICIO ptr ← libre SI (ptr ≠ Nulo) ENTONCES libre ← memoria[ptr]. sig FINSI RESULTADO ← ptr FIN PROC EliminarNodo (↓↑p : TLista) INICIO memoria[p].sig ← libre lbre ← p p ← VALOR_NULO FIN Metodología de Programación 31 de en ep D PROC ImprimirLista(↓lista : TLista) VARIABLES ptr : TLista INICIO ptr ← lista de to en m le TE MIENTRAS (ptr ≠ VALOR_NULO) HACER Escribir(memoria[ptr].elemento) ptr ← memoria[ptr].sig FINMIENTRAS FIN PROC InsertarLista(↓↑lista: TLista; ↓elem: TElemento) VARIABLES ptr : TLista INICIO ptr ← NuevoNodo() SI (ptr ≠ VALOR_NULO) ENTONCES memoria[ptr].elemento ← elem memoria[ptr].sig ← lista lista ← ptr FINSI FIN Metodología de Programación PROC EliminarLista (↓↑lista: TLista; ↓elem :TElemento) VARIABLES pav, pret : TLista Suponemos que el INICIO elemento a borrar pav ← lista // puntero avanzado está en la lista pret ← Nulo // puntero retrasado MIENTRAS (memoria[pav].elemento ≠ elem) HACER pret ← pav pav ← memoria[pav].sig FINMIENTRAS SI (pret = VALOR_NULO) ENTONCES lista ← memoria[lista].sig EN OTRO CASO memoria[pret].sig ← memoria[pav].sig FINSI EliminarNodo(pav) Fin Metodología de Programación 32 PROC DestruirLista(↓↑lista: TLista) Variables aux: TLista INICIO MIENTRAS (lista ≠ VALOR_NULO) HACER aux ← lista lista ← memoria[lista].sig EliminarNodo(aux) FIN FIN INICIO // Mlista Libre ← 1 PARA ptr ← 1 HASTA (Max-1) HACER memoria[ptr].sig ← ptr + 1 FINPARA memoria[Max].enlace ← VALOR_NULO FIN // Mlista Metodología de Programación Listas enlazadas circulares • Implementación estática o dinámica. • El campo de enlace del último nodo apunta al primer nodo de la lista, en lugar de tener el valor NULO. • No existe ni primer ni último nodo. Tenemos un anillo de elementos enlazados unos con otros. Metodología de Programación 33 Listas enlazadas circulares • Es conveniente, aunque no necesario, tener un enlace (puntero o índice) al último nodo lógico de la lista. Así podemos acceder facilmente a ambos extremos de la misma. p • Una lista circular vacía vendrá representada por un valor NULO (o VALOR_NULO). Metodología de Programación Listas enlazadas circulares Ejemplo: (usando una implementación estática) PROC ImprimirLista(↓lista:TLista) VARIABLES ptr : TLista INICIO ptr ← lista SI (ptr ≠ VALOR_NULO) ENTONCES REPETIR Escribir(memoria[ptr].elemento) ptr ← memoria[ptr].sig HASTA QUE ptr = lista FINSI Fin Metodología de Programación 34 Listas enlazadas circulares • Con una lista enlazada circular es muy fácil implementar una Cola, sin tener que disponer de un registro con dos campos para el frente y para el final. Frente Final p Implementación Metodología de Programación Listas doblemente enlazadas • Es una lista enlazada en la que cada nodo tiene al menos tres campos: - Elemento. El dato de la lista. - Enlace al nodo anterior. - Enlace al nodo siguiente. • Los algoritmos para las operaciones sobre listas doblemente enlazadas son normalmente más complicados. • Pueden ser recorridas fácilmente en ambos sentidos. lista Implementación Metodología de Programación 35 Listas doblemente enlazadas • Una lista doblemente enlazada puede modificarse para obtener una estructura circular de la misma lista Implementación Metodología de Programación Listas NIVEL DE UTILIZACIÓN • Estructura muy utilizada. • Ejemplo: Manejo de tablas hash con el método de encadenamiento para el tratamiento de sinónimos. – Utilizaríamos un array de listas como tabla hash. (Lo que en el primer tema se llamó Encadenamiento) – Las listas tienen como elementos cadenas de caracteres. Metodología de Programación 36 Modulo Mhash DEFINICIÓN DESDE MLista IMPORTA Tlista CONSTANTES MAXCAD ← 20 MAXELE ← 100 TIPOS TCadena = TElemento = TRango = TTablaHash= ARRAY [0..MAXCAD-1] DE CARÁCTER TCadena [0.. MAXELE-1] ARRAY TRango DE TLista PROC Almacenamiento(↓↑tabla:TTablaHash; ↓dato:TElemento) FUNC Búsqueda(↓tabla:TTablaHash; ↓dato:TElemento):LÓGICO PROC Eliminación(↓↑tabla:TTablaHash; ↓dato:TElemento) Metodología de Programación IMPLEMENTACIÓN PROC Almacenamiento(↓↑tabla:TTablaHash; ↓dato:TElemento) INICIO Insertar(tabla[Hash(dato)],dato) FIN FUNC Búsqueda(↓tabla:TTablaHash; ↓dato:TElemento):LÓGICO INICIO RESULTADO ← Buscar(tabla[Hash(dato)],dato) FIN PROC Eliminación(↓↑tabla:TTablaHash; ↓dato:TElemento) INICIO Eliminar(tabla[Hash(dato)],dato) FIN Fin (* Mhash *) Metodología de Programación 37 Árboles binarios • 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. derecho • El subárbol izquierdo o derecho puede estar vacío. • Cada elemento de un árbol binario se denomina nodo. nodo Metodología de Programación Árboles binarios • Un método convencional para representar gráficamente un árbol binario es: • Consta de 9 nodos. A B • A es el nodo raiz. • El subárbol izquierdo tiene como nodo raiz B. C • El subárbol derecho tiene C como raiz. E D G • La ausencia de ramas indica un árbol vacío. F H I Metodología de Programación 38 Árboles binarios • 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. hoja • Un nodo n1 es un antecesor de un nodo n2 (y n2 es un descendiente de n1) n1 si n1 es el padre de n2 o el padre de algún antecesor de n2. 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. n1 Un descendiente derecho se puede definir de forma similar. • Dos nodos son hermanos si son los hijos izquierdo y derecho del mismo padre. Metodología de Programación Árboles binarios • Árbol estrictamente binario: 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: 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: 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. Metodología de Programación 39 Árboles binarios 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 Metodología de Programación Árboles binarios Á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. Metodología de Programación 40 Árboles binarios Operaciones sobre árboles: ¿Esta vacío? Crear árbol vacío Crear árbol dada su raíz, y sus hijos derecho e Izquierdo ¿Está lleno? Devolver el contenido del nodo raíz Devolver el subárbol derecho Devolver el subárbol derecho Destruir Metodología de Programación Módulo MArbolBin DEFINICIÓN Imp TIPOS TElemento = // Cualquier tipo de datos TArbolBin = PUNTERO A TNodoArbolBin TNodoArbolBin = REGISTRO dato : TElemento izq,der : TArbolBin FINREGISTRO lem e diná ntación mic a FUNC CrearArbolVacio():TArbolBin FUNC CrearArbol(↓raiz:TElemento;↓izq, ↓dch: TArbolBin ): TArbolBin FUNC ArbolVacio(↓arbol:TArbolBin):LÓGICO FUNC Info(↓arbol:TArbolBin):TElemento FUNC Izq(↓arbol:TArbolBin): TArbolBin FUNC Der(↓arbol: TArbolBin): TArbolBin PROC DestruirArbol(↓↑arbol: TArbolBin) Metodología de Programación 41 IMPLEMENTACIÓN FUNC CrearArbolVacio():TArbolBin INICIO RESULTADO ← NULO FIN FUNC CrearArbol(↓raiz:TElemento;↓izq, ↓dch: TArbolBin ): TArbolBin VARIABLES arbol : TArbolBin INICIO arbol ← NUEVO(TNodoArbolBin) arbol^.dato ← raiz arbol^.izq ← izq arbol^.der ← dch RESULTADO ← arbol FIN Metodología de Programación FUNC ArbolVacio(↓arbol:TArbolBin):LÓGICO INICIO RESULTADO ← (arbol = NULO) FIN FUNC Info(↓arbol:TArbolBin):TElemento INICIO RESULTADO ← arbol^.dato FIN FUNC Izq(↓arbol:TArbolBin): TArbolBin INICIO RESULTADO ← arbol^.izq FIN FUNC Der(↓arbol: TArbolBin): TArbolBin INICIO RESULTADO ← arbol^.der FIN Metodología de Programación 42 PROC DestruirArbol(↓↑arbol: TArbolBin) INICIO SI (¬ArbolVacio(arbol)) ENTONCES DestruirArbol(arbol^.der) DestruirArbol(arbol^.izq) ELIMINAR(arbol) FINSI FIN FIN // MArbolBin Metodología de Programación Módulo MArbolBinEstático DEFINICIÖN CONSTANTES VALOR_NULO ← 0 MAX ← 100 TIPOS Im Se deja propuesto comoplem est entac ejercicio la de los procedimientos átic ión y funciones para una implementación a estática de un arbol binario TArbolBin = [0..MAX] TNodoArbolBin = REGISTRO dato : TElemento izq,der : TArbolBin FINREGISTRO FUNC CrearArbolVacio():TArbolBin FUNC CrearArbol(↓raiz:TElemento;↓izq, ↓dch: TArbolBin ): TArbolBin FUNC ArbolVacio(↓arbol:TArbolBin):LÓGICO FUNC Info(↓arbol:TArbolBin):TElemento FUNC Izq(↓arbol:TArbolBin): TArbolBin FUNC Der(↓arbol: TArbolBin): TArbolBin PROC DestruirArbol(↓↑arbol: TArbolBin) Metodología de Programación 43 Árboles binarios 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: + 12 5 + - 5+2 3 4 1 2 Metodología de Programación Árboles binarios Ejemplo: Diseñemos un algoritmo para evaluar una expresión aritmética que está almacenada en un árbol binario. Tipos TipoDecision = (Operador, Operando) TElemento = REGISTRO CASO contenido:TipoDecision SEA Operador: oper: CARÁCTER Operando: val: REAL FINCASO FINREGISTRO Metodología de Programación 44 FUNC Eval(↓arbol:TArbolBin):REAL VARIABLES dato:TElemento; result: REAL INICIO dato ← Info(arbol) SI (dato.contenido = Operando) ENTONCES result ← dato.val EN OTRO CASO CASO dato.oper SEA '+': result ← Eval(Izq(arbol))+Eval(Der(arbol)) '-': result ← Eval(Izq(arbol))-Eval(Der(arbol)) '*': result ← Eval(Izq(arbol))*Eval(Der(arbol)) '/': result ← Eval(Izq(arbol))/Eval(Der(arbol)) FINCASO FINSI RESULTADO ← result Fin Metodología de Programación Árboles binarios de búsqueda 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 Metodología de Programación 45 Árboles binarios de búsqueda • 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 I F C G Metodología de Programación Árboles binarios de búsqueda Operaciones: Crear Buscar Insertar Suprimir Imprimir + Las definidas para un árbol binario general Metodología de Programación 46 Módulo MABB Definición TIPOS TRecorrido = (InOrden,PreOrden,PostOrden) TClave = ENTERO TElemento = REGISTRO clave:TClave ......... FINREGISTRO TABB = PUNTERO A TNodoABB TNodoABB = REGISTRO izq,der:TABB elem:TElemento FINREGISTRO // Operaciones típicas de los árboles FUNC CrearABB():TABB FUNC FUNC FUNC FUNC PROC ABBVacio(↓arbol:TABB):LÓGICO InfoABB(↓arbol:TABB):TElemento IzqABB(↓arbol:TABB): TABB DerABB(↓arbol: TABB): TABB DestruirABB(↓↑arbol: TABB) Metodología de Programación // Operaciones Exclusivas de los árboles binarios de búsqueda PROC BuscarABB(↓arbol:TABB; ↓c:TClave; ↑dato:TElemento; ↑EnArbol:LÓGICO) PROC InsertarABB(↓↑arbol:TABB; ↓dato:TElemento) PROC SuprimirABB(↓↑arbol:TABB; ↓c:TClave) PROC ImprimirABB(↓arbol:TABB; ↓rec:TRecorrido) IMPLEMENTACIÓN FUNC CrearABB():TABB INICIO RESULTADO ← NULO FIN FUNC ABBVacio(↓arbol:TABB):LÓGICO INICIO RESULTADO ← (arbol = NULO) FIN FUNC InfoABB(↓arbol:TABB):TElemento INICIO RESULTADO ← arbol^.dato FIN Metodología de Programación 47 FUNC IzqABB(↓arbol:TABB): TABB INICIO RESULTADO ← arbol^.izq FIN FUNC DerABB(↓arbol: TABB): TABB INICIO RESULTADO ← arbol^.der FIN PROC DestruirABB(↓↑arbol: TABB) INICIO DestruirABB(arbol^.izq) DestruirABB(arbol^.dch) ELIMINAR(arbol) FIN Metodología de Programación PROC BuscarABB(↓arbol:TABB; ↓c:TClave; ↑dato:TElemento; ↑EnArbol:LÓGICO) // Solución Iterativa VARIABLES ptrArbol: TABB ele:TElemento INICIO EnArbol ← FALSO ptrArbol ← arbol MIENTRAS ((¬ABBVacio(ptrArbol)) ∧ (¬EnArbol)) HACER ele = InfoABB(ptrArbol) SI (ele.clave = c) ENTONCES EnArbol ← CIERTO dato ← ele SINO SI (c < ele.clave) ENTONCES ptrArbol ← IzqABB(ptrArbol) EN OTRO CASO ptrArbol ← DechABB(ptrArbol) FINSI FINMIENTRAS FIN Metodología de Programación 48 PROC BuscarABB(↓arbol:TABB; ↓c:TClave; ↑dato:TElemento; ↑EnArbol:LÓGICO) // Solución Recursiva VARIABLES ele:TElemento INICIO SI (ABBVacio(arbol)) ENTONCES EnArbol ← FALSO EN OTRO CASO ele = InfoABB(arbol) SI (ele.clave = c) ENTONCES EnArbol ← CIERTO dato ← ele SINO SI (c < ele.clave ) ENTONCES BuscarABB(IzqABB(arbol),c,dato,EnArbol) EN OTRO CASO BuscarABB(DechABB(arbol),c,dato,EnArbol) FINSI FINSI FIN Metodología de Programación Árboles binarios de búsqueda 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 F D A G G C Los mismos datos, insertados en orden diferente, producirán árboles con formas o distribuciones de elementos muy distintas. F E Entrada: BADCGFE Metodología de Programación 49 Árboles binarios de búsqueda PROC InsertarABB(↓↑arbol:TABB; ↓dato:TElemento) // Solución Iterativa VARIABLES nuevonodo,pav,pret:TABB clavenueva:Tclave ele:TElemento Inicio nuevonodo ← NUEVO(TNodoABB) nuevonodo^.izq ← NULO nuevonodo^.der ← NULO nuevonodo^.elem ← dato clavenueva ← dato.clave Los datos, insertados en orden Avanzado ← arbol pavmismos // Puntero diferente, árboles NULO pret ←producirán // con Puntero Retrasado formas o distribuciones de elementos muy distintas. Metodología de Programación Árboles binarios de búsqueda MIENTRAS (pav ≠ NULO) HACER pret ← pav ele = pav^.elem SI (clavenueva < ele.clave ) ENTONCES pav ← pav^.izq // Voy hacia el hijo izquierdo EN OTRO CASO pav ← pav^.dch // Voy hacia el hijo derecho FINSI FINMIENTRAS ele = pret^.elem SI (clavenueva < ele.clave ) ENTONCES pret ^.izq ← nuevonodo // Inserto en el hijo izquierdo EN OTRO CASO pret ^.dch ← nuevonodo // Inserto en el hijo izquierdo FINSI FIN Metodología de Programación 50 Árboles binarios de búsqueda PROC InsertarABB(↓↑arbol:TABB; ↓dato:TElemento) VARIABLES ele:TElemento ¿Por qué usamos arbol^.izq INICIO // Solución Recursiva y arbol^.dch en vez de SI (ABBVacio(arbol)) ENTONCES IzqABB(arbol) y arbol ← NUEVO(TNodoABB) DechABB(arbol? arbol^.izq ← NULO arbol^.der ← NULO arbol^.elem ← dato EN OTRO CASO ele = InfoABB(arbol) SI (dato.clave < ele.clave) ENTONCES InsertarABB(arbol^.izq, dato) EN OTRO CASO dato) Los mismos datos,InsertarABB(arbol^.dch, insertados en orden FINSI diferente, producirán árboles con FINSI formas o distribuciones de elementos FIN muy distintas. Metodología de Programación Árboles binarios de búsqueda 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 Metodología de Programación 51 Árboles binarios de búsqueda ex-padre de x padre de x Caso 2 x ex-hijo de x hijo de x J J Q B R L M R L Z N K Eliminar Q P B N K P z Caso 3 M Metodología de Programación PROC SuprimirABB(↓↑arbol:TABB; ↓c:TClave) // Solución Iterativa VARIABLES pav,pret:TABB INICIO pav ← arbol pret ← NULO //Busco el elemento MIENTRAS (pav ≠ NULO) ∧ (pav^.elem.clave ≠ c) HACER pret ← pav SI (c < pav^.elem.clave) ENTONCES pav ← pav^.izq EN OTRO CASO pav ← pav^.der FINSI FINMIENTRAS SI (pav = NULO) ENTONCES // No hacer Nada, ya que no hay nada que borrar SINO SI (pav = arbol) ENTONCES // equivalente a: (pret = NULO) SuprimirNodo(arbol) SINO SI (pret^.izq = pav) ENTONCES SuprimirNodo(pret^.izq) EN OTRO CASO SuprimirNodo(pret^.der) FINSI FIN Metodología de Programación 52 PROC SuprimirNodo(↓↑arbol:TABB) Variables // Solución Iterativa 0 o 1 hijo temp,ant:TABB Inicio temp ← arbol SI (arbol^.der = NULO) ENTONCES arbol ← arbol^.izq // Casos sin Hijos ó sin Hijo derecho SINO SI (arbol^.izq = NULO) ENTONCES arbol ← arbol^.der EN OTRO CASO temp ← arbol^.izq 1 hijo // Caso de Sólo Hijo derecho // Caso Hijos derecho y izquierdo 2 hijos // Busco el mayor hijo derecho del hijo izquierdo ant ← arbol MIENTRAS (temp^.der <> NULO) HACER anterior ← temp temp ← temp^.der FINMIENTRAS arbol^.elem ← temp^.elem SI (anterior = arbol) ENTONCES anterior^.izq ← temp^.izq EN OTRO CASO anterior^.der ← temp^.izq FINSI FINSI ELIMINAR(temp) FIN Metodología de Programación PROC SuprimirABB(↓↑arbol:TABB; ↓c:TClave) // Solución Recursiva VARIABLES ele:TElemento INICIO SI (ABBVacio(arbol)) ENTONCES // No hacer Nada, ya que no hay nada que borrar EN OTRO CASO ele = InfoABB(arbol) SI (ele.clave = c) ENTONCES SuprimirNodo(arbol) SINO SI (c < ele.clave ) ENTONCES SuprimirABB(arbol^.izq,c) EN OTRO CASO SuprimirABB(arbol^.dch,c) FINSI FINSI ¿Por qué usamos arbol^.izq FIN y arbol^.dch en vez de IzqABB(arbol) y DechABB(arbol? ? Metodología de Programación 53 PROC SuprimirNodo(↓↑arbol:TABB) // Solución Recursiva Variables temp:TABB 0 o 1 hijo ele :TElemento FUNC MayorHijoDerecho(↓arbol:TipoABBúsqueda):TElemento INICIO // Solución Recursiva SI (ABBVacio(DchABB(arbol))) ENTONCES RESULTADO ← InfoABB(arbol) 1 hijo EN OTRO CASO RESULTADO ← MayorHijoDerecho(DchABB(arbol)) FINSI FIN INICIO SI (arbol^.der = NULO) ENTONCES temp ← arbol arbol ← arbol^.izq// Casos sin Hijos ó sin Hijo derecho ELIMINAR(temp) SINO SI (arbol^.izq = NULO) ENTONCES temp ← arbol arbol ← arbol^.der// Caso de Sólo Hijo derecho ELIMINAR(temp) // Caso Hijos derecho y izquierdo EN OTRO CASO ele ← MayorHijoDerecho(IzqABB(arbol)) arbol^.elem ← ele SuprimirABB(arbol^.izq,ele.clave) FINSI Metodología de Programación FIN Árboles binarios de búsqueda Consideraciones acerca de la operación de imprimir. • 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 imprimir los elementos de un árbol? ¿en qué orden?. Metodología de Programación 54 Árboles binarios de búsqueda • Para recorrer un árbol binario en general (de búsqueda o no), 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 Metodología de Programación PROC Imp_InOrden(↓arbol:TABB) INICIO SI (¬ABBVacio(arbol)) ENTONCES Imp_InOrden(IzqABB(arbol)) ImpNodo(InfoABB(arbol)) Imp_InOrden(DerABB(arbol)) FINSI FIN PROC Imp_PreOrden(↓arbol:TABB) INICIO SI (¬ABBVacio(arbol)) ENTONCES ImpNodo(InfoABB(arbol)) Imp_PreOrden(IzqABB(arbol)) Imp_PreOrden(DerABB(arbol)) FINSI FIN Metodología de Programación 55 PROC Imp_PostOrden(↓arbol:TABB) INICIO SI (¬ABBVacio(arbol)) ENTONCES Imp_PostOrden(IzqABB(arbol)) Imp_PostOrden(DchABB(arbol)) ImpNodo(InfoABB(arbol)) FINSI Fin PROC ImprimirABB(↓arbol:TABB; ↓rec:TRecorrido) Inicio CASE rec SEA inorden: Imp_InOrden(arbol) preorden: Imp_PreOrden(arbol) postorden: Imp_PostOrden(arbol) FINCASO Fin Fin (* MArbolBinarioBusqueda *) Metodología de Programación Árboles binarios de búsqueda Ejemplo: P S F Y B R H Z T G W • El recorrido InOrden mostraría: BFGHPRSTWYZ • El recorrido PreOrden: PFBHGSRYTWZ • El recorrido PostOrden: BGHFRWTZYSP Metodología de Programación 56 Árboles binarios de búsqueda Nivel de utilización • Aplicaciones en las que estén implicas operaciones de búsqueda de elementos • Ejemplo: Supongamos que deseamos implementar un diccionario inglés/español en que la búsqueda de la traducción de una palabra inglesa sea rápida. Para ello podemos usar un árbol binario de búsqueda en el que el tipo elemento sea un registro con la palabra en inglés (que será la clave) y la palabra en español. Metodología de Programación Árboles binarios de búsqueda ALGORITMO Diccionario DESE MABB IMPORTA TABB, CrearABB, DestruirABB, BuscarABB, InsertarABB, SuprimirABB, ImprimirABB CONSTANTES MAXCAD = 20 TIPOS TCadena = ARRAY [0..MAXCAD-1] DE CARÁCTER TDic = TABB Tclave = TCadena TElemento = REGISTRO clave:TClave // Palabra inglés traducción: TCadena // Palabra Español FINREGISTRO Metodología de Programación 57 Árboles binarios de búsqueda PROC InsPalDic(↓↑d:Tdic; ↓pal: TElemento) INICIO InsertarABB(d,pal) FIN PROC BuscaPalDic(↓d:TDic; ↓inglés:TClave ; ↑pal: TElemento; ↑encontrado:LÓGICO) INICIO BuscarABB(d,inglés,pal,encontrado) FIN PROC BorrarPalDic(↓↑d:TDic; ↓inglés:TClave) INICIO SuprimirABB(d,inglés) FIN Metodología de Programación Bibliografía 6 7 8 9 : ; < = > ? 8 9 : ; @ A B : C : : D @ E F G F H I J K I L M N J O P Q K O Q P I J R S T I O U J F E V W X Y Z [ ; Z \ ] \ ^ Y F _ ] ` a [ b c d \ 6 7 m e e f n C Y D g V 9 a o [ h o V ? m a \ n ] [ D Y 9 [ Z A V ; ; E @ i j : [ k H F [ P @ U l p = P < I = q F I K r s t S t u v v w x d L p U P r O q U J y S J O P Q K O Q P I J R S R I O U J M U z { S O U J w _ ] ` a [ b \ e e @ | o o o F d 6 7 E 9 } C o o ? E 9 } C G @ ~ F S J U L Q K r s t R S v v w E V W X Y Z [ ; Z \ ] \ ^ Y F a V Y g \ ] P U z L S q I J K U t | d u V [ e e @ o o o F N 6 7 E P U p n P I o q l I ? K E r s t u n v v E F ; Z \ ] \ ^ @ Y ; F i L j V ] L S \ t [ e p @ Q 9 I Z { \ S i R i S Y c ~ V i e V B @ | o o l F Metodología de Programación 58