/// <inheritdoc /> public override ITreeNode <T> Difference(ITreeNode <T> other, DEquality <ITreeNode <T> > traversalEquality, DEquality <T> deletionEquality) { // if nodes arn't equal return nothing if (Equals(other)) { return(null); } // if these arn't traversal equal, return a copy of this node if (!traversalEquality(this, other)) { return(Copy()); } // if this has no children, test for deletion if (ChildCount == 0) { return(deletionEquality(Value, other.Value) ? null : new UniqueChildrenTreeNode <T>(this.Value)); } // if other has no children, retun this as copy if (other.ChildCount == 0) { return(Copy()); } // calculate difference of children nodes UniqueChildrenTreeNode <T> differenceTree = new UniqueChildrenTreeNode <T>(Value); List <ITreeNode <T> > originalNodesWithoutTraversalNeighbour = new List <ITreeNode <T> >(Children); foreach (ITreeNode <T> child in other.Children) { ITreeNode <T> traversalNode = originalNodesWithoutTraversalNeighbour.Find(n => traversalEquality(n, child)); // if node exists, perform a difference and add new node to output if (traversalNode != default(ITreeNode <T>)) { UniqueChildrenTreeNode <T> newDifference = traversalNode.Difference(child, traversalEquality, deletionEquality) as UniqueChildrenTreeNode <T>; originalNodesWithoutTraversalNeighbour.Remove(traversalNode); if (newDifference == null) { continue; } UnsafeAddChild(differenceTree, newDifference); } } // Add all nodes without a traversale neighbour to output foreach (ITreeNode <T> node in originalNodesWithoutTraversalNeighbour) { node.Copy(differenceTree); } return(differenceTree); }
/// <summary> /// Adds child and returns node if child with value does not already exist /// Otherwise returns null /// </summary> /// <param name="value">value of node</param> /// <returns>created child or null</returns> public override ITreeNode <T> AddChild(T value) { if (_children.QueryContains(n => { return(n.Value.Equals(value)); })) { return(null); } UniqueChildrenTreeNode <T> node = new UniqueChildrenTreeNode <T>(value); UnsafeAddChild(this, node); return(node); }
/// <inheritdoc /> public override ITreeNode <T> Intersection(ITreeNode <T> other, DEquality <ITreeNode <T> > equality) { // if not equal return null if (!equality(this, other)) { return(null); } // if netiehr have children return new tree node if (ChildCount == 0 || other.ChildCount == 0) { return(new UniqueChildrenTreeNode <T>(Value)); } // process node and children to find intersection UniqueChildrenTreeNode <T> intersectionRoot = new UniqueChildrenTreeNode <T>(Value); List <ITreeNode <T> > otherChildren = new List <ITreeNode <T> >(other.Children); foreach (ITreeNode <T> originalChild in Children) { ITreeNode <T> matchingOtherNode = otherChildren.Find(n => equality(n, originalChild)); // if a match exists, perform an intersection if (matchingOtherNode != default(ITreeNode <T>)) { UniqueChildrenTreeNode <T> newIntersection = originalChild.Intersection(matchingOtherNode) as UniqueChildrenTreeNode <T>; if (newIntersection == null) { continue; } UnsafeAddChild(intersectionRoot, newIntersection); otherChildren.Remove(matchingOtherNode); } } return(intersectionRoot); }
/// <inheritdoc /> public override ITreeNode <T> Union(ITreeNode <T> other, DEquality <ITreeNode <T> > equality, DMerge <T> merge) { // if not equal, return null if (!equality(this, other)) { return(null); } // since values are equal, if they both have no children, return node with value if (ChildCount == 0 && other.ChildCount == 0) { return(new UniqueChildrenTreeNode <T>(merge(Value, other.Value))); } // return copy of node with children if only 1 has children if (ChildCount > 0 && other.ChildCount == 0) { return(Copy()); } if (other.ChildCount > 0 && ChildCount == 0) { return(other.Copy()); } // set up the union tree for recursive calculation UniqueChildrenTreeNode <T> unionTree = new UniqueChildrenTreeNode <T>(merge(Value, other.Value)); // sort out children in both that have no equivalent in other // perform a union on any nodes that match List <ITreeNode <T> > otherNodesNotInOriginal = new List <ITreeNode <T> >(other.Children); List <ITreeNode <T> > originalNodesNotInOther = new List <ITreeNode <T> >(); foreach (ITreeNode <T> child in Children) { ITreeNode <T> matchingOtherNode = otherNodesNotInOriginal.Find(n => equality(n, child)); if (matchingOtherNode == default(ITreeNode <T>)) { originalNodesNotInOther.Add(child); } else { UniqueChildrenTreeNode <T> newUnion = child.Union(matchingOtherNode) as UniqueChildrenTreeNode <T>; if (newUnion == null) { continue; } // add union of matching nodes to tree UnsafeAddChild(unionTree, newUnion); otherNodesNotInOriginal.Remove(matchingOtherNode); } } // copy other nodes missing from original foreach (ITreeNode <T> node in otherNodesNotInOriginal) { node.Copy(unionTree); } // copy original nodes missing from other foreach (ITreeNode <T> node in originalNodesNotInOther) { node.Copy(unionTree); } return(unionTree); }
private void UnsafeAddChild(UniqueChildrenTreeNode <T> parent, UniqueChildrenTreeNode <T> child) { parent._children.Add(child); child._parent = parent; }