Programación III, Guía 7 1 Facultad : Ingeniería Escuela : Computación Asignatura: Programación III Tema: “ARBOLES BINARIOS”. Objetivo • Implemente la estructura de datos arboles utilizando C#. NET. • Conozca los recorridos más comunes en los árboles. Introducción En ciencias de la computación, un árbol binario es una estructura de datos en la cual cada nodo siempre tiene un hijo izquierdo y un hijo derecho. No pueden tener más de dos hijos (de ahí el nombre ‘Binario’). Si algún hijo tiene como referencia a null, es decir que no almacena ningún dato, entonces este es llamado un nodo externo. En el caso contrario el hijo es llamado un nodo interno. Terminología: Nodo: Cada elemento en un árbol. Nodo Raíz: Primer elemento agregado al árbol. Nodo Padre: Se le llama así al nodo predecesor de un elemento. Programación III, Guía 7 2 Nodo Hijo: Es el nodo sucesor de un elemento. Nodo Hermano: Nodos que tienen el mismo nodo padre. Nodo Hoja: Aquel nodo que no tiene hijos. Subárbol: Todos los nodos descendientes por la izquierda o derecha de un nodo. Altura y Niveles: La altura es la cantidad de niveles. Programación III, Guía 7 Recorrido del árbol: Recorrer el árbol significa que cada nodo sea procesado una vez en una secuencia determinada. Existen dos enfoques generales: • Recorrido en Profundidad: El proceso exigen alcanzar las profundidades de un camino desde la raíz hacia el descendiente más lejano del primer hijo, antes de proseguir con el segundo. • Recorrido en Anchura: El proceso se realiza horizontalmente desde la raíz a todos sus hijos antes de pasar con la descendencia de algunos de ellos. Algoritmos: Recorrido PreOrden(RID) void preOrden(ArbolBinario raíz) { if(raiz) { visitar(raiz–>dato); preOrden(raiz–>izq); preOrden(raiz–>der); } } El recorrido en PreOrden del árbol es el siguiente: 15, 6, 4, 10, 20, 17, 22 3 Programación III, Guía 7 4 Recorrido EnOrden (IRD) void enOrden(ArbolBinario raíz) { if(raiz) { enOrden(raiz–>izq); visitar(raiz–>dato); enOrden(raiz–>der); } } El recorrido en EnOrden del árbol es el siguiente: 4, 6, 10, 15, 17, 20, 22 Recorrido PostOrden (IDR) void PostOrden(ArbolBinario raíz) { if(raiz) { PostOrden(raiz–>izq); PostOrden(raiz–>der); visitar(raiz–>dato); } } El recorrido en PostOrden del árbol es el siguiente: 4, 10, 6, 17, 22, 20, 15 Materiales y equipo • • • Guía de Laboratorio Nº 7. Computadora con programa: o Visual Studio 2005. C# Dispositivo de Almacenamiento (USB). Programación III, Guía 7 Procedimiento using System; using System.Collections.Generic; using System.Text; namespace arboles { public class NodoT { public NodoT NodoIzquierdo; public int Informacion; public NodoT NodoDerecho; //Constructor public NodoT() { this.NodoIzquierdo = null; this.Informacion = 0; this.NodoDerecho = null; } } class Program { static void Main(string[] args) { int Opcion = 0; NodoT Raiz = null; int Dato; do { Opcion = Menu(); switch (Opcion) { case 1: Console.Write("Valor del Nuevo Nodo: "); Dato = int.Parse(Console.ReadLine()); if (Raiz == null) { NodoT NuevoNodo = new NodoT(); NuevoNodo.Informacion = Dato; Raiz = NuevoNodo; } else { Insertar(Raiz, Dato); } Console.Clear(); break; //Recorrido en Pre Orden del Arbol case 2: RecorridoPreorden(Raiz); Console.WriteLine("Fin del Recorrido,..."); Console.ReadLine(); Console.Clear(); break; //Recorrido en Post Orden del Arbol case 3: RecorridoPostorden(Raiz); Console.WriteLine("Fin del Recorrido,..."); Console.ReadLine(); Console.Clear(); break; //Recorrido en In Orden del Arbol 5 Programación III, Guía 7 6 case 4: RecorridoInorden(Raiz); Console.WriteLine("Fin del Recorrido,..."); Console.ReadLine(); Console.Clear(); break; case 5: Console.Write("Teclee el Dato a Buscar: "); Dato = int.Parse(Console.ReadLine()); if (Raiz != null) { BuscarNodo(Raiz, Dato); } else { Console.WriteLine("ERROR, Arbol Vacio...."); } Console.Clear(); break; case 6: Console.Write("Teclee el Dato a Eliminar: "); Dato = int.Parse(Console.ReadLine()); if (Raiz != null) { EliminarNodo(ref Raiz, Dato); } else { Console.WriteLine("ERROR, Arbol Vacio...."); } Console.Clear(); break; case 7: Finalizar(); break; } } while (Opcion != 7); } static int Menu() { int Resultado = 0; do { Console.WriteLine("MENU DE ARBOLES"); Console.WriteLine(""); Console.WriteLine("1.- Registrar un Nuevo Nodo"); Console.WriteLine("2.- Recorrido en Pre-orden"); Console.WriteLine("3.- Recorrido en Post-orden"); Console.WriteLine("4.- Recorrido en In-orden"); Console.WriteLine("5.- Buscar un Nodo"); Console.WriteLine("6.- Eliminar un Nodo"); Console.WriteLine("7.- Finalizar el Programa"); Console.WriteLine(""); Console.Write("Teclee la Opcion Deseada: "); Resultado = int.Parse(Console.ReadLine()); Console.WriteLine(""); if (Resultado < 1 || Resultado > 7) { Console.WriteLine("ERROR, Opcion Invalida...."); Console.ReadLine(); Console.WriteLine(""); } Console.Clear(); } while (Resultado < 1 || Resultado > 7); Programación III, Guía 7 return Resultado; } //Insertar en un arbol binario static void Insertar(NodoT Raiz, int Dato) { if (Dato < Raiz.Informacion) { if (Raiz.NodoIzquierdo == null) { NodoT NuevoNodo = new NodoT(); NuevoNodo.Informacion = Dato; Raiz.NodoIzquierdo = NuevoNodo; } else { //Llamada recursiva Insertar(Raiz.NodoIzquierdo, Dato); } } else //Buscar por el lado derecho { if (Dato > Raiz.Informacion) { if (Raiz.NodoDerecho == null) { NodoT NuevoNodo = new NodoT(); NuevoNodo.Informacion = Dato; Raiz.NodoDerecho = NuevoNodo; } else { //Llamada recursiva por el lado derecho Insertar(Raiz.NodoDerecho, Dato); } } else { //El Nodo existe en el Arbol Console.WriteLine("Nodo Existente, Imposible Insertar..."); Console.ReadLine(); } } } //Metodo de recorrido en Pre-Orden static void RecorridoPreorden(NodoT Raiz) { if (Raiz != null) { Console.Write("{0}, ", Raiz.Informacion); RecorridoPreorden(Raiz.NodoIzquierdo); RecorridoPreorden(Raiz.NodoDerecho); } } //Metodo de recorrido en In-Orden static void RecorridoInorden(NodoT Raiz) { Console.WriteLine("No existe ningun metodo para esta opcion..."); Console.Read(); } //Metodo de recorrido en Post-Orden static void RecorridoPostorden(NodoT Raiz) { 7 Programación III, Guía 7 8 if (Raiz != null) { RecorridoPostorden(Raiz.NodoIzquierdo); RecorridoPostorden(Raiz.NodoDerecho); Console.Write("{0}, ", Raiz.Informacion); } } //Metodo de Buscar un nodo static void BuscarNodo(NodoT Raiz, int Dato) { if (Dato < Raiz.Informacion) { //Buscar por el Sub-Arbol izquierdo if (Raiz.NodoIzquierdo == null) { Console.WriteLine("ERROR, No se encuentra el Nodo..."); Console.ReadLine(); } else { BuscarNodo(Raiz.NodoIzquierdo, Dato); } } else { if (Dato > Raiz.Informacion) { //Buscar por el Sub-Arbol derecho if (Raiz.NodoDerecho == null) { Console.WriteLine("ERROR, No se encuentra el Nodo..."); Console.ReadLine(); } else { BuscarNodo(Raiz.NodoDerecho, Dato); } } else { //El nodo se encontro Console.WriteLine("Nodo Localizado en el Arbol..."); Console.ReadLine(); } } } //Metodo de Eliminar static void EliminarNodo(ref NodoT Raiz, int Dato) { if (Raiz != null) { if (Dato < Raiz.Informacion) { EliminarNodo(ref Raiz.NodoIzquierdo, Dato); } else { if (Dato > Raiz.Informacion) { EliminarNodo(ref Raiz.NodoDerecho, Dato); } else { Programación III, Guía 7 //Si lo Encontro NodoT NodoEliminar = Raiz; if (NodoEliminar.NodoDerecho == null) { Raiz = NodoEliminar.NodoIzquierdo; } else { if (NodoEliminar.NodoIzquierdo == null) { Raiz = NodoEliminar.NodoDerecho; } else { NodoT AuxiliarNodo = null; NodoT Auxiliar = Raiz.NodoIzquierdo; bool Bandera = false; while (Auxiliar.NodoDerecho != null) { AuxiliarNodo = Auxiliar; Auxiliar = Auxiliar.NodoDerecho; Bandera = true; } Raiz.Informacion = Auxiliar.Informacion; NodoEliminar = Auxiliar; if (Bandera == true) { AuxiliarNodo.NodoDerecho = Auxiliar.NodoIzquierdo; } else { Raiz.NodoIzquierdo = Auxiliar.NodoIzquierdo; } } } } } } else { Console.WriteLine("ERROR, EL Nodo no se Encuentra en el Arbol..."); Console.ReadLine(); } } //Metodo de Finalizacion static void Finalizar() { Console.WriteLine("Fin del Programa, press any key to continue,..."); Console.ReadLine(); } } } 9 Programación III, Guía 7 10 Análisis de resultados • Crear un método al ejercicio anterior, que realice el recorrido en INORDEN Investigación complementaria. • Como determinar la altura del árbol. • Como determinar la profundidad de un nodo • Como determinar el número de nodos en cualquier momento. NOTA: Todo esto aplicarlo al ejercicio de la práctica. Bibliografía. • DEITEL, HARVEY M. / DEITEL, PAUL J. Cómo programar en C#. Editorial Pearson Prentice Hall, México 2004. http://www.ucema.edu.ar/~rst/Algoritmos_y_Estructura_de_Datos/Teoria/5._Arboles_binar ios.pdf Programación III, Guía 7 Hoja de cotejo: 7 1 Guía 7: Árboles Binarios. Alumno: Máquina No: Docente: GL: Fecha: EVALUACION % CONOCIMIENTO 40 APLICACIÓN DEL CONOCIMIENTO 40 ACTITUD 20 TOTAL 100% 1-4 5-7 8-10 Nota 11