2010-02-12 22 views
5

Estoy tomando un curso de algoritmo en la universidad, y para uno de mis proyectos quiero implementar un árbol rojo-negro en C# (la implementación en sí no es el proyecto, sin embargo, algo decidí elige ayudarme).C# problema de referencia

Mi árbol rojo-negro debe contener claves de cadena, y el objeto que he creado para cada nodo tiene este aspecto:

class sRbTreeNode 
{ 
    public sRbTreeNode Parent = null; 
    public sRbTreeNode Right = null; 
    public sRbTreeNode Left = null; 
    public String Color; 
    public String Key; 

    public sRbTreeNode() 
    { 
    } 

    public sRbTreeNode(String key) 
    { 
     Key = key; 
    } 
} 

ya he añadido algunos métodos generales para imprimir el árbol, la búsqueda de la raíz, min/tecla máx (por alfabeto), etc ...

Tengo problemas para insertar nodos (por lo tanto, construir el árbol). Quien esté familiarizado con los árboles rojo-negro sabe que al agregar un nodo a un lado, podría haber cambiado el equilibrio del árbol. Para solucionar esto, debe "rotar" alrededor de los nodos en el árbol para equilibrar el árbol.

Escribí un método RightRotate y LeftRotate en pseudocódigo, y luego cuando traté de implementarlo en C#, me encontré con un montón de problemas de referencia con el objeto sRbTreeNode que creé.

Este es el pseudo-código que escribí para el método LeftRotate:

LeftRotate(root, node) 
    y <- node.Right; 
    node.Right <- y.Left; 
    if (y.Left != null) 
     y.Left.Parent <- node; 
    y.Parent <- node.Parent; 
    if (node.Parent = null) 
     root <- y; 
    else 
     if (node = node.Parent.Left) 
      node.Parent.Left = y; 
     else 
      node.Parent.Right = y; 
    y.Left <- node; 
    node.Parent <- y 

he recibido una sugerencia para ponerlo en práctica en línea recta, pero sin utilizar la palabra clave 'ref', que he intentado en un principio. Esto es cómo lo hice:

public static void LeftRotate(sRbTreeNode root, sRbTreeNode node) 
    { 
     sRbTreeNode y = node.Right; 
     node.Right = y.Left; 
     if (y.Left != null) 
      y.Left.Parent = node; 
     y.Parent = node.Parent; 
     if (node.Parent == null) 
      root = y; 
     else 
      if (node == node.Parent.Left) 
       node.Parent.Left = y; 
      else 
       node.Parent.Right = y; 
     y.Left = node; 
     node.Parent = y; 
    } 

Ahora, cuando puedo depurar, veo que funciona bien, pero los objetos que pase a este método sólo se rotan dentro del alcance del método. Cuando deja este método, parece que no hubo ningún cambio en los nodos reales. Es por eso que pensé en usar las palabras clave 'ref' en primer lugar.

¿Qué estoy haciendo mal?

+0

Como dice Andras, muéstrenos el código hasta el momento y lo probaremos. –

Respuesta

2

Debido a que en el cuerpo de su método de hacer esto:

root = y; 

que necesita para pasar root con un modificador ref. node no necesita uno, porque node nunca se actualiza para apuntar a un ndoe diferente. .

+0

Acabo de probarlo, y finalmente funciona !! ¡No puedo creer que haya sido tan fácil, y no me di cuenta de eso! ... ¡Muchas gracias! – gillyb

1

No veo por qué debería haber tenido problemas con las referencias: los nodos izquierdo/derecho/principal se pueden copiar igual que en este pseudocódigo.

Debería poder expandirlo a C# sin demasiado alboroto, a menos que esté usando la palabra clave 'ref', en cuyo caso podría obtener resultados impredecibles.

Quizás si pudiera mostrar el código que ha escrito hasta ahora, y podemos ayudar a depurar eso.

+0

Bueno, estaba tratando de usar la palabra clave ref, y pensé que era la forma correcta de hacerlo ... Lo intentaré sin usar la referencia y veré cómo funciona, gracias. – gillyb

+0

Acabo de editar la pregunta con el código que probé hasta el momento, tal vez te ayude a ayudarme, ya que no funciona del todo, expliqué por qué en la pregunta editada arriba. – gillyb

+0

Bueno, ahí lo tienes - ¡AakashM lo ordenó para ti! –

1

Mis recomendaciones:

  • no incluyen punteros de padres. No son esenciales para los algoritmos de inserción o eliminación y harán que su código sea más complejo. Por ejemplo, LeftRotate se puede escribir con solo un parámetro y será aproximadamente la mitad de largo si no utiliza punteros primarios.
  • Utilice enum para la propiedad Color en lugar de string, e inicialícela en el constructor.
  • Lea this article si no lo ha hecho ya.
+0

Necesito los punteros principales para otra cosa que tenga que ver con la estructura. Esto hará que sea mucho más rápido viajar a lo largo del árbol. – gillyb

+1

Incluso si los necesita, podría ser más fácil implementar los algoritmos sin ellos primero y agregarlos más tarde. – finnw