您的位置:首页 > 理论基础 > 数据结构算法

课程笔记 14:数据结构(清华) 二叉树-遍历

2015-07-26 20:40 405 查看
如前所述,二叉树的遍历一般有四种,即层次、先序、中序、后序。鉴于后序遍历与先序遍历基本构思相同,故这里只就前三种遍历方式作讨论。

先是先序遍历。采用递归的思路来解决先序遍历问题无疑是很容易想到,只要规定访问的次序,让系统先访问该节点,再访问左子树,最后再访问右子树,之后循环递归即可。但是,递归的缺点是显而易见的,那就是由于每一次的递归需要开辟全新的存储空间来进行操作,因此总的时间成本和空间成本在常系数意义上都远大于迭代算法。我们需要另辟蹊径来重新设计迭代的思路。

仔细考察先序遍历的路径,不难发现对于每棵子树而言,都是率先顺序读入最左端的子链并进行写入操作,而右子树的操作又是逆序进行的。这就提示我们,可以采用栈结构来进行先序遍历操作。具体地说,就是在读入每一个节点都将该节点和右孩子节点入栈,并转入左孩子节点作继续的访问,直至没有左孩子时才开始对栈顶的元素开始施行操作。

#include "Stack.h"

template <typename T, typename VST>

void BinTree<T>::travPre(VST &visit)

{

BinNodePosi(T) x = this._root;

Stack<BinNodePosi(T)> S(x);

while (S.size())

{

S = goAlongLeftBrach(x, S, visit);

x = S.pop();

}

Stack<BinNodePosi(T)> goAlongLeftBranch(BinNodePosi(T) x, Stack<BinNodePosi(T)> S, VST &visit)

{

while (x.lChild)

{

visit(x.data);

if (x.rChild) S.push(x.rChild);

S.push(x.lChild);

}

return S;

}

其次是中序遍历。采用递归的思路来解决中序遍历问题无疑是很容易想到,只要规定访问的次序,让系统先访问左子树,再访问该节点,最后再访问右子树,之后循环递归即可。但是,递归的缺点是显而易见的,那就是由于每一次的递归需要开辟全新的存储空间来进行操作,因此总的时间成本和空间成本在常系数意义上都远大于迭代算法。我们需要另辟蹊径来重新设计迭代的思路。

仔细考察中序遍历的路径,不难发现对于每棵子树而言,都是率先顺序读入最左端的子链,但是再进行写入操作时,左端子链却又是逆序进行的。这就提示我们,可以采用栈结构来进行先序遍历操作。具体地说,就是在读入每一个节点都将该节点和右孩子节点入栈,并转入左孩子节点作继续的访问,直至没有左孩子时才开始对栈顶的元素开始施行操作。

#include "Stack.h"

template <typename T, typename VST>

void BinTree<T>::travIn(VST &visit)

{

Stack<BinNodePosi(T)> S;

BinNodePosi(T) x = this._root;

do {

S = goAlongLeftBrach(x, S);

x = S.pop();

visit(x.data);

} while (S.size());

}

Stack<BinNodePosi(T)> goAlongLeftBranch(BinNodePosi(T) x, Stack<BinNodePosi(T)> S)

{

while (x.lChild)

{

if (x.rChild) S.push(x.rChild);

S.push(x);

}

return S;

}

最后我们再来考察层次遍历。不难发现,层次遍历的执行次序是逐层展开的,只是一种类似于队列的操作过程,因此可以考虑使用队列来简化算法,其实现如下:

#include "queue.h"

template <typename T, typename VST>

void travLevel(VST &visit)

{

BinNodePosi(T) x = this._root;

queue<BinNodePosi(T)> R(x);

while (!R.empty())

{

R = goAlongLevel(x, R);

visit(x.data);

x = R.dequeue;

}

}

queue<BinNodePosi(T)> goAlongLevel(BinNodePosi(T) x, queue<BinNodePosi(T)> R)

{

if (HasLChild(x)) R.enqueue(x.lChild);

if (HasRChild(x)) R.enqueue(x.rChild);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: