二叉树相关笔试题(二)

来源:互联网 发布:linux 创建网络接口 编辑:程序博客网 时间:2024/04/25 23:43

1.二叉树中和为某一值的路径

题目:输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整树的所有路径。从树的根节点开始往下直到叶节点所经的结点形成一条路径。

分析:由于路径是从根节点出发的,所以选择前序遍历,当访问到一个结点时,把该结点添加到路径,并累加该结点的值,如果该结点为叶子结点并且路径中结点值的和刚好等于输入的整数,则该路径符合要求,如果当前结点不是叶子结点,则继续访问它的子节点。

实现代码:

    void FindPath(TreeNode* root, int num,                  vector<vector<int>>& ret, vector<int>& path){        if(root == NULL){            return;        }        if(root->val > num){            return;        }        path.push_back(root->val);        if((root->val) == num && (root->left == NULL && root->right == NULL)){            ret.push_back(path);            path.pop_back();        }        else{            FindPath(root->left, num - root->val, ret, path);            FindPath(root->right, num - root->val, ret, path);            path.pop_back();        }    }    vector<vector<int>> FindPath(TreeNode* root,int expectNumber) {        vector<vector<int>> ret;        vector<int> path;        if(root == NULL){            return ret;        }        FindPath(root, expectNumber, ret, path);        return ret;    }


2.二叉搜索树与双向链表

题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表,要求不能创建任何新的结点,只能调整树中结点指针的指向。

分析:在二叉搜索树中,左子结点的值总是小于父节点的值,右子节点的值总是大于父节点的值,因为要求转换成排序的双向链表,可以中序遍历这棵二叉搜索树,因此在转换时,原先指向左子结点的指针调整为指向前一个结点的指针,原先指向右子节点的指针调整为指向后一个结点的指针。当遍历到根节点时,将根节点和它的左子树值最大的结点链接,和右子树最小的结点链接。

实现代码:


    TreeNode* ConvertNode(TreeNode* pRoot, TreeNode*& LastNode)    {         if(pRoot == NULL){            return NULL;        }        TreeNode* left = ConvertNode(pRoot->left,LastNode);        if(left != NULL){            LastNode->right = pRoot;            pRoot->left = LastNode;        }        LastNode = pRoot;        TreeNode* right = ConvertNode(pRoot->right,LastNode);        if(pRoot->right != NULL){            right->left = pRoot;            pRoot->right = right;        }        return left != NULL ? left:pRoot;    }         TreeNode* Convert(TreeNode* pRootOfTree)    {        if(pRootOfTree == NULL){            return NULL;        }        TreeNode* LastNode = NULL;        if(pRootOfTree->left == NULL && pRootOfTree->right == NULL){            LastNode = pRootOfTree;            return pRootOfTree;        }        return ConvertNode(pRootOfTree, LastNode);     }

3.二叉树的深度
实现代码:
    int TreeDepth(TreeNode* pRoot)    {        if(pRoot == NULL){            return 0;        }        int left = TreeDepth(pRoot->left);        int right = TreeDepth(pRoot->right);        return left>right ? left+1:right+1;    }
4.判断一棵树是不是平衡二叉树
方法一:调用求二叉树深度的函数得到它的左右子树深度,如果每个结点的左右子树深度相差的绝对值不超过一,则是平衡二叉树。
实现代码:
    bool IsBalanced_Solution(TreeNode* pRoot)     {        if(pRoot == NULL){            return true;        }        int left = TreeDepth(pRoot->left);        int right = TreeDepth(pRoot->right);        int dif = abs(left - right);        if(dif > 1){            return false;        }        return IsBalanced_Solution(pRoot->left) && IsBalanced_Solution(pRoot->right);    }

方法二:用后序遍历的方法遍历二叉树的结点,在遍历到每个节点之前就已经遍历了它的左右子树。只要在遍历每个结点时记下它的深度,这样就可以只需遍历一次判断出每个结点是否平衡。
实现代码:
    bool IsBalanced(TreeNode *root, int& depth){        if(root == NULL){            return true;        }        int left = 0;        int right = 0;        if(IsBalanced(root->left,left) && IsBalanced(root->right, right)){            int dif = abs(left - right);            if(dif <= 1){                depth = (left > right ? left : right) + 1;                return true;            }        }        return false;    }    bool IsBalanced_Solution(TreeNode* pRoot) {        int depth = 0;        return IsBalanced(pRoot, depth);    }
5.二叉树的下一个结点
题目:给定一棵二叉树和其中一个结点,如何找出中序遍历顺序的下一个结点?树中的结点除了有两个分别指向左右子结点的指针外,还有一个指向父节点指针。
分析:1.如果一个结点有右子树,则它的下一个结点就是指向它的右子树中最左的子节点;
           2.如果一个结点没有右子树,并且该结点是它父亲结点的左子节点,那么它的下一个节点就是它的父亲结点;    
          3.如果一个结点既没有右子树并且该结点是它父亲结点的右子结点,这种情况下就得沿着它的父节点的指针向上遍历,直到找到一个结点是它父亲结点的左子结点的结点,如果存在,那么这个结点就是要找的结点。
实现代码:
    TreeLinkNode* GetNext(TreeLinkNode* pNode)    {        if(pNode == NULL){            return NULL;        }        TreeLinkNode* pNext = NULL;        if(pNode->right != NULL){            TreeLinkNode* cur = pNode->right;            while(cur->left != NULL){                cur = cur->left;            }            pNext = cur;        }        else if(pNode->parent != NULL){            TreeLinkNode* cur = pNode;            TreeLinkNode* pParent = pNode->parent;            while(pParent != NULL && cur == pParent->right){                cur = pParent;                pParent = pParent->parent;            }            pNext = pParent;        }        retur3n pNext;    }
6.对称的二叉树
题目:请实现一个函数,判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
分析:可以定义一种与前序遍历对称的遍历算法,即先遍历根节点,再遍历它的右子结点,最后遍历它的左子结点。如果得到的遍历序列与前序遍历得到的一样,那么这棵树就是对称的。
实现代码:
    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);    }    bool isSymmetrical(TreeNode* pRoot)    {        return isSymmetrical(pRoot, pRoot);    }

2 0