rj-action-library/Runtime/Graphs/Trees/TreeWalker.cs

322 lines
5.4 KiB
C#

using System.Collections;
using System.Collections.Generic;
namespace Rokojori
{
public abstract class TreeWalker<N> where N:class
{
public abstract N Parent( N node );
public abstract N ChildAt( N node, int index );
public abstract int NumChildren( N node );
public bool HasChildren( N node )
{
return NumChildren( node ) > 0;
}
public bool HasParent( N node )
{
return Parent( node ) != null;
}
public int ChildIndexOf( N node )
{
var p = Parent( node );
if ( p == null )
{
return -1;
}
var numKids = NumChildren( p );
for ( var i = 0; i<numKids; i++ )
{
if ( ChildAt( p, i ) == node )
{
return i;
}
}
return -1;
}
public N SiblingAt( N node, int index )
{
var p = Parent( node );
if ( p == null || index<0 || index >= NumChildren( p ) )
{ return null; }
return ChildAt( p, index );
}
public N NextSibling( N node )
{
var index = ChildIndexOf( node );
return SiblingAt( node, index+1 );
}
public N PreviousSibling( N node )
{
var index = ChildIndexOf( node );
return SiblingAt( node, index-1 );
}
public bool HasSiblingAt( N node, int index )
{
var p = Parent( node );
if ( p == null || index<0 || index >= NumChildren( p ) )
{ return false; }
return true;
}
public N FirstChild( N node )
{
return NumChildren( node )<=0?null:ChildAt( node, 0 );
}
public N LastChild( N node )
{
var num = NumChildren( node );
return num <= 0 ? null : ChildAt( node, num - 1 );
}
public N NextNode( N node )
{
if ( HasChildren( node ) )
{
return FirstChild( node );
}
var next = NextSibling( node );
if ( next != null )
{
return next;
}
var parent = Parent( node );
while ( parent != null )
{
var n = NextSibling( parent );
if ( n != null )
{
return n;
}
parent = Parent( parent );
}
return null;
}
public N PreviousNode( N node )
{
var prev = PreviousSibling( node );
if ( prev != null )
{
while ( HasChildren( prev ) )
{
prev = LastChild( prev );
}
return prev;
}
return Parent( node );
}
public N RootParent( N node )
{
node = Parent( node );
if ( node == null )
{
return null;
}
while ( HasParent( node ) )
{
node = Parent( node );
}
return node;
}
public N LastGrandChild( N node )
{
if ( HasChildren( node ) )
{
node = LastChild( node );
while ( HasChildren( node ) )
{
node = LastChild( node );
}
return node;
}
return null;
}
public bool IsChildOf( N child, N parent )
{
var p = Parent( child );
while ( p != null )
{
if ( p == parent )
{
return true;
}
p = Parent( p );
}
return false;
}
public int NumParents( N node )
{
var num = 0;
var p = Parent( node );
while ( p != null )
{
num++;
p = Parent( p );
}
return num;
}
public N LastOuterNode( N node )
{
var its = 0;
var max = 10000;
while ( HasChildren( node ) )
{
its++;
if ( its > max )
{
throw new System.Exception();
}
node = LastChild( node );
}
return node;
}
public N NextNonChild( N node )
{
return NextNode( LastOuterNode( node ) );
}
public N IterationEndOf( N node )
{
return NextNonChild( node );
}
public void Iterate( N node, System.Action<N> callback, bool childrenOnly = false )
{
var end = IterationEndOf( node );
var it = node;
if ( childrenOnly )
{
it = NextNode( it );
}
while ( it != end )
{
callback( it );
it = NextNode( it );
}
}
public N Find( N node, System.Predicate<N> predicate, bool childrenOnly )
{
var end = IterationEndOf( node );
var it = node;
if ( childrenOnly )
{
it = NextNode( it );
}
while ( it != end )
{
if ( predicate( it ) )
{
return it;
}
it = NextNode( it );
}
return null;
}
public void Filter( List<N> list, N node, System.Predicate<N> predicate, bool childrenOnly )
{
System.Action<N> addToList = ( N n ) =>
{
if ( predicate( n ) )
{
list.Add( n );
}
};
Iterate( node, addToList, childrenOnly );
}
public void FilterAndMap<U>( List<U> list, N node, System.Predicate<N> predicate, System.Func<N,U> mapper, bool childrenOnly )
{
System.Action<N> addToList = ( N n ) =>
{
if ( predicate( n ) )
{
list.Add( mapper( n ) );
}
};
Iterate( node, addToList, childrenOnly );
}
public void Map<U>( List<U> list, N node, System.Predicate<N> predicate, System.Func<N,U> mapper, bool childrenOnly )
{
System.Action<N> addToList = ( N n ) =>
{
list.Add( mapper( n ) );
};
Iterate( node, addToList, childrenOnly );
}
}
}