二叉树定义结构:
struct BtNode{
int data;
BtNode * lchild;
BtNode * rchild;
};
二叉树有三种遍历,前序遍历,中序遍历,后序遍历
前序遍历的顺序是对每一棵树(子树),先访问根节点,然后访问左子树,然后访问右子树
中序遍历的顺序是对每一棵树,先访问左子树,再访问根节点,再访问右子树;
后序遍历的顺序是对每一棵树,先访问左子树,再访问右子树,在访问根节点
按照这个思路,递归的写法非常直观,而非递归的写法都要借助于栈来完成
前序遍历:
递归写法
void preOrder1(BtNode * T)
{
if(T)
{
cout<<T->data<<" ";
preOrder1(T->lchild);
preOrder1(T->rchild);
}
}
非递归写法
void preOrder2(BtNode *T)
{
//根节点入栈
stack<BtNode*>st;
BtNode * p = T;
st.push(p);
while(!st.empty())
{
//先访问根节点
p = st.top();st.pop();
cout<<p->data<<" ";
//右节点先入栈,再入栈左节点,这样访问的时候会先弹出左节点
if(p->rchild!=NULL)
{
st.push(p->rchild); p = p->rchild;
}
if(p->lchild !=NULL)
{
st.push(p->lchild);p= p->lchild;
}
}
}
中序遍历:
递归写法
void inOrder1(BtNode * T)
{
if(T)
{
inOrder1(T->lchild);
cout<<T->data<<" ";
inOrder1(T->rchild);
}
}
非递归写法
void inOrder2(BtNode *T)
{
stack<BtNide*>st;
BtNode * p = T;
while(!st.empty() || p)
{
//每一次先找到最左边的那个节点
while(p)
{
st.push(p);
p = p -> lchild;
}
if(!st.empty())
{
p = st.top();
st.pop();
cout<<p->data<<" ";
//这里如果有右节点就访问,没有为空就直接访问父节点的那个根节点了
p = p -> rchild;
}
}
}
后续遍历:
递归写法
void postOrder1(BtNode * T)
{
if(T) {
postOrder1(T->lchild);
postOrder1(T->rchild);
cout<<T->data<<" ";
}
}
非递归写法
void postOrder2(BtNode *T)
{
stack<BtNode *> st;
//plastVisit记录上次访问哪个节点,因为只有右节点也被访问过后才访问当前节点
BtNode * pcur,plastVisit;
pcur = T; plastVisit = NULL;
//还是先从最左边的节点开始
while(pcur)
{
st.push(pcur);
pcur = pcur->lchild;
}
while(!st.empty())
{
pcur = st.top();st.pop();
//当前在最左边,没有右节点或者右节点已经被访问过,就访问当前节点(子树的根节点)
if(pcur->rchild == NULL || pcur->rchild == plastVisit)
{
cout<<pcur->data<<" ";
plastVisit = pcur;
}
//右节点没有访问过 ,那当前根节点进栈,右节点进栈,然后进一步找右边子树最左边的节点
else{
st.push(pcur);
pcur = pcur -> rchild;
while(pcur)
{
st.push(pcur);
pcur = pcur->lchild;
}
}
}
}