Programación III, Guía 8 1 Facultad : Ingeniería Escuela : Computación Asignatura: Programación III Tema: “ARBOLES ROJO NEGRO”. Objetivo Implementar la estructura de árboles B y árboles Rojo Negro, utilizando C#. Introducción Un árbol rojo negro es un tipo abstracto de datos, concretamente es un árbol binario de búsqueda equilibrado, una estructura de datos utilizada en informática y ciencias de la computación. Puede buscar, insertar y borrar en un tiempo O(log n), donde n es el número de elementos del árbol. En los árboles rojo-negro las hojas no son relevantes y no contienen datos. A la hora de implementarlo en un lenguaje de programación, para ahorrar memoria, un único nodo (nodo-centinela) hace de nodo hoja para todas las ramas. Así, todas las referencias de los nodos internos a las hojas van a parar al nodo centinela. En los árboles rojo-negros, como en todos los árboles binarios de búsqueda, es posible moverse ordenadamente a través de los elementos de forma eficiente si hay forma de localizar el padre de cualquier nodo. El tiempo de desplazarse desde la raíz hasta una hoja a través de un árbol equilibrado que tiene la mínima altura posible es de O(log n). Propiedades: Un árbol rojo-negro es un árbol binario de búsqueda en el que cada nodo tiene un atributo de color cuyo valor es o bien rojo o bien negro. Además de los requisitos impuestos a los árboles binarios de búsqueda convencionales, se deben satisfacer los siguientes para tener un árbol rojo-negro válido: 1. Todo nodo es o bien rojo o bien negro. 2. La raíz es negra. 3. Todas las hojas son negras (las hojas son los hijos nulos). 4. Los hijos de todo nodo rojo son negros (también llamada "Propiedad del rojo"). Programación III, Guía 8 2 5. Cada camino simple desde un nodo a una hoja descendiente contiene el mismo número de nodos negros, ya sea contando siempre los nodos negros nulos, o bien no contándolos nunca (el resultado es equivalente). También es llamada "Propiedad del camino", y al número de nodos negros de cada camino, que es constante para todos los caminos, se le denomina "Altura negra del árbol", y por tanto el camino no puede tener dos rojos seguidos. 6. El camino más largo desde la raíz hasta una hoja no es más largo que 2 veces el camino más corto desde la raíz del árbol a una hoja en dicho árbol. El resultado es que dicho árbol está aproximadamente equilibrado. Materiales y equipo Guía de Laboratorio Nº 8. Computadora con programa: o Visual Studio 2005. C# Dispositivo de Almacenamiento (USB). Procedimiento 1. Cree un proyecto modo consola en Visual C# .NET y nómbrelo como BinarySearchTree.cs using System; using System.Collections.Generic; using System.Text; namespace BinaryTree { public class Node { public String data; public Object key; Programación III, Guía 8 public Node left, right; public Node(Object key, String data) { this.data = data; this.key = key; left = null; right = null; } } public class BinarySearchTree { private Node root; private int count = 0; public BinarySearchTree() { root = null; count = 0; } public int Count { get { return this.count; } set { this.count = value; } } public Node Root { get { return this.root; } } private void CreateNode(Node node, ref Node tree) { if (tree == null) tree = node; else { int result = String.Compare(node.key.ToString(), tree.key.ToString()); if (result == 0) throw new Exception("Duplicate key..."); else if (result < 0) CreateNode(node, ref tree.left); else CreateNode(node, ref tree.right); 3 Programación III, Guía 8 4 } } public Node Insert(Object key, String data) { Node node = new Node(key, data); try { if (root == null) root = node; else CreateNode(node, ref root); this.Count++; return node; } catch { return null; } } public Node Search(Node node, Object key) { if (node == null) return null; else { int result = String.Compare(key.ToString(), node.key.ToString()); if (result < 0) return Search(node.left, key); else if (result > 0) return Search(node.right, key); else return node; } } } } 2. Ahora cree otro archivo con el nombre Program.cs using using using using System; System.Collections.Generic; System.Collections.Specialized; System.Text; namespace Trees { public enum Color { Red = 0, Black = 1 } Programación III, Guía 8 public enum Direction { Left, Right } public class Node { public IComparable data; public Node left; public Node right; public Color color = Color.Black; public Node(IComparable data) : this(data, null, null) { } public Node(IComparable data, Node left, Node right) { this.data = data; this.left = left; this.right = right; } } public class Tree { protected Node root; protected Node freshNode; protected Node currentNode; protected Tree() { freshNode = new Node(null); freshNode.left = freshNode.right = freshNode; root = new Node(null); root.left = freshNode; root.right = freshNode; } protected int Compare(IComparable item, Node node) { if (node != root) return item.CompareTo(node.data); else return 1; } public IComparable Search(IComparable data) { freshNode.data = data; currentNode = root.right; while (true) { 5 Programación III, Guía 8 6 if (Compare(data, currentNode) < 0) currentNode = currentNode.left; else if (Compare(data, currentNode) > 0) currentNode = currentNode.right; else if (currentNode != freshNode) return currentNode.data; else return null; } } protected void Display() { this.Display(root.right); } protected void Display(Node temp) { if (temp != freshNode) { Display(temp.left); Console.WriteLine(temp.data); Display(temp.right); } } } public sealed class RedBlackTree : Tree { private Color Black = Color.Black; private Color Red = Color.Red; private Node parentNode; private Node grandParentNode; private Node tempNode; public RedBlackTree() { } public void Insert(IComparable item) { currentNode = parentNode = grandParentNode = root; freshNode.data = item; int returnedValue = 0; while (Compare(item, currentNode) != 0) { tempNode = grandParentNode; grandParentNode = parentNode; parentNode = currentNode; returnedValue = Compare(item, currentNode); if (returnedValue < 0) Programación III, Guía 8 currentNode = currentNode.left; else currentNode = currentNode.right; if (currentNode.left.color == Color.Red && currentNode.right.color == Color.Red) ReArrange(item); } if (currentNode == freshNode) { currentNode = new Node(item, freshNode, freshNode); if (Compare(item, parentNode) < 0) parentNode.left = currentNode; else parentNode.right = currentNode; ReArrange(item); } } private void ReArrange(IComparable item) { currentNode.color = Red; currentNode.left.color = Color.Black; currentNode.right.color = Color.Black; if (parentNode.color == Color.Red) { grandParentNode.color = Color.Red; bool compareWithGrandParentNode = (Compare(item, grandParentNode) < 0); bool compareWithParentNode = (Compare(item, parentNode) < 0); if (compareWithGrandParentNode != compareWithParentNode) parentNode = Rotate(item, grandParentNode); currentNode = Rotate(item, tempNode); currentNode.color = Black; } root.right.color = Color.Black; } private Node Rotate(IComparable item, Node parentNode) { int value; if (Compare(item, parentNode) < 0) { value = Compare(item, parentNode.left); if (value < 0) parentNode.left = this.Rotate(parentNode.left, 7 Programación III, Guía 8 8 Direction.Left); else parentNode.left = this.Rotate(parentNode.left, Direction.Right); return parentNode.left; } else { value = Compare(item, parentNode.right); if (value < 0) parentNode.right = this.Rotate(parentNode.right, Direction.Left); else parentNode.right = this.Rotate(parentNode.right, Direction.Right); return parentNode.right; } } private Node Rotate(Node node, Direction direction) { Node tempNode; if (direction == Direction.Left) { tempNode = node.left; node.left = tempNode.right; tempNode.right = node; return tempNode; } else { tempNode = node.right; node.right = tempNode.left; tempNode.left = node; return tempNode; } } private int RandomNumber(int min, int max) { Random random = new Random(); return random.Next(min, max); } public static void Main(String[] args) { RedBlackTree redBlackTree = new RedBlackTree(); BinaryTree.BinarySearchTree binarySearchTree = new BinaryTree.BinarySearchTree(); Console.WriteLine("ARBOL ROJO-NEGRO"); Console.WriteLine("ingreso de datos en arbol Rojo Negro"); for (int i = 0; i < 9000000; i++) { Programación III, Guía 8 redBlackTree.Insert(i); } Console.WriteLine("ingreso de datos en arbol de busqueda"); for (int p = 0; p < 9000000; p++) { binarySearchTree.Insert(p, p.ToString()); } DateTime startTime = DateTime.Now; Console.WriteLine("Buscando dato 4596126 dentro del arbol rojo negro"); redBlackTree.Search(4596126); DateTime endTime = DateTime.Now; TimeSpan timeElasped = (TimeSpan)(endTime - startTime); Console.WriteLine("Arbol Rojo Negro tiempo de busqueda: " + timeElasped.Milliseconds.ToString() + " milisegundos."); startTime = DateTime.Now; Console.WriteLine("Buscando dato 4596126 dentro arbol de busqueda"); binarySearchTree.Search(binarySearchTree.Root, "4596126"); endTime = DateTime.Now; timeElasped = (TimeSpan)(endTime - startTime); Console.WriteLine("Arbol binario tiempo de busqueda: " + timeElasped.Milliseconds.ToString() + "milisegundos."); Console.Read(); } } } Análisis de resultados Analice el código proporcionado en Program.cs y explique su funcionamiento. _______________________________________________________________ _______________________________________________________________ _______________________________________________________________ Hacer un menú que permita insertar n valores (automático o manual) y que además me permita realizar búsquedas mediante el árbol rojo negro o mediante el árbol de búsqueda y que imprima el tiempo de ejecución. 9 Programación III, Guía 8 10 Investigación complementaria. Investigue el funcionamiento de los arboles B (B- Trees). Qué diferencias y similitudes tienen con los otros árboles desarrollados Bibliografía. DEITEL, HARVEY M. / DEITEL, PAUL J. Cómo programar en C#. Editorial Pearson Prentice Hall, México 2004 JOYANES AGUILAR, LUIS. Programación en C# - Algoritmos, estructuras de datos y objetos. Editorial McGraw Hill, España 2006. Programación III, Guía 8 Hoja de cotejo: Docente: Guía 8: Arboles Rojo Negro. 6 1 Máquina No: Tema: Presentación del programa GL: Alumno: Máquina No: Alumno: Docente: a Máquina No: GL: Docente: GL: Fecha: EVALUACION % CONOCIMIENTO 40 APLICACIÓN DEL CONOCIMIENTO 40 ACTITUD 20 TOTAL 100% 1-4 5-7 8-10 Nota 11