您的位置:首页 > 其它

迭代器访问树

2008-03-26 21:47 267 查看
//节点是对某种类型数据的封装;通过这种封装,能够对这种数据建立树形模型

//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?我没仔细测。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: