Programación III, Guía8
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).
1
Programación III, Guía 8 2
4.
Los hijos de todo nodo rojo son negros (también llamada "Propiedad del rojo").
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 2012.
 C#
Dispositivo de Almacenamiento (USB).
Procedimiento
1.
Cree un proyecto modo consola en Visual C# y nómbrelo como BinarySearchTree.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace BinaryTree
{
public class Node
{
Programación III, Guía 8
public String data;
public Object key;
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("Clave duplicada...");
else if (result < 0)
CreateNode(node, ref tree.left);
else
CreateNode(node, ref tree.right);
}
}
public Node Insert(Object key, String data)
{
Node node = new Node(key, data);
try
{
3
Programación III, Guía 8 4
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 System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
namespace Trees
{
public enum Color
{
Red = 0, Black = 1
}
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)
Programación III, Guía 8
{
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)
{
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
{
5
Programación III, Guía 8 6
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)
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)
Programación III, Guía 8
{
int value;
if (Compare(item, parentNode) < 0)
{
value = Compare(item, parentNode.left);
if (value < 0)
parentNode.left = this.Rotate(parentNode.left,
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++)
7
Programación III, Guía 8 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.
Programación III, Guía 8
9
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 10
Hoja de cotejo:
8
Guía 8: Arboles Rojo Negro.
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