2009-04-09 3 views
4

유형 매개 변수 T를 취하고 트리에 존재하는 T 유형의 모든 항목을 반환하는 트리 검색 메소드를 작성해야합니다. 이 일을 할 수있는 방법이 있습니까? 나는이 시점에서 효율성보다 우아함을 선호합니다 ...트리 구조에서 T 유형의 모든 객체 찾기 C#

답변

2

뭔가 :

foreach(MyCustomNodeClass item in rootNode.AllDescendantNodes<MyCustomNodeClass>()) 
{ 
    ... 
} 
:

internal static IEnumerable<T> AllDescendantNodes<T>(this TreeNode input) 
    where T class; 
{ 
    T current = null; 
    foreach (TreeNode node in input.Nodes) 
     if((current = node as T) != null) 
     { 
      yield return current; 
      foreach (var subnode in node.AllDescendantNodes<T>()) 
       yield return subnode; 
     } 
} 

그런 다음 확장 방법으로 루트 노드에 대해이 부를 것이다을

+0

그게 나를 위해 작동합니다. 나는 아직 확장 방법에 대한 이해가 없으므로 그것이 효과적인지 여부에 대해서는 확신 할 수 없다. 그러나 그것은 우아한 해결책입니다. 내가보기에 주어진 입력의 자손 만 검사됩니다. AllDescendants를 수정하여 입력 노드 유형을 확인하고이를 산출해야했습니다. 고마워요 –

+0

사실, 나는 특별한 루트 노드를 만든 다음 그것을 전달해야했습니다. AllDescendants를 수정하는 것은 잘못되었습니다. 감사합니다. –

+0

확장 메소드는 컴파일 타임에 정상 정적 호출로 변환됩니다. 사용시 성능에 영향을 미치지 않습니다. 이 메서드는 재귀를 처리하므로 잠재적으로 트리의 루트 노드에서 작업 한 다음 비슷한 작업을 수행합니다. – Keith

1

당신의 나무가 일반이라고 가정합니다. 즉 Item<T>입니다.

int count = yourTree.Count(p => p == typeof(T)); 

그렇지 않으면, 각 노드를 구문 분석하고 "item == typeof(T)는"

2

글쎄, 내부적으로 방법을 통해 나무의 모든 요소를 ​​반복해야 할 것입니다 비교, 그래서 스킵은 위에 열거하고 사용하기 OfType LINQ 방법은 멀지 않은 :

var onlyTs = yourTree.OfType<SomeT>(); 
+0

정답을 주심 +1 : 그냥 포인트를 놓친 것을 깨달았습니다 –

1

는 당신이 필요로하는 기본적인 트리 탐색 기능입니다 (전순은, inorder를 또는 postorder -이 중요하지 않습니다) 및 필터 기능. 그럼 당신은 함께 두를 작성하고 당신이 필요로하는 것을 얻을 수 있습니다 :이 같은

IEnumerable<T> Traverse(Tree<T> tree) 
{ 
    yield return tree.Data; 

    foreach(Tree<T> subtree in tree.Subtrees) 
     foreach(T t in Traverse(subtree)) 
      yield return t; 
} 

IEnumerable<U> Filter<T, U>(IEnumerable<T> source)   
    where U : T 
{ 
    foreach(T t in source) 
     if(t is U) 
      yield return (U)t; 
} 
+0

내 생각은 비슷하지만 한 가지 변경을해야합니다. 두 번 변환을 수행하고 있습니다. - 't를 U로 설정하고 null을 확인하는 것이 더 빠릅니다. 수업보다 'if (t is U) (U) t'; – Keith

관련 문제