一种方法是创建一个静态
Parse
方法
Node
节点
基于输入字符串。逻辑应该是:
去掉外圆括号
移除并为新节点指定名称
确定表示左节点的字符串(这可以通过对左括号和右括号计数来完成,直到每个括号的计数相等为止)。
将左节点指定给
Node.Parse
使用“左”字符串
将右节点指定给的结果
节点。解析
使用“右”字符串
我还添加了一些代码以一种基本的方式打印出树,这样您就可以看到每个节点的值是什么样子的。
例如
节点
解析
方法,该方法将根据字符串输入创建节点:
public class Node
{
public string Name { get; set; }
public Node Left { get; set; }
public Node Right { get; set; }
///
/// Creates a Node based on a valid input string: "(Name(Left)(Right))",
/// where 'Left' and 'Right' are empty or valid strings like above.
///
/// Input string to parse
/// Root node of the tree
public static Node Parse(string input)
{
input = input?.Trim();
// Some light validation
if (string.IsNullOrEmpty(input) || input == "()") return null;
if (input.Length < 7)
{
throw new ArgumentException(
$"input '{input}' is not long enough to represent a valid " +
"node. The minimum string length is 7 characters: (A()())");
}
if (!input.StartsWith("(") || !input.EndsWith(")"))
{
throw new FormatException(
$"input '{input}' must be surrounded by parenthesis");
}
// Remove outer parenthesis so input is now: "Name(Left)(Right)"
input = input.Substring(1, input.Length - 2);
// Find the name and start of left node
var leftNodeStart = input.IndexOf('(', 1);
var root = new Node {Name = input.Substring(0, leftNodeStart)};
// Remove name so input is now just: "(Left)(Right)"
input = input.Substring(leftNodeStart);
// Find the end of the left node by counting opening and closing parenthesis
// When the opening count is equal to the closing count, we have our Left set
var openParenthesisCount = 0;
var closeParenthesisCount = 0;
var leftNodeLength = 0;
for (int i = 0; i < input.Length - 1; i++)
{
if (input[i] == '(') openParenthesisCount++;
else if (input[i] == ')') closeParenthesisCount++;
if (openParenthesisCount == closeParenthesisCount)
{
leftNodeLength = i + 1;
break;
}
}
// Recursive calls to create Left and Right children
root.Left = Node.Parse(input.Substring(0, leftNodeLength));
root.Right = Node.Parse(input.Substring(leftNodeLength));
return root;
}
public void Print()
{
PrintTree();
}
private static class Connector
{
public const string Empty = " ";
public const string Single = "ââ";
public const string Double = "â â";
public const string Extension = "â";
}
private static class Position
{
public const string Empty = "";
public const string Left = "Left : ";
public const string Right = "Right: ";
}
private void PrintTree(string indent = "", string position = Position.Empty,
bool extendParentConnector = false, string connector = Connector.Empty)
{
// Extend the parent's connector if necessary by
// adding a "â" under the parent node's connector
if (extendParentConnector && indent.Length > position.Length + 2)
{
var replaceIndex = indent.Length - position.Length - 2;
indent = indent.Remove(replaceIndex, 1)
.Insert(replaceIndex, Connector.Extension);
}
Console.ForegroundColor = ConsoleColor.DarkMagenta;
Console.Write(indent + connector);
Console.ForegroundColor = position == Position.Left
? ConsoleColor.DarkCyan
: ConsoleColor.DarkYellow;
Console.Write(position);
Console.BackgroundColor = ConsoleColor.DarkGray;
Console.ForegroundColor = ConsoleColor.DarkBlue;
Console.WriteLine($" {Name} ");
Console.ResetColor();
var nextIndent = indent + new string(' ', position.Length + 2);
var extendParent = connector == Connector.Double;
Left?.PrintTree(nextIndent, Position.Left, extendParent,
Right == null ? Connector.Single : Connector.Double);
Right?.PrintTree(nextIndent, Position.Right, extendParent, Connector.Single);
}
}
在使用中,它看起来像:
static void Main(string[] args)
{
var nodeString = "(A(B(C(L()())(M()()))(D()()))(E(F(G(H()())())(I()(J()())))(K()())))";
var rootNode = Node.Parse(nodeString);
rootNode.Print();
Console.Write("\nDone! Press any key to exit...");
Console.ReadKey();
}
输出结果如下: