您的位置:首页 > 其它

二叉树——二叉树的遍历

2016-02-21 12:29 197 查看

二叉树遍历(Binary Tree Traversal)

  二叉树的遍历是指按照一定次序访问树中所有结点,并且每个结点仅被访问一次的过程。它是最基本的运算,是二叉树中所有其他运算的基础。

  重用的4种遍历方法如下:

1.前序遍历

  前序遍历的二叉树的过程如下:

  (1)访问根结点

  (2)前序遍历左子树

  (3)前序遍历右子树

  前序遍历二叉树的递归算法如下:

//前序遍历(递归)
void PreOrder(TreeNode *root) {
if(root) {
cout<<root->val<<" ";
PreOrder(root->left);
PreOrder(root->right);
}
}


  由前序遍历的过程可知,先访问根结点,再访问左子树,最后访问右子树。因此,先将根结点进栈,在栈不为空时循环:出栈p,访问*p结点,若它有右孩子,将其右孩子结点进栈,若它有左孩子,再将其左孩子进栈。对应的非递归算法如下:

//前序遍历(非递归)
void PreOrder2(TreeNode *root) {
stack<TreeNode *> st;
TreeNode *p =root;
while(p || !st.empty()) {
if(p) {
st.push(p);
cout<<p->val<<" ";
p=p->left;
}
else {
p = st.top();
st.pop();
p = p->right;
}
}
}


2.中序遍历

  中序遍历的二叉树的过程如下:

  (1)中序遍历左子树

  (2)访问根结点

  (3)中序遍历右子树

  中序遍历二叉树的递归算法如下:

//中序遍历(递归)
void InOrder(TreeNode *root) {
if(root) {
InOrder(root->left);
cout<<root->val<<" ";
InOrder(root->right);
}
}


  由中序遍历过程可知,采用一个栈保存需要返回的结点指针,先扫描(并非访问)根结点的所有左下结点并将它们一一进栈。然后出栈一个结点,显然该结点没有左孩子结点或者左孩子结点已被访问过(进一步说明该结点的左子树均已被访问过),则访问它。然后扫描该结点的右孩子结点,将其进栈,再扫描该右孩子结点的所有左结点并一一进栈,如此这样,直到栈为空为止。对应的非递归算法如下:

//中序遍历(非递归)
void InOrder2(TreeNode *root) {
stack<TreeNode *> st;
TreeNode *p = root;
while(p || !st.empty()) {
if(p) {
st.push(p);
p = p->left;
}
else {
p = st.top();
cout<<p->val<<" ";
st.pop();
p=p->right;
}
}
}


3.后序遍历

  后序遍历的二叉树的过程如下:

  (1)后序遍历左子树

  (2)后序遍历右子树

  (3)访问根结点

  后序遍历二叉树的递归算法如下:

//后序遍历(递归)
void PostOrder(TreeNode *root) {
if(root) {
PostOrder(root->left);
PostOrder(root->right);
cout<<root->val<<" ";
}
}


  由后续遍历可知,采用一个栈保存需要返回的结点指针,先扫描根结点的所有左结点并一一进栈,出栈一个结点*b即当前结点,然后扫描该节点的右孩子结点并进栈,再扫描该右孩子结点的所有左结点并建站。当一个结点的左右孩子结点均被访问后再访问该结点,如此这样,直到栈为空为止。

  其中的难点是如何判断一个结点*b的右孩子结点已被反问过,为此用p保存刚刚访问过的结点(初始值为NULL),若b->rchild==p成立(在后续遍历中,*b的右孩子结点一定刚好在*b之前被访问),说明*b的左右子树均已被访问,现在应访问*b。

  从上述过程可知,栈中保存的是当前结点*b的所有祖先结点(均未被访问过)。对应的递归算法如下:

//后序遍历(非递归)
void PostOrder2(TreeNode *root) {
stack<BTNode *> st;
TreeNode *p=root;
BTNode *temp;
while(p || !st.empty()) {
while(p) {
BTNode *btn = new BTNode();
btn->btnode = p;
btn->ifFirst = true;
st.push(btn);
p=p->left;
}
if(!st.empty()) {
temp = st.top();
st.pop();
if(temp->ifFirst) {
temp->ifFirst=false;
st.push(temp);
p = temp->btnode->right;
}
else {
cout<<temp->btnode->val<<" ";
p=NULL;
}
}
}
}


4.层次遍历

  层次遍历二叉树的过程如下:

  (1)访问根结点(第1层)。

  (2)从左到右访问第2层的所有结点。

  (3)从左到右访问第3层的所有结点,······,第h层的所有结点。

  层次遍历二叉树的算法如下:

//层次遍历
void LevelOrder(TreeNode *root) {
TreeNode *p = root;
queue<TreeNode *> qu;
qu.push(p);
while(!qu.empty()) {
p = qu.front();
cout<<p->val<<" ";
qu.pop();
if(p->left) {
qu.push(p->left);
}
if(p->right) {
qu.push(p->right);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  二叉树 遍历