using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Advanced.Algorithms.DataStructures
{
///
/// A tree implementation.
///
public class Tree : IEnumerable where T : IComparable
{
private TreeNode root { get; set; }
public int Count { get; private set; }
///
/// Time complexity: O(n)
///
public bool HasItem(T value)
{
if (root == null)
{
return false;
}
return find(root, value) != null;
}
///
/// Time complexity: O(n)
///
public int GetHeight()
{
return getHeight(root);
}
///
/// Time complexity: O(n)
///
public void Insert(T parent, T child)
{
if (root == null)
{
root = new TreeNode(null, child);
Count++;
return;
}
var parentNode = find(parent);
if (parentNode == null)
{
throw new ArgumentNullException();
}
var exists = find(root, child) != null;
if (exists)
{
throw new ArgumentException("value already exists");
}
parentNode.Children.InsertFirst(new TreeNode(parentNode, child));
Count++;
}
///
/// Time complexity: O(n)
///
public void Delete(T value)
{
delete(root.Value, value);
}
///
/// Time complexity: O(n)
///
public IEnumerable Children(T value)
{
return find(value)?.Children.Select(x => x.Value);
}
private TreeNode find(T value)
{
if (root == null)
{
return null;
}
return find(root, value);
}
private int getHeight(TreeNode node)
{
if (node == null)
{
return -1;
}
var currentHeight = -1;
foreach (var child in node.Children)
{
var childHeight = getHeight(child);
if (currentHeight < childHeight)
{
currentHeight = childHeight;
}
}
currentHeight++;
return currentHeight;
}
private void delete(T parentValue, T value)
{
var parent = find(parentValue);
if (parent == null)
{
throw new Exception("Cannot find parent");
}
var itemToRemove = find(parent, value);
if (itemToRemove == null)
{
throw new Exception("Cannot find item");
}
//if item is root
if (itemToRemove.Parent == null)
{
if (itemToRemove.Children.Count() == 0)
{
root = null;
}
else
{
if (itemToRemove.Children.Count() == 1)
{
root = itemToRemove.Children.DeleteFirst();
root.Parent = null;
}
else
{
throw new Exception("Node have multiple children. Cannot delete node unambiguosly");
}
}
}
else
{
if (itemToRemove.Children.Count() == 0)
{
itemToRemove.Parent.Children.Delete(itemToRemove);
}
else
{
if (itemToRemove.Children.Count() == 1)
{
var orphan = itemToRemove.Children.DeleteFirst();
orphan.Parent = itemToRemove.Parent;
itemToRemove.Parent.Children.InsertFirst(orphan);
itemToRemove.Parent.Children.Delete(itemToRemove);
}
else
{
throw new Exception("Node have multiple children. Cannot delete node unambiguosly");
}
}
}
Count--;
}
private TreeNode find(TreeNode parent, T value)
{
if (parent.Value.CompareTo(value) == 0)
{
return parent;
}
foreach (var child in parent.Children)
{
var result = find(child, value);
if (result != null)
{
return result;
}
}
return null;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public IEnumerator GetEnumerator()
{
return new TreeEnumerator(root);
}
}
internal class TreeNode : IComparable where T : IComparable
{
internal T Value { get; set; }
internal TreeNode Parent { get; set; }
internal SinglyLinkedList> Children { get; set; }
internal bool IsLeaf => Children.Count() == 0;
internal TreeNode(TreeNode parent, T value)
{
Parent = parent;
Value = value;
Children = new SinglyLinkedList>();
}
public int CompareTo(object obj)
{
return Value.CompareTo(obj as TreeNode);
}
}
internal class TreeEnumerator : IEnumerator where T : IComparable
{
private readonly TreeNode root;
private Stack> progress;
internal TreeEnumerator(TreeNode root)
{
this.root = root;
}
public bool MoveNext()
{
if (root == null)
{
return false;
}
if (progress == null)
{
progress = new Stack>(root.Children);
Current = root.Value;
return true;
}
if (progress.Count > 0)
{
var next = progress.Pop();
Current = next.Value;
foreach (var child in next.Children)
{
progress.Push(child);
}
return true;
}
return false;
}
public void Reset()
{
progress = null;
Current = default(T);
}
public T Current { get; private set; }
object IEnumerator.Current => Current;
public void Dispose()
{
progress = null;
}
}
}