• 二叉树遍历


    行文结构

    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 << "
    Not 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 << "
    Not Recursion" << endl;
        BST2BLink(root);
        cout << "----------------------" << endl;
        BLinkTraversal(root);
        
    }
    View Code
  • 相关阅读:
    如何快速查看archlinux pacman 软件记录?
    如何快速判断检查主机ip端口是否存活?
    如何在不清楚有哪些tag的情况下拉取docker镜像?
    如何使用docker版Openresty测试框架Test::Nginx进行测试?
    .net mvc4 使用 System.Web.Optimization 对javascript和style的引入、代码合并和压缩的优化(ScriptBundle,StyleBundle,Bund
    zen coding de 一些快捷功能
    C# Xpath
    一个SQL SERVER查询分析器非常好用的工具
    探索MSSQL执行计划
    博客园武林人士
  • 原文地址:https://www.cnblogs.com/kaituorensheng/p/3431409.html
Copyright © 2020-2023  润新知