简单定义一个抽象的节点类,为了看上去更通用一点,写成了比较难看的泛型:
1
public
abstract
class TreeNode<TNode, TValue>
2 where TNode : TreeNode<TNode, TValue>, new()
3 {
4 public TValue Value { get; set; }
5
6 public TNode LeftChild { get; protected set; }
7
8 public TNode RightChild { get; protected set; }
9
10 public abstract TNode CreateLeftChild(TValue value);
11
12 public abstract TNode CreateRightChild(TValue value);
13 }
2 where TNode : TreeNode<TNode, TValue>, new()
3 {
4 public TValue Value { get; set; }
5
6 public TNode LeftChild { get; protected set; }
7
8 public TNode RightChild { get; protected set; }
9
10 public abstract TNode CreateLeftChild(TValue value);
11
12 public abstract TNode CreateRightChild(TValue value);
13 }
然后我们的二叉树单独写一个接口,里面放一个根节点,然后继承一下IEnumerable,表示我们是可以被迭代的:
1
public
interface IBinaryTree<
out TNode> : IEnumerable<TNode>
2 {
3 TNode Root { get; }
4 }
5
6 public class BinaryTree<TNode, TValue> : IBinaryTree<TNode>
7 where TNode : TreeNode<TNode, TValue>, new()
8 {
9 public TNode Root { get; protected set; }
10
11 public BinaryTree(TValue value)
12 {
13 Root = new TNode { Value = value };
14 }
15
16 #region IEnumerable
17
18 public IEnumerator<TNode> GetEnumerator()
19 {
20 return new InorderTraversalBinaryTreeEnumerator<TNode, TValue>(Root);
21 }
22
23 IEnumerator IEnumerable.GetEnumerator()
24 {
25 return GetEnumerator();
26 }
27
28 #endregion
29 }
2 {
3 TNode Root { get; }
4 }
5
6 public class BinaryTree<TNode, TValue> : IBinaryTree<TNode>
7 where TNode : TreeNode<TNode, TValue>, new()
8 {
9 public TNode Root { get; protected set; }
10
11 public BinaryTree(TValue value)
12 {
13 Root = new TNode { Value = value };
14 }
15
16 #region IEnumerable
17
18 public IEnumerator<TNode> GetEnumerator()
19 {
20 return new InorderTraversalBinaryTreeEnumerator<TNode, TValue>(Root);
21 }
22
23 IEnumerator IEnumerable.GetEnumerator()
24 {
25 return GetEnumerator();
26 }
27
28 #endregion
29 }
GetEnumerator方法里那个长长的我胡乱命名的东西,就是所谓的迭代器了。用一个栈来配合迭代当前访问的节点:
1
public
class InorderTraversalBinaryTreeEnumerator<TNode, TValue> : IEnumerator<TNode>
2 where TNode : TreeNode<TNode, TValue>, new()
3 {
4 private readonly Stack<TNode> _stack = new Stack<TNode>();
5 private TNode _current;
6
7 TNode IEnumerator<TNode>.Current
8 {
9 get { return _current; }
10 }
11
12 object IEnumerator.Current
13 {
14 get { return _current; }
15 }
16
17 public InorderTraversalBinaryTreeEnumerator(TNode root)
18 {
19 FindLeftBottomNode(root);
20 }
21
22 bool IEnumerator.MoveNext()
23 {
24 if (_stack.Count == 0)
25 return false;
26
27 _current = _stack.Pop();
28
29 FindLeftBottomNode(_current.RightChild);
30
31 return true;
32 }
33
34 private void FindLeftBottomNode(TNode node)
35 {
36 while (node != null)
37 {
38 _stack.Push(node);
39 node = node.LeftChild;
40 }
41 }
42
43 void IEnumerator.Reset()
44 {
45 }
46
47 void IDisposable.Dispose()
48 {
49 }
50 }
2 where TNode : TreeNode<TNode, TValue>, new()
3 {
4 private readonly Stack<TNode> _stack = new Stack<TNode>();
5 private TNode _current;
6
7 TNode IEnumerator<TNode>.Current
8 {
9 get { return _current; }
10 }
11
12 object IEnumerator.Current
13 {
14 get { return _current; }
15 }
16
17 public InorderTraversalBinaryTreeEnumerator(TNode root)
18 {
19 FindLeftBottomNode(root);
20 }
21
22 bool IEnumerator.MoveNext()
23 {
24 if (_stack.Count == 0)
25 return false;
26
27 _current = _stack.Pop();
28
29 FindLeftBottomNode(_current.RightChild);
30
31 return true;
32 }
33
34 private void FindLeftBottomNode(TNode node)
35 {
36 while (node != null)
37 {
38 _stack.Push(node);
39 node = node.LeftChild;
40 }
41 }
42
43 void IEnumerator.Reset()
44 {
45 }
46
47 void IDisposable.Dispose()
48 {
49 }
50 }
基础代码就这些,下面演示一个可以在控制器打印出来的二叉树。
为了打印方便,给节点扩展了Parent属性,外加一点简单的判断方法:
1
public
class PrintableTreeNode : TreeNode<PrintableTreeNode,
int>
2 {
3 public PrintableTreeNode Parent { get; private set; }
4
5 public PrintableTreeNode()
6 : this( null)
7 {
8 }
9
10 public PrintableTreeNode(PrintableTreeNode parent)
11 {
12 Parent = parent;
13 }
14
15 public override PrintableTreeNode CreateLeftChild( int value)
16 {
17 return LeftChild = new PrintableTreeNode { Value = value, Parent = this };
18 }
19
20 public override PrintableTreeNode CreateRightChild( int value)
21 {
22 return RightChild = new PrintableTreeNode { Value = value, Parent = this };
23 }
24
25 public bool IsLeftChild()
26 {
27 return Parent != null && ReferenceEquals( this, Parent.LeftChild);
28 }
29
30 public bool IsRightChild()
31 {
32 return Parent != null && ReferenceEquals( this, Parent.RightChild);
33 }
34 }
35
36 public interface IPrintableBinaryTree : IBinaryTree<PrintableTreeNode>
37 {
38 void Print();
39 }
2 {
3 public PrintableTreeNode Parent { get; private set; }
4
5 public PrintableTreeNode()
6 : this( null)
7 {
8 }
9
10 public PrintableTreeNode(PrintableTreeNode parent)
11 {
12 Parent = parent;
13 }
14
15 public override PrintableTreeNode CreateLeftChild( int value)
16 {
17 return LeftChild = new PrintableTreeNode { Value = value, Parent = this };
18 }
19
20 public override PrintableTreeNode CreateRightChild( int value)
21 {
22 return RightChild = new PrintableTreeNode { Value = value, Parent = this };
23 }
24
25 public bool IsLeftChild()
26 {
27 return Parent != null && ReferenceEquals( this, Parent.LeftChild);
28 }
29
30 public bool IsRightChild()
31 {
32 return Parent != null && ReferenceEquals( this, Parent.RightChild);
33 }
34 }
35
36 public interface IPrintableBinaryTree : IBinaryTree<PrintableTreeNode>
37 {
38 void Print();
39 }
Print的实现就不贴出来了。
随机生成一棵树,然后直接foreach就能中序遍历整棵树了: