二叉树遍历

行文结构

  1. 递归方法(前中后)
  2. 非递归方法(前中后层)
  3. 微软面试题

 

二叉树遍历根据“根节点”遍历时相对的次序分为前序、中序、后序。图示为相对于根节点的次序,左右子树也是一样的规则。

                     前序遍历                                             中序遍历                                                后续遍历

1. 递归方法

前序遍历

void PreorderTraversal(BiTree T)
{
    if(T != NULL)
    {
        cout << T->data << endl;
        PreorderTraversal(T->left);
        PreorderTraversal(T->right);
    }
}

中序遍历

void InorderTraversal(BiTree T)
{
    if(T != NULL)
    {
        InorderTraversal(T->left);
        cout << T->data << endl;
        InorderTraversal(T->right);
    }
}

后续遍历

void PostorderTraversal(BiTree T)
{
    if(T != NULL)
    {
        PostorderTraversal(T->left);
        PostorderTraversal(T->right);
        cout << T->data << endl;
    }
}

整合参考程序

#include<iostream>
#include<vector>
using namespace std;

typedef struct BiTNode
{
    int data;
    BiTNode *left;
    BiTNode *right;
}BiTNode, *BiTree;

bool SearchBST(BiTree T, int val, BiTree f, BiTree &p)
{
    if(!T)
    {
        p = f;
        return false;
    }
    else if(val == T->data)
    {
        p = T;
        return true;
    }
    else if(val < T->data)
        SearchBST(T->left, val, T, p);
    else
        SearchBST(T->right, val, T, p);
}

bool InsertBST(BiTree &T, int val)
{
    BiTree p;
    if(!SearchBST(T, val, NULL, p))
    {
        BiTree node = new BiTNode;
        node->data = val;
        node->left = node->right = NULL;
        if(!p)
            T = node;
        else if(val < p->data)
            p->left = node;
        else
            p->right = node;
        return true;
    }
    return false;
}

void PreorderTraversal(BiTree T)
{
    if(T)
    {
        cout << T->data << endl;
        PreorderTraversal(T->left);
        PreorderTraversal(T->right);
    }
}

void InorderTraversal(BiTree T)
{
    if(T)
    {
        InorderTraversal(T->left);
        cout << T->data << endl;
        InorderTraversal(T->right);
    }
}

void PostorderTraversal(BiTree T)
{
    if(T)
    {
        PostorderTraversal(T->left);
        PostorderTraversal(T->right);
        cout << T->data << endl;
    }
}

int main()
{
    int array[] = {5, 1, 0, 45, 10, 3, 8, 5};
    int len_array = sizeof(array) / sizeof(*array);
    BiTree root = NULL;
    for(int i = 0; i< len_array; ++i)
        InsertBST(root, array[i]);
    cout << "PreorderTraversal" << endl;
    PreorderTraversal(root);
    cout << "----------------------" << endl;

    cout << "InorderTraversal" << endl;
    InorderTraversal(root);
    cout << "----------------------" << endl;

    cout << "PostorderTraversal" << endl;
    PostorderTraversal(root);
    cout << "----------------------" << endl;
}
View Code

结果

 

2. 非递归方法

非递归方法借助于栈,“记忆”走过的结点。

前序遍历

“根-左孩子-右孩子”,对每一个结点看成是根节点,先输出,后入栈(到时返回访问右孩子),然后访问左孩子。当不能在往左走时,查询栈中的记忆,根据栈顶进入右孩子,重复上边的故事。

void PreorderTraversal(BiTree T)
{
    stack<BiTree> s;
    while(T != NULL || !s.empty())
    {
        while(T != NULL)
        {
            cout << T->data << endl;
            s.push(T);
            T = T->left;
        }
        T = s.top();
        T = T->right;
        s.pop();
    }
}

中序遍历

“左孩子-根-右孩子”,对每一个结点看成是根节点,先入栈(到时返回访问自己和右孩子),然后访问左孩子。当不能在往左走时,查询栈中的记忆,根据栈顶访问自己并且进入右孩子,重复上边的故事。

void InorderTraversal(BiTree T)
{
    stack<BiTree> s;
    while(T != NULL || !s.empty())
    {
        while(T != NULL)
        {
            s.push(T);
            T = T->left;
        }
        T = s.top();
        cout << T->data << endl;
        T = T->right;
        s.pop();
    }
}

后续遍历

“左孩子-右孩子-根”,为了达到这个效果,需要把把按“根-->右孩子-->左孩子”的顺序入栈,因为栈的特征是先进后出,所以访问时顺序相反。对于一个结点只有满足以下两个条件时,才访问,否则按“根-->右孩子-->左孩子”顺序入栈。

  • 左右孩子全为NULL
  • 前边访问的结点正好为当前结点的左孩子或右孩子(访问了左孩子必定已经访问了右孩子)
