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


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

    二叉树的数据结构:

    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;
    }        
  • 相关阅读:
    Kinect 开发 —— 硬件设备解剖
    Kinect 开发 —— 引言
    (转)OpenCV 基本知识框架
    OpenCV —— 摄像机模型与标定
    OpenCV —— 跟踪与运动
    OpenCV —— 图像局部与分割(二)
    OpenCV —— 图像局部与部分分割(一)
    OpenCV —— 轮廓
    OpenCV —— 直方图与匹配
    OpenCV —— 图像变换
  • 原文地址:https://www.cnblogs.com/bencai/p/9518174.html
Copyright © 2020-2023  润新知