• 面试笔试总结——二叉树


    收集整理一些关于二叉树的笔试面试题。

    二叉树的数据结构:

    struct TreeNode {
        int val;
        struct TreeNode *left;
        struct TreeNode *right;
    };

    1. 二叉树的深度

    最简单的方法便是递归法。

    int TreeDepth(TreeNode *proot)
    {
        if(!pRoot) return 0;
        return max(1+TreeDepth(pRoot->left), TreeDepth(pRoot->right));
    }

    2. 二叉树的遍历

    这里仅给出中序遍历。

    2.1 非递归遍历

    思路:对于任一结点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;
            }
        }    
    }

    2.2 递归遍历

    void inOrder(TreeNode* root)     
    {
        if(root!=NULL)
        {
            inOrder(root->left);
            cout<<root->val<<" ";
            inOrder(root->right);
        }
    }

    3. 二叉树的层序遍历

    将遍历的结果放入vector中。

    vector<int> PrintFromTopToBottom(TreeNode* root) {
        vector<int> vec;
        if(root==nullptr) return vec;  //指针推荐这种写法 布尔值这样写:if(!root) 
        queue<TreeNode*> Q ;
        TreeNode* p = nullptr;
       
        Q.push(root);
        while(!Q.empty()){          //empty()返回布尔值 所以这样写
            p = Q.front();
            Q.pop();
            vec.push_back(p->val);
            if(p->left != nullptr) 
                Q.push(p->left);
            if(p->right != nullptr)
                Q.push(p->right);
        }
        return vec;
    }

    延伸:二叉树层序遍历,将树的每一层的结果保存为一行。

    vector<vector<int> > Print(TreeNode* pRoot) {
        vector<vector<int> > res;
        if(pRoot==nullptr) return res;
        queue<TreeNode*> q;
        q.push(pRoot);
        
        while(!q.empty())
        {
            int lo = 0, hi = q.size();  //使用lo和hi提取行号
            vector<int> c;
            while(lo++ < hi)
            {
                TreeNode *t = q.front();
                q.pop();
                c.push_back(t->val);
                if(t->left) q.push(t->left);
                if(t->right) q.push(t->right);
            }
            res.push_back(c);
        }
        return res;
    }

    4. 求二叉树的镜像

    操作给定的二叉树,将其变换为源二叉树的镜像。

    void Mirror(TreeNode *pRoot) {
        if(pRoot==NULL){
            return;
        }
        TreeNode *tmp = pRoot->left;
        pRoot->left = pRoot->right;
        pRoot->right = tmp;
        Mirror(pRoot->left);
        Mirror(pRoot->right);
    } 

    延伸:判断两个二叉树是否对称,即其中一个是否是另一个的镜像。

    思路:

    /*首先根节点以及其左右子树,左子树的左子树和右子树的右子树相同
    * 左子树的右子树和右子树的左子树相同即可,采用递归
    * 非递归也可,采用栈或队列存取各级子树根节点
    */

    bool isSymmetrical(TreeNode* pRoot)
    {
        return isSymmetrical(pRoot,pRoot);
    }
    
    bool isSymmetrical(TreeNode* pRoot1, TreeNode* pRoot2)
    {
        if(pRoot1==NULL && pRoot2==NULL)
            return true;
        if(pRoot1==NULL ||  pRoot2==NULL)
            return false;
        if(pRoot1->val != pRoot2->val)
            return false;
        return isSymmetrical(pRoot1->left, pRoot2->right) && isSymmetrical(pRoot1->right, pRoot2->left);
    }

    5. 给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8)    中,按结点数值大小顺序第三小结点的值为4

        int count = 0;
        TreeNode* KthNode(TreeNode* pRoot, int k)
        {
            if(pRoot){
                TreeNode* ret = KthNode(pRoot->left,k);
                if(ret) return ret;   //此判断为了确保在找到(count == k)的时候能逐层返回
                if(++count==k) return pRoot;
                ret = KthNode(pRoot->right,k);
                if(ret) return ret;
            }
            return nullptr;
        }

    6. 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

    public class TreeLinkNode {
        int val;
        TreeLinkNode left = null;
        TreeLinkNode right = null;
        TreeLinkNode next = null;
    
        TreeLinkNode(int val) {
            this.val = val;
        }
    }

    分析二叉树的下一个节点,一共有以下情况:

    1.二叉树为空,则返回空;
    2.节点右孩子存在,则设置一个指针从该节点的右孩子出发,一直沿着指向左子结点的指针找到的叶子节点即为下一个节点;
    3.节点不是根节点。如果该节点是其父节点的左孩子,则返回父节点;否则继续向上遍历其父节点的父节点,重复之前的判断,返回结果。
    public TreeLinkNode GetNext(TreeLinkNode pNode)
    {
        if(pNode == null) return null;
        if(pNode.right!=null){   //如果有右子树,则找右子树的最左节点
            pNode = pNode.right;
            while(pNode.left!=null) 
                pNode = pNode.left;
            return pNode;
        }
        
        while(pNode.next!=null){
           //没有右子树,如果该节点是其父节点的左孩子,则返回父节点;
           //否则继续向上遍历其父节点的父节点,重复之前的判断,返回结果。
            if(pNode.next.left==pNode) 
                return pNode.next;
            pNode = pNode.next;
        }
        return null;
    }        
  • 相关阅读:
    call_user_func和call_user_func_array的区别
    25行实现文件上传功能(PHP)
    PHP 结合MYSQL简单的实现了Todo List 功能
    向ASP.NET自定义控件中嵌入CSS资源
    模态子窗口不执行page_load
    oracle一次插入多条数据
    转载:数据库表结构设计方法及原则
    Js中的window.parent ,window.top,window.self
    在一个JS文件中包含中文字符串通过innerHTML输出后中文乱码
    转载:数据库表结构设计方法及原则
  • 原文地址:https://www.cnblogs.com/bencai/p/9518174.html
Copyright © 2020-2023  润新知