Binary tree parser is a simple project developed for purpose of deserializing binary tree from a text file or a string. Developing this project, next goals were claimed:
- Read binary tree from a file using API:
public static Tree BuildTree (StreamReader reader);
- Required support for format (# - stays for null):
root, left, right
left, subnode, #
right, #, subnode
- Parsing file, algorythm should use as minimum iterations as possible
- If algorythm cannot parse a file for any reason it should be able to describe the reason
Tree class is a main file used across the project and represents a binary tree with links to Left, Right and Parent nodes. And of-course there is a data property represented by a .NET String
class.
Tree creation is hidden by the factory method located in the same class, called Create
and accepting a string data. Calling a factory method will return you a tree creation result. Result can contain successfully created tree if indicator IsSuccess
returns true or an error message if indicator IsFailure
was set. Let's see this in example:
var createTreeResult = Tree.Create("data");
if (createTreeResult.IsFailure)
{
Console.WriteLine("Creating a tree an error occured: {0}.", createTreeResult.FailureMessage);
}
Console.WriteLine("A tree was successfully created with data: {0}.", createTreeResult.Result.Data)
Tree class itself has two methods for children maintenance. A method OverrideNode
allows to override any of already existing nodes by using reference to another tree and AddNode
allows to create a new node from String data and add it to the current tree. Let's see an example:
public void MyLogic(Tree root, Tree randomNode)
{
// Override existing node in tree. May produce an error if randomNode already has a parent.
var overrideNodeResult = root.OverrideNode(randomNode, BinaryChildrenEnum.Left);
// Add node and override it instead of right node. Could return an error if creation of new node were not passed.
var addNodeResult = root.AddNode("rightNode", BinaryChildrenEnum.Right);
// Indicate a full success by providing result to console.
if (overrideNodeResult.IsSuccess && addNodeResult.IsSuccess)
{
Console.WriteLine("Tree populated with nodes successfully.");
}
}
API has several methods dedicated to build a tree from string representation:
- The simpliest way to try things out is to copy the string above and pass it to
BuildTreeByStringInput
overload, like this:
var input =
@"root, left, right
left, subnode, #
right, #, subnode";
Tree result = Api.BuildTreeByStringInput(input);
- The same tree you can create by putting an input into a text file and calling a
BuildTreeByFilePath
overload like this:
var path = "C:\\data.txt";
Tree result = Api.BuildTreeByFilePath(path);
- Pro-mode is when you care about streams yourself, for files we have
BuildTree(StreamReader streamReader)
overload, use it like this:
var path = "C:\\data.txt";
using (StreamReader streamReader = new StreamReader(path))
{
var tree = Api.BuildTree(streamReader);
}
- Pro-mode is also when you know that
StreamReader
is inherited fromTextReader
as other classes likeStringReader
and for this purpose we haveBuildTree(TextReader textReader)
overload, don't hesitate to use it like this:
var input =
@"root, left, right
left, subnode, #
right, #, subnode";
using (TextReader streamReader = new StringReader(input))
{
var tree = Api.BuildTree(streamReader);
}
According to the tests, which you can find in Performance Tests File, an algorythm parsing tree has next results:
- Parsing from memory
200.000+
nodes takes~3 seconds
, acceptance criteria is6 seconds
- Parsing from file on the HDD
200.000+
nodes takes~11 seconds
, acceptance criteria is13 seconds
When you try to deserialize a tree of 400.000+ nodes program complains that it has no so much memory to use. An issue brought by parser and in most cases is thrown in "Create Tree From Parsed Values file".
๐ OMG, this is not a tree when there are cycles in graph, for more information, please reference Wikipedia Page.
The main reason why cyclic references are possible is that there are no check when adding a child node, so possible solutions can be:
- Creating a global validator, so to check the tree when it is created;
- Creating a tree manager which will have all data in one place and will be able to quickly resolve an error;
Yes, this project is not ideal ๐ , so you're welcome to contribute. Use these sections to bring your ideas to this project:
- Issues section of this repository where you can suggest your ideas;
- Pull Request where you can suggest your code.