//節點是對某種類型資料的封裝;通過這種封裝,能夠對這種資料建立樹形模型
//Node是Data的馬甲,穿上馬甲的Data能夠組織成一棵樹
public abstract class Node<T>
{
protected T _data;
public T Data
{
get
{
return _data;
}
set
{
_data = value;
}
}
}
//定義子節點集合。這樣定義節點有一個好處,如果獲得一個節點的引用,也就引用的以該節點為根的整棵樹
public class CldNode<T> : Node<T>
{
public CldNode(T data)
{
_data = data;
}
public CldNode()
{ }
private List<CldNode<T>> _children;
public List<CldNode<T>> Children
{
get
{
if (_children == null) //從單例模式改的,不知道有沒有問題?
{
lock (this)
{
if (_children == null)
{
_children = new List<CldNode<T>>();
}
}
}
return _children;
}
}
}
//後面使用堆棧類比遍曆樹,這個輔助類定義了堆棧中的元素。
//First表示堆棧中的節點,Second表示要遍曆這個節點的第幾個子
[Serializable]
public class Pair<FT, ST>
{
public Pair(FT first, ST second)
{
First = first;
Second = second;
}
public FT First
{
get;
set;
}
public ST Second
{
get;
set;
}
}
//不用遞迴是因為不知道用遞迴改怎麼寫成迭代器
public class CldNodeIterator<T>
{
private Stack<Pair<CldNode<T>, int>> _stack;
private CldNode<T> _root;
public CldNodeIterator(CldNode<T> root)
{
_root = root;
}
public CldNodeIterator() { }
public CldNode<T> Root
{
get
{
return _root;
}
set
{
_root = value;
}
}
//首先訪問父節點
//然後訪問所有的子結點
//上面這兩點是遞迴的
public IEnumerable<T> FPermiseTraverse()
{
if (_stack == null)
{
_stack = new Stack<Pair<CldNode<T>, int>>(16);
}
_stack.Push(new Pair<CldNode<T>, int>(_root, -1));
while (_stack.Count != 0)
{
Pair<CldNode<T>, int> stkTop = _stack.Peek();
if (stkTop.Second == -1) //尚未開始遍曆
{
yield return stkTop.First.Data;
stkTop.Second++;
continue;
}
if (stkTop.First.Children.Count == stkTop.Second) //已經結束
{
_stack.Pop();
if (_stack.Count != 0)
{
_stack.Peek().Second++;
}
continue;
}
_stack.Push(new Pair<CldNode<T>, int>(stkTop.First.Children[stkTop.Second], -1));
}
}
//先子後父
public IEnumerable<T> CPermiseTraverse()
{
if (_stack == null)
{
_stack = new Stack<Pair<CldNode<T>, int>>(16);
}
_stack.Push(new Pair<CldNode<T>, int>(_root, -1));
while (_stack.Count != 0)
{
Pair<CldNode<T>, int> stkTop = _stack.Peek();
if (stkTop.Second == -1) //尚未開始遍曆
{
stkTop.Second++;
continue;
}
if (stkTop.First.Children.Count == stkTop.Second) //已經結束
{
yield return stkTop.First.Data;
_stack.Pop();
if (_stack.Count != 0)
{
_stack.Peek().Second++;
}
continue;
}
_stack.Push(new Pair<CldNode<T>, int>(stkTop.First.Children[stkTop.Second], -1));
}
}
}
//不知道有沒有bug?我沒仔細測。