二叉树遍历

简介: 递归遍历比较简单,本文主要总结非递归遍历。前序遍历前序遍历按照“根结点-左孩子-右孩子”的顺序进行访问。 对于任一结点P:访问结点P,并将结点P入栈;判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;直到P为NULL并且栈为空,则遍历结束。vo

递归遍历比较简单,本文主要总结非递归遍历。

前序遍历

前序遍历按照“根结点-左孩子-右孩子”的顺序进行访问。
对于任一结点P:

  1. 访问结点P,并将结点P入栈;
  2. 判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;
  3. 直到P为NULL并且栈为空,则遍历结束。
void preorder(TreeNode *root)
{
    stack<TreeNode*> s;
    TreeNode *p = root;
    while (p != NULL || !s.empty())
    {
        while (p != NULL)
        {
            cout<<p->val<<" ";
            s.push(p);
            p = p->left;
        }

        if (!s.empty())
        {
            p = s.top();
            s.pop();
            p = p->right;
        }
    }
}

中序遍历

中序遍历按照“左孩子-根结点-右孩子”的顺序进行访问。
对于任一结点P,

  1. 若其左孩子不为空,则将P入栈并将P的左孩子置为当前的P,然后对当前结点P再进行相同的处理;
  2. 若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的P置为栈顶结点的右孩子;
  3. 直到P为NULL并且栈为空则遍历结束
void inorder(TreeNode *root)
{
    stack<TreeNode*> s;
    TreeNode *p = root;
    while (p != NULL || !s.empty())
    {
        while (p != NULL)
        {
            s.push(p);
            p = p->left;
        }

        if (!s.empty())
        {
            p = s.top();
            cout<<p->val<<" ";
            s.pop();
            p = p->right;
        }
    }
}

后序遍历

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

void postorder(TreeNode *root)
{
    if (root == NULL)
    {
        return;
    }
    stack<TreeNode*> s;
    s.push(root);
    TreeNode *pre = NULL;
    TreeNode *cur;
    while (!s.empty())
    {
        cur = s.top();
        if (cur->left == NULL && cur->right == NULL ||
            pre != NULL && (pre == cur->left || pre == cur->right))
        {
            cout<<cur->val<<" ";
            s.pop();
            pre = cur;
        }
        else
        {
            if (cur->right != NULL)
            {
                s.push(cur->right);
            }
            if (cur->left != NULL)
            {
                s.push(cur->left);
            }
        }
    }
}

层次遍历

void levelTraverse(TreeNode *root)
{
    if (root == NULL)
    {
        return;
    }
    queue<TreeNode*> q;
    q.push(root);
    TreeNode *p;
    while (!q.empty())
    {
        p = q.front();
        q.pop();
        cout<<p->val<<" ";
        if (p->left != NULL)
        {
            q.push(p->left);
        }
        if (p->right != NULL)
        {
            q.push(p->right);
        }
    }
}

建立二叉树:

     a
b        c
   d        e
--------------
void create(TreeNode *&p, const char *str, int& i)
{
    if (i < strlen(str) && str[i] == '#')
    {
        p = NULL;
    }
    else
    {
        p = new TreeNode(str[i] - '0');
        create(p->left, str, ++i);
        create(p->right, str, ++i);
    }
}

int main()
{
    TreeNode *root = NULL;
    char *str = "ab#d##c#e##";
    int i = 0;
    create(root, str, i);
}
目录
相关文章
|
7月前
二叉树遍历及应用
二叉树遍历及应用
78 0
|
7月前
|
算法
带你深入理解二叉树的遍历
带你深入理解二叉树的遍历
|
7月前
|
存储
LeetCode题94,44,145,二叉树的前中后序遍历,非递归
LeetCode题94,44,145,二叉树的前中后序遍历,非递归
62 0
|
7月前
【二叉树遍历和练习】
【二叉树遍历和练习】
57 0
|
算法
25 二叉树的遍历
25 二叉树的遍历
29 0
|
存储
二叉树的遍历问题
二叉树的遍历问题