课程笔记 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);
}
先是先序遍历。采用递归的思路来解决先序遍历问题无疑是很容易想到,只要规定访问的次序,让系统先访问该节点,再访问左子树,最后再访问右子树,之后循环递归即可。但是,递归的缺点是显而易见的,那就是由于每一次的递归需要开辟全新的存储空间来进行操作,因此总的时间成本和空间成本在常系数意义上都远大于迭代算法。我们需要另辟蹊径来重新设计迭代的思路。
仔细考察先序遍历的路径,不难发现对于每棵子树而言,都是率先顺序读入最左端的子链并进行写入操作,而右子树的操作又是逆序进行的。这就提示我们,可以采用栈结构来进行先序遍历操作。具体地说,就是在读入每一个节点都将该节点和右孩子节点入栈,并转入左孩子节点作继续的访问,直至没有左孩子时才开始对栈顶的元素开始施行操作。
#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);
}
相关文章推荐
- 【数据结构】1、串的模式匹配算法
- 算法和数据结构
- 数据结构:图 (总结)
- java数据结构------二叉树
- 数据结构和算法(Java版本)
- 数据结构——HDU1312:Red and Black(DFS)
- 课程笔记 13:数据结构(清华) 二叉树
- Python学习日志之Python数据结构初识
- Python学习日志之Python数据结构初识
- Python学习日志之Python数据结构初识
- Java数据结构-串及其应用-KMP模式匹配算法
- 数据结构-外部排序
- 数据结构-内部排序
- 讨伐 数据结构!!!
- 递归:解决汉诺塔问题(数据结构3.2 P103)
- 递归:解决汉诺塔问题(数据结构3.2 P103)
- 递归:解决汉诺塔问题(数据结构3.2 P103)
- 递归:解决汉诺塔问题(数据结构3.2 P103)
- 递归:解决汉诺塔问题(数据结构3.2 P103)
- 递归:解决汉诺塔问题(数据结构3.2 P103)