剑指offer-数据结构二——树

剑指offer-数据结构—树

1.重建二叉树

题目描述:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

class Solution {
public:
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
        TreeNode* root = nullptr;
        int size1 = pre.size();
        int size2 = vin.size();
        if (size1 <= 0 || size2 <= 0)
            return nullptr;
        root = ContructTree(pre, vin, 0, size1 - 1, 0, size2 - 1);
        return root;
    }

    TreeNode* ContructTree(vector<int> pre, vector<int> vin, int prel, int prer, int vinl, int vinr) {
        TreeNode* T = nullptr;
        if (prer >= prel) {
            int index = 0;
            for (index = vinl; index <= vinr; index++) {
                //  寻找到前序第一个节点在中序中的位置。
                if (vin[index] == pre[prel]) {
                    break;
                }
            }
            T = new TreeNode(pre[prel]);
            int leftlen = index - vinl;
            int rightlen = vinr - index;
            if (leftlen > 0)
                T -> left = ContructTree(pre, vin, prel + 1, prel + leftlen, vinl, vinl + leftlen - 1);
            else
                T -> left = nullptr;
            if (rightlen > 0)
                T -> right = ContructTree(pre, vin, prer - rightlen + 1, prer, vinr - rightlen + 1, vinr);
            else
                T -> right = nullptr;
        }
        return T;
    }
};

2.二叉树的下一个节点

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

思路分析: 分为以下三种情况考虑:

(1)给定节点有右子节点,那么中序遍历的下一个节点就是给定节点的右子节点的最左子节点;

(2)给定节点没有右子节点,并且给定节点是该节点的父节点的左子节点,那么中序遍历的下一个节点就是给定节点的父节点;

(3)给定节点没有右子节点,并且给定节点是该节点的父节点的右子节点,从该节点开始往上寻找,直到找到一个节点m是m的父节点n的左子节点,那么中序遍历的下一个节点就是父节点n。(这里的依据是中序遍历先遍历左子树,输出根节点值,再遍历右子树,那么给定一个节点,并且知道节点没有右子节点,并且这个节点是它的父节点的右子节点,所以需要寻找的就是一个虚拟的根节点)。

/*
struct TreeLinkNode {
    int val;
    struct TreeLinkNode *left;
    struct TreeLinkNode *right;
    struct TreeLinkNode *next;
    TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) {
        
    }
};
*/
class Solution {
public:
    TreeLinkNode* GetNext(TreeLinkNode* pNode) {
        TreeLinkNode* ret = nullptr;
        if (pNode == nullptr)
            return ret;
        if (pNode -> right != nullptr) {
            //  如果节点有右子节点,那么中序的下一个节点就是右子节点的最左子节点
            ret = pNode -> right;
            while (ret -> left != nullptr)
                ret = ret -> left;
        } else if (pNode -> right == nullptr) {
            //  如果没有右子节点
            if (pNode -> next && pNode -> next -> left == pNode) {
                // 看该节点是左子节点还是右子节点,如果是左子节点,那么
                //  中序的下一个节点就是父节点
                ret = pNode -> next;
            } else if (pNode -> next && pNode -> next -> right == pNode) {
                //  如果这个这个节点是它的父节点右子节点,并且本身没有右子节点
                //  那么沿着该节点的父节点往上寻找,直到找到一个节点是它父节点的
                //  左子节点,那么那个节点的父节点就是要寻找的节点
                
                TreeLinkNode* temp = pNode -> next;
                TreeLinkNode* tempfather = nullptr;
                while (temp) {
                    tempfather = temp -> next;
                    if (tempfather && tempfather -> left == temp) {
                        ret = tempfather;
                        break;
                    }
                    temp = temp -> next;
                }
            }
        }
        return ret;
    }
};

3.树的子结构

题目描述: 输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
注意:本题中两个数是整数所以可以直接比较大小,但是如果是浮点数,由于计算机内表示的小数都有误差,所以需要自己单独写一个函数来判断两个浮点数是不是相等,判断时两个数的误差不超过10^(-7)都可以认为两个数相等。

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    bool isTheSubTree(TreeNode* root1, TreeNode* root2) {
        //  向下寻找到了树B的叶节点,说明树B是树A的子树
        if (root2 == nullptr)
            return true;
        
        //  如果输A到达了叶节点但是树B还没有到达叶节点,那么树B不是树A的子树
        if (root1 == nullptr)
            return false;

        if (root1 -> val != root2 -> val)
            return false;
        
        return isTheSubTree(root1 -> left, root2 -> left) && isTheSubTree(root1 -> right, root2 -> right);
    }


    bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2) {
        // 判断树pRoot2(A)是否是PRoot1(B)的子结构
        //  在树A中查找树B中的根节点,查找到了之后判断后面的子树是否相等
        
        bool result = false;
        if (pRoot1 && pRoot2) {
            if (pRoot1 -> val == pRoot2 -> val)
                result = isTheSubTree(pRoot1, pRoot2);
            if (!result)
                result = HasSubtree(pRoot1 -> left, pRoot2);
            if (!result)
                result = HasSubtree(pRoot1 -> right, pRoot2);
        }
        return result;
    }
};

