以前经常说:
系统栈爆了怎么办?
手写啊!!
然而并没有写过一次
这次数据结构课介绍了非递归的二叉树遍历算法,后序还没讲,先写了再说
先序遍历:
1.我的直观想法是先把右子树压进去,再把左子树压进去
2.然而书上给的做法有点不一样,是先压左子树压到底,弹出的时候把当前的右子树给压进去。事实上在先序遍历上来说这两种做法没什么区别,我的想法相当于在压左子树之前就直接先把右子树压进去了
中序遍历:
中序遍历的时候我的做法不是那么管用了,因为先序遍历根节点最先访问,而中序需要左子树弹回来才能访问根节点,所以必须得用类似上面做法2的一样的思路
后序遍历:
可以和先序遍历一样一次性把右左子树压进去,在访问根节点前判一下上一个访问的是不是根节点的左右儿子,也就是说是不是从访问完左右儿子之后弹回来的,或者根本没有左右儿子,满足两种情况之一才能将这个点弹出来并访问,同时更新pre为这个根节点
void preOrder1(BiTree root) {
stack <BiTree> s;
BiTree p = root;
while (p != NULL || !s.empty()) {
while (p != NULL) {
visit(p);
s.push(p); //prepare the traversal for the p's right child
p = p -> lchild;
}
if (!s.empty()) {
p = s.top(); //get the node
s.pop();
p = p -> rchild; // turn to right child
}
}
}
void preOrder2(BiTree root) {
stack <BiTree> s;
BiTree p = root;
while (!s.empty()) {
vist(p = s.top());
s.pop();
if (p -> rchild != NULL)
s.push(p -> rchild);
if (p -> lchild != NULL)
s.push(p -> lchild);
}
}
void inOrder(BiTree root) {
stack <BiTree> s;
BiTree p = root;
while (p != NULL || !s.empty()) {
while (p != NULL) {
s.push(p); //prepare the traversal for the p's right child
p = p -> lchild;
}
if (!s.empty()) {
visit(p = s.top());
s.pop();
push(s.rchild);
}
}
}
void postOrder(BiTree root) {
stack <BiTree> s;
BiTree p = root, pre = NULL;
s.push(root);
while (!s.empty()) {
p = s.top();
if ((p -> lchild == NULL && p -> rchild == NULL) || (pre != NULL && (pre == p -> lchild || pre == p -> rchild))) { // come from child node
visit(p);
s.pop();
pre = p;
}
else {
if (p -> rchild != NULL)
s.push(p -> rchild);
if (p -> lchild != NULL)
s.push(p -> lchild);
}
}
}