НАЙТИ предыдущие узлы в дереве на С#

Я пытаюсь написать функцию Previous(), чтобы получить предыдущие узлы дерева. Утверждение: «У нас есть дерево, построенное с использованием класса Node, где экземпляр класса представляет узел в дереве. Для простоты узел имеет одно поле данных типа int. Ваша задача — написать метод расширения NodeExtensions.Previous() для поиска предыдущего элемента в дереве. Вы можете написать столько вспомогательных методов, сколько хотите, но не меняйте сигнатуру метода расширения NodeExtensions.Previous()."

Класс узла выглядит следующим образом:

public class Node
{
    private List<Node> _children;

    public Node(int data, params Node[] nodes)
    {
        Data = data;
        AddRange(nodes);
    }

    public Node Parent { get; set; }

    public IEnumerable<Node> Children
    {
        get
        {
            return _children != null
                ? _children
                : Enumerable.Empty<Node>();
        }
    }

    public int Data { get; private set; }

    public void Add(Node node)
    {
        Debug.Assert(node.Parent == null);

        if (_children == null)
        {
            _children = new List<Node>();
        }

        _children.Add(node);
        node.Parent = this;
    }

    public void AddRange(IEnumerable<Node> nodes)
    {
        foreach (var node in nodes)
        {
            Add(node);
        }
    }

    public override string ToString()
    {
        return Data.ToString();
    }
}

Мне нужно написать метод расширения следующим образом:

using System;
using System.Linq;

public static class NodeExtensions
{
    public static Node Previous(this Node node)
    {
        // TODO Implement extension method here
        
    }
  
}

У меня есть тестовый пример:

using System;
using System.Text;
using NUnit.Framework;

public class NodeExtensionsTests
{
    [Test]
    public void Test()
    {
        // Test tree:
        // 
        // 1
        // +-2
        //   +-3
        //   +-4
        // +-5
        //   +-6
        //   +-7
        //
        var lastNode = new Node(7);
        var tree = new Node(
            1,
            new Node(
                2,
                new Node(3),
                new Node(4)),
            new Node(
                5,
                new Node(6),
                lastNode));

        // Expected output:
        //
        // 7
        // 6
        // 5
        // 4
        // 3
        // 2
        // 1
        //
        var n = lastNode;
        while (n != null)
        {
            Console.WriteLine(n.Data);
            n = n.Previous();
        }

        // Test
        //
        n = lastNode;
        Assert.AreEqual(7, n.Data);
        n = n.Previous();
        Assert.AreEqual(6, n.Data);
        n = n.Previous();
        Assert.AreEqual(5, n.Data);
        n = n.Previous();
        Assert.AreEqual(4, n.Data);
        n = n.Previous();
        Assert.AreEqual(3, n.Data);
        n = n.Previous();
        Assert.AreEqual(2, n.Data);
        n = n.Previous();
        Assert.AreEqual(1, n.Data);
        n = n.Previous();
        Assert.IsNull(n);
    }
}

Что бы я ни пытался, это либо входит в бесконечный цикл, либо просто возвращает корневые узлы вместо «всех братьев и сестер». Может ли кто-нибудь помочь мне здесь?

Лучший способ — добавить свойство к родительскому узлу вашего класса, чтобы вы могли легко перемещаться вверх по дереву. Затем добавьте значение parent при добавлении нужной ветви в дерево.

jdweng 23.12.2020 11:48

Какова ваша реализация метода Previous?

Pavel Anikhouski 23.12.2020 12:25
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
502
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, это сработает для вас

public static class NodeExtensions
{
    public static Node Previous(this Node node)
    {
        if (node.Parent == null) { return null; }
        var brothers = (List<Node>) node.Parent.Children;
        var index = brothers.IndexOf(node);
        if (index == 0) 
        {
            return node.Parent;
        }
        else
        {
            var next = brothers[index - 1];
            while (next.Children.Any()) 
            {
                next = next.Children.Last();
            }
            return next;
        }
    }

}

Другие вопросы по теме