Я беру курс алгоритма в университете, и для одного из моих проектов я хочу реализовать красно-черное дерево в C# (сама реализация не является проектом, еще просто что-то, что я решил принять решение выручить меня).
Мое красно-черное дерево должно содержать строковые ключи, и объект, который я создал для каждого узла, похож на это:
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;
}
}
Я уже добавил некоторые основные методы для печати дерева, нахождения корня, минута, ключевая / макс. ключевой (алфавитом), и т.д...
Я испытываю затруднения при вставке узлов (следовательно, создании дерева). Кто бы ни знаком с красно-черными деревьями, знает, что при добавлении узла к одной стороне, Вы, возможно, изменили баланс дерева. Для фиксации этого необходимо "вращаться" вокруг узлов на дереве для балансирования дерева.
Я записал метод RightRotate и LeftRotate в псевдокоде, и затем когда я пытался реализовать его в C#, я столкнулся с набором ссылочных проблем с объектом sRbTreeNode, который что я создал.
Это - псевдокод, который я записал для метода 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
Я получил предложение для реализации его прямой, но не используя 'касательно' ключевого слова, которое я попробовал сначала. Это - то, как я сделал это:
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;
}
Теперь, когда я отлаживаю, я вижу, что это хорошо работает, но объекты, которые я передаю этому методу, только повернуты в рамках метода. Когда это оставляет этот метод, кажется, что не было никакого изменения в фактических узлах. Именно поэтому я думал об использовании 'касательно' ключевых слов во-первых.
Что я делаю неправильно?
Потому что в теле вашего метода вы делаете следующее:
root = y;
вам нужно передать root
с модификатором ref
. node
он не нужен, потому что node
сам никогда не обновляется, чтобы указывать на другое ndoe.
.
Я не вижу причин, почему у вас должны были возникнуть проблемы со ссылками - узлы Left/Right/Parent могут быть скопированы, как в этом псевдокоде.
Вы должны быть в состоянии расширить его до C# без особых проблем - если только вы не используете ключевое слово 'ref', в этом случае вы вполне можете получить непредсказуемые результаты.
Возможно, если вы покажете код, который вы на самом деле написали, мы сможем помочь отладить его.
Мои рекомендации:
LeftRotate
может быть написан с одним параметром и будет примерно вдвое длиннее, если не использовать родительские указатели. enum
для свойства Color
, а не string
, и инициализируйте его в конструкторе.