void PostorderTraversal(BiTree T)
{
    stack<BiTree> s;
    BiTree cur = NULL, pre = NULL;
    s.push(T);
    while(!s.empty())
    {
        cur = s.top();
        if((cur->left != NULL && cur->right != NULL) ||
          (pre != NULL && (pre == cur->left || pre == cur->right)))
        {
            cout << cur->data << endl;
            pre = cur;
            s.pop();
        }
        else
        {
            if(cur->right)
                s.push(cur->right);
            if(cur->left)    
                s.push(cur->left);
        }
    }
}

整合参考程序

#include<iostream>
#include<stack>

using namespace std;

typedef struct BiTNode
{
    int data;
    BiTNode *left;
    BiTNode *right;
}BiTNode, *BiTree;

bool SearchBST(BiTree T, int val, BiTree f, BiTree &p)
{
    if(!T)
    {
        p = f;
        return false;
    }
    else if(val == T->data)
    {
        p = T;
        return true;
    }
    else if(val < T->data)
        SearchBST(T->left, val, T, p);
    else
        SearchBST(T->right, val, T, p);
}

bool InsertBST(BiTree &T, int val)
{
    BiTree p;
    if(!SearchBST(T, val, NULL, p))
    {
        BiTree node = new BiTNode;
        node->data = val;
        node->left = node->right = NULL;
        if(!p)
            T = node;
        else if(val < p->data)
            p->left = node;
        else
            p->right = node;
        return true;
    }
    return false;
}

void PreorderTraversal(BiTree T)
{
    stack<BiTree> s;
    while(T || !s.empty())
    {
        while(T)
        {
            cout << T->data << endl;
            s.push(T);
            T = T->left;
        }
        T = s.top();
        T = T->right;
        s.pop();
    }
}

void InorderTraversal(BiTree T)
{
    stack<BiTree> s;
    while(T || !s.empty())
    {
        while(T)
        {
            s.push(T);
            T = T->left;
        }
        T = s.top();
        cout << T->data << endl;
        T = T->right;
        s.pop();
    }
}

void PostorderTraversal(BiTree T)
{
    if (T == NULL)
         return;
    stack<BiTree> s;
    BiTree cur = NULL, pre = NULL;
    s.push(T);
    while(!s.empty())
    {
        cur = s.top();
        if((!cur->left && !cur->right) ||
                (pre != NULL && (pre == cur->left || pre == cur->right)))
        {
            cout << cur->data << endl;
            pre = cur;
            s.pop();
        }
        else
        {
            if(cur->right)
                s.push(cur->right);
            if(cur->left)    
                s.push(cur->left);
        }
    }
}

int main()
{
    int array[] = {5, 1, 0, 45, 10, 3, 8, 5};
    int len_array = sizeof(array) / sizeof(*array);
    BiTree root = NULL;
    for(int i = 0; i< len_array; ++i)
        InsertBST(root, array[i]);
    cout << "PreorderTraversal" << endl;
    PreorderTraversal(root);
    cout << "----------------------" << endl;

    cout << "InorderTraversal" << endl;
    InorderTraversal(root);
    cout << "----------------------" << endl;

    cout << "PostorderTraversal" << endl;
    PostorderTraversal(root);
    cout << "----------------------" << endl;
}
View Code

结果同递归遍历

层次遍历

详见http://www.cnblogs.com/kaituorensheng/p/3558645.html

 

3. 微软面试题

分析:由二叉遍历树变成有序的结构,不用说绝对是中序遍历。中序遍历分为两种方法——递归、非递归。递归不需要额外的空间,非递归需要额外空间(借助与栈)。现在用两种方法实现,其思路都是基本中序遍历的改进。

方法一(递归方法)

void BST2BLink(BiTree T, BiTree &pre)  //&地址操作,所有递归使用同一个
{
    if(T)
    {
        BST2BLink(T->left, pre);
        if(pre)
        {
            pre->right = T;
            T ->left = pre;
        }
        pre = T;
        BST2BLink(T->right, pre);
    }
}

执行程序

#include<iostream>
#include<stack>

using namespace std;

typedef struct BiTNode
{
    int data;
    BiTNode *left;
    BiTNode *right;
}BiTNode, *BiTree;

bool SearchBST(BiTree T, int val, BiTree f, BiTree &p)
{
    if(!T)
    {
        p = f;
        return false;
    }
    else if(val == T->data)
    {
        p = T;
        return true;
    }
    else if(val < T->data)
        SearchBST(T->left, val, T, p);
    else
        SearchBST(T->right, val, T, p);
}

bool InsertBST(BiTree &T, int val)
{
    BiTree p;
    if(!SearchBST(T, val, NULL, p))
    {
        BiTree node = new BiTNode;
        node->data = val;
        node->left = node->right = NULL;
        if(!p)
            T = node;
        else if(val < p->data)
            p->left = node;
        else
            p->right = node;
        return true;
    }
    return false;
}

void BST2BLink(BiTree T, BiTree &pre)
{
    if(T)
    {
        BST2BLink(T->left, pre);
        if(pre)
        {
            pre->right = T;
            T ->left = pre;
        }
        pre = T;
        BST2BLink(T->right, pre);
    }
}

int BST2BLink(BiTree &T)
{
    stack<BiTree> s;
    BiTree cur = T, pre = NULL;
    while(cur || !s.empty())
    {
        while(cur)
        {
            s.push(cur);
            cur = cur->left;
        }

        cur = s.top();
        s.pop();
        cout << cur->data << endl;

        if(!pre)
            T = cur;
        else
        {
            pre->right = cur;
            cur ->left = pre;
        }
        pre = cur;
        cur = cur->right;
    }
}

void BLinkTraversal(BiTree root)
{
    while(root)
    {
        cout << root->data << endl;
        root = root->right;
    }
}

int main()
{
    int array[] = {5, 8, 0, 3, 100, 45};
    int len_array = sizeof(array) / sizeof(*array);
    BiTree root = NULL;
    for(int i = 0; i< len_array; ++i)
        InsertBST(root, array[i]);

    cout << "Recursion" << endl;
    BiTree pre = NULL;
    BST2BLink(root, pre);
    while(root->left)
        root = root->left;
    BLinkTraversal(root);
/*
    cout << "\nNot Recursion" << endl;
    BST2BLink(root_copy);
    cout << "----------------------" << endl;
    BLinkTraversal(root);
    */
}
View Code

方法二(非递归方法)

int BST2BLink(BiTree &T)
{
    stack<BiTree> s;
    BiTree cur = T, pre = NULL;
    while(cur || !s.empty())
    {
        while(cur)
        {
            s.push(cur);
            cur = cur->left;
        }

        cur = s.top();
        s.pop();
        cout << cur->data << endl;
        if(!pre)
            T = cur;
        else
        {
            pre->right = cur;
            cur ->left = pre;
        }
        pre = cur;
        cur = cur->right;
    }
}

执行程序

#include<iostream>
#include<stack>

using namespace std;

typedef struct BiTNode
{
    int data;
    BiTNode *left;
    BiTNode *right;
}BiTNode, *BiTree;

bool SearchBST(BiTree T, int val, BiTree f, BiTree &p)
{
    if(!T)
    {
        p = f;
        return false;
    }
    else if(val == T->data)
    {
        p = T;
        return true;
    }
    else if(val < T->data)
        SearchBST(T->left, val, T, p);
    else
        SearchBST(T->right, val, T, p);
}

bool InsertBST(BiTree &T, int val)
{
    BiTree p;
    if(!SearchBST(T, val, NULL, p))
    {
        BiTree node = new BiTNode;
        node->data = val;
        node->left = node->right = NULL;
        if(!p)
            T = node;
        else if(val < p->data)
            p->left = node;
        else
            p->right = node;
        return true;
    }
    return false;
}

void BST2BLink(BiTree T, BiTree &pre)
{
    if(T)
    {
        BST2BLink(T->left, pre);
        if(pre)
        {
            pre->right = T;
            T ->left = pre;
        }
        pre = T;
        BST2BLink(T->right, pre);
    }
}

int BST2BLink(BiTree &T)
{
    stack<BiTree> s;
    BiTree cur = T, pre = NULL;
    while(cur || !s.empty())
    {
        while(cur)
        {
            s.push(cur);
            cur = cur->left;
        }

        cur = s.top();
        s.pop();
//        cout << cur->data << endl;

        if(!pre)
            T = cur;
        else
        {
            pre->right = cur;
            cur ->left = pre;
        }
        pre = cur;
        cur = cur->right;
    }
}

void BLinkTraversal(BiTree root)
{
    while(root)
    {
        cout << root->data << endl;
        root = root->right;
    }
}

int main()
{
    int array[] = {5, 8, 0, 3, 100, 45};
    int len_array = sizeof(array) / sizeof(*array);
    BiTree root = NULL;
    for(int i = 0; i< len_array; ++i)
        InsertBST(root, array[i]);
/*
    cout << "Recursion" << endl;
    BiTree pre = NULL;
    BST2BLink(root, pre);
    while(root->left)
        root = root->left;
    BLinkTraversal(root);
*/
    cout << "\nNot Recursion" << endl;
    BST2BLink(root);
    cout << "----------------------" << endl;
    BLinkTraversal(root);
    
}
View Code

 

posted @ 2013-11-19 21:04  jihite  阅读(1539)  评论(0编辑  收藏  举报