对于一棵二叉树一般有三种遍历方式,先序遍历(preOrder)、中序遍历(inOrder)、后序遍历(postOrder)。

同时这里还介绍了二叉树的 层次遍历(levelOrder)

每种遍历都有递归的实现和非递归的实现。

1、preOrder

对每个节点进行遍历,并将right节点push到一个stack中

//递归实现
void preOrder1(BinTree *root)     //递归前序遍历 
{
    if(root!=NULL)
    {
        cout<<root->data<<" ";
        preOrder1(root->lchild);
        preOrder1(root->rchild);
    }
}

//非递归
void preOrder2(BinTree *root)     //非递归前序遍历 
{
    stack<BinTree*> s;
    BinTree *p=root;
    while(p!=NULL||!s.empty())
    {
        while(p!=NULL)
        {
            cout<<p->data<<" ";
            s.push(p);
            p=p->lchild;
        }
        if(!s.empty())
        {
            p=s.top();
            s.pop();
            p=p->rchild;
        }
    }
}

2、inOrder

通过一个stack存储遍历的中心节点,知道最左边的节点,然后对stack进行pop操作。

//递归实现
void inOrder1(BinTree *root)      //递归中序遍历
{
    if(root!=NULL)
    {
        inOrder1(root->lchild);
        cout<<root->data<<" ";
        inOrder1(root->rchild);
    }
} 
//非递归实现
void inOrder2(BinTree *root)      //非递归中序遍历
{
    stack<BinTree*> s;
    BinTree *p=root;
    while(p!=NULL||!s.empty())
    {
        while(p!=NULL)
        {
            s.push(p);
            p=p->lchild;
        }
        if(!s.empty())
        {
            p=s.top();
            cout<<p->data<<" ";
            s.pop();
            p=p->rchild;
        }
    }    
} 

3、postOrder

  要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。  

//递归
void postOrder1(BinTree *root)    //递归后序遍历
{
if(root!=NULL)
{
postOrder1(root->lchild);
postOrder1(root->rchild);
cout<<root->data<<" ";
}
}
//非递归
void postOrder(BinTree *root) //非递归后序遍历 { stack<BinTree*> s; BinTree *cur; //当前结点 BinTree *pre=NULL; //前一次访问的结点 s.push(root); while(!s.empty()) { cur=s.top(); if((cur->lchild==NULL&&cur->rchild==NULL)|| (pre!=NULL&&(pre==cur->lchild||pre==cur->rchild))) { cout<<cur->data<<" "; //如果当前结点没有孩子结点或者孩子节点都已被访问过 s.pop(); pre=cur; } else { if(cur->rchild!=NULL) s.push(cur->rchild); if(cur->lchild!=NULL) s.push(cur->lchild); } } }

4、层次遍历

一次从左到右输出一颗二叉树的 每一层元素。

定义两个queue,将其中一个queue中每个元素的左右节点一次push进另一个queue中,直到该队列为空。

然后访问另一queue执行同样的操作。

//leetcode中遍历的方法
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        queue<TreeNode *> in1,in2;
        vector<vector<int>> re;
        if (root == NULL) return re;
        in1.push(root);
        while (!in1.empty()||!in2.empty()){
            vector<int> temp;
            if (!in1.empty()){
                while (!in1.empty()){
                    TreeNode    *p = in1.front();
                    in1.pop();
                    temp.push_back(p->val);
                    if (p->left != NULL) in2.push(p->left);
                    if (p->right!= NULL) in2.push(p->right);
                }
            }
            else {
                while (!in2.empty()){
                    TreeNode    *p = in2.front();
                    in2.pop();
                    temp.push_back(p->val);
                    if (p->left != NULL) in1.push(p->left);
                    if (p->right != NULL) in1.push(p->right);
                }
            }
            re.push_back(temp);
        }
        return re;
    }
};