对与二叉树的便遍历有递归遍历与非递归遍历,递归遍历理解起来较简单,容易理解,代码书写简单,但是效率比较低下,对于非递归算法,虽然效率较高但是代码相对对一,且不是那么好容易理解,下面就进行一一解释
数据结构
typedef struct Tree
{
int date;
struct Tree* lchild;
struct Tree * rchild;
}BiTree,*PBiTree;
(1)链表的先序递归遍历
void PreOrder(PBiTree root)
{
if (root != NULL)
{
cout << root->date;
PreOrder(root->lchild);
PreOrder(root->rchild);
}
}
(2)链表的非递归先序遍历
void PreOrderPush(PBiTree root)
{
stack<PBiTree> s;
if (root == NULL)
{
return;
}
while (root != NULL || !s.empty() )
{
if (root)
{
cout << root->date;
s.push(root);
root = root->lchild;
}
else
{
PBiTree p = s.top();
s.pop();
root = p->rchild;
}
}
}
(3)链表的中序递归遍历
void InOrder(PBiTree root)
{
if (root != NULL)
{
InOrder(root->lchild);
cout << root->date;
InOrder(root->rchild);
}
}
(5)链表的非递归中序遍历
void InOrderPush(PBiTree root)
{
stack<PBiTree> s;
if (root == NULL)
{
return;
}
while (root != NULL || !s.empty())
{
if (root)
{
s.push(root);
root = root->lchild;
}
else
{
PBiTree p = s.top();
cout << p->date;
s.pop();
root = p->rchild;
}
}
}
(6)链表的递归后序遍历
void PostOrder(PBiTree root)
{
if (root != NULL)
{
PostOrder(root->lchild);
PostOrder(root->rchild);
cout << root->date;
}
}
(7)链表的非递归后续遍历, 前两种非递归比较简单,在此只介绍后序非递归遍历的思路:
(1)首先只有当二叉树的节点不为空并且栈不为空时才能继续进行遍历
(2)然后沿着二叉树的左孩子一直进行压栈,直到左孩子为空
(3)这时候需要取得栈顶元素观察其右孩子是否为空 如果为空既可以输出弹出顶元素,并输出数据。
(4)否则就把其右孩当做子树根节点重复上述操作,但是刚才为了简单解释,没有说明当第三走时,只判断为空是不准的,如果不为空但是其右孩子已经遍历完了也应该输出数据这时就需要一个指针记录还节点的右孩子是否已经输出
void PostOrderPush(PBiTree root)
{
stack<PBiTree> s;
PBiTree p, q;
p = root;
q = NULL;//上一个节点
while (p != NULL || !s.empty())
{//先遍历左子树
while (p != NULL)
{
s.push(p);
p = p->lchild;
}
if (!s.empty())
{
p = s.top();
//如果没有右子树,或者右子树刚刚被访问过,则输出根节点
if (p->rchild == NULL ||
p->rchild == q)
{
cout << p->date;
q = p;
s.pop();
p = NULL;
}
else
{
p = p->rchild;
}
}
}
}
以上就是我的遍历书写是的代码,感觉对于二叉树的遍历也不是那么难,递归方法最好理解