4.二叉树的镜像

题目描述:
操作给定的二叉树,将其变换为源二叉树的镜像。

输入描述:
二叉树的镜像定义:源二叉树 
	    8
	   /  \
	  6   10
	 / \  / \
	5  7 9 11
	镜像二叉树
	    8
	   /  \
	  10   6
	 / \  / \
	11 9 7  5

思路分析:使用递归的思路很容易的就可以得出二叉树的镜像

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    void Mirror(TreeNode *pRoot) {
        if (pRoot == nullptr)
            return;
        TreeNode* temp = nullptr;
        temp = pRoot -> left;
        pRoot -> left = pRoot -> right;
        pRoot -> right = temp;
        Mirror(pRoot -> left);
        Mirror(pRoot -> right);
    }
};

5.对称的二叉树

题目描述: 请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:

    bool isSymmetrical(TreeNode* root1, TreeNode* root2) {
        if (root1 == nullptr && root2 == nullptr)
            return true;
        else if (root1 == nullptr && root2 != nullptr)
            return false;
        else if (root1 != nullptr && root2 == nullptr)
            return false;
        else if (root1 -> val != root2 -> val)
            return false;
        else return isSymmetrical(root1 -> left, root2 -> right) 
                    && isSymmetrical(root1 -> right, root2 -> left);
    }

    bool isSymmetrical(TreeNode* pRoot) {
        return isSymmetrical(pRoot, pRoot);
    }

};

6.层次遍历二叉树

题目描述: 从上往下打印出二叉树的每个节点,同层节点从左至右打印。

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    vector<int> PrintFromTopToBottom(TreeNode* root) {
        vector<int> vec;
        if (root == nullptr) return vec;
        queue<TreeNode*> que;
        que.push(root);
        TreeNode* proot = nullptr;
        while (!que.empty()) {
            proot = que.front();
            vec.push_back(proot -> val);
            if (proot -> left != nullptr)
                que.push(proot -> left);
            if (proot -> right != nullptr)
                que.push(proot -> right);
            que.pop();
        }
        return vec;
    }
};

7.二叉树的后序遍历序列

题目描述: 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。

思路分析: 首先画出一棵二叉搜索树,然后从遍历的序列可以得知序列的最后一个元素是根节点,然后从开始节点开始,寻找根节点左边的部分,然后根据左边的部分继续查找,如果根节点右边的部分存在比根节点的值小的节点,那么后序的序列就是错的,接着找出根节点的右子树,然后再递归分别判断左子树和右子树。

测试样例: (1)空二叉树;(2)只有左子树的搜索二叉树;(3)只有右子树的搜索二叉树;(4)一般的搜索二叉树的后序序列;(5)具有错误的序列的后序序列。

class Solution {
public:
    bool isPostSequence(vector<int> vec, int start, int end) {
        //if (vec.size() <= 0 || end - start <= 0)
        if (vec.size() <= 0) return false;
        if (start == end) return true;
        if (start > end) return false;
        int root = vec[end];

        int index = 0;
        //在二叉树中寻找值小于根节点的值
        for (index = start; vec[index] < vec[end]; ++index);

        bool left = true;
        if (index > start)
            left = isPostSequence(vec, start, index - 1);
        //  看看二叉树的右子树中是否有小于根节点的值
        for (int i = index + 1; i <= end; i++)
            if (vec[i] < root) {
                return false;
            }
                
        
        bool right = true;
        //  判断右子树
        if (end - 1 > index)
          right = isPostSequence(vec, index, end - 1);

        if (left && right) return true;
        return false;
    }
    bool VerifySquenceOfBST(vector<int> sequence) {
        if (sequence.size() > 0) {
            if (isPostSequence(sequence, 0, sequence.size() - 1))
                return true;
            return false;
        }
        return false;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值