树的结构的定义是一个递归的定义。树是n个结点的有限集。在任意一棵非空树中(1)有且仅有一个特定的称为根的结点(2)n>1时其余结点可分为m个互不相交的有限集,其中每一个集合本身又是一棵树,并且称为根的子树。
二叉树的实现和遍历
二叉树的四个性质:1.2.3.4.节点数目为k的完全二叉树的数目
先序遍历:先访问根节点;再递归地访问左子树;再递归
面试题:树的子结构
class Solution {
public:
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2) {
bool result=false;//采用先序遍历
if(pRoot1!=NULL&&pRoot2!=NULL){
if(pRoot1->val==pRoot2->val)
result=DoesTree1HaveTree2(pRoot1, pRoot2);
if(!result) {
result=HasSubtree(pRoot1->left, pRoot2);
}
if(!result) {
result=HasSubtree(pRoot1->right, pRoot2);
}
}
return result;
}
bool DoesTree1HaveTree2(TreeNode* pRoot1,TreeNode* pRoot2){
if(pRoot2==NULL) return true;//这两行代码的顺序不能改!说明了树B已经匹配完成,越过了叶子节点了
if(pRoot1==NULL) return false;//说明已经越过了树A的叶子节点了,匹配失败
if(pRoot1->val!=pRoot2->val) return false;
return DoesTree1HaveTree2(pRoot1->left, pRoot2->left)&& DoesTree1HaveTree2(pRoot1->right, pRoot2->right);
}
};
面试题:重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。(没有这个不含重复数字的条件就没法用这个算法做)思路如下,采用递归的方式,要注意递归函数的返回条件。
class Solution {
public:
TreeNode* buildTreeCore(const vector<int>& preorder, const vector<int>& inorder, int preleft, int preright, int inleft, int inright){
int n=preorder.size();
if(preleft>preright) return NULL;//注意此处
if(inleft>inright) return NULL;//加不加这一句都可以通过
TreeNode* a=new TreeNode();
a->val=preorder[preleft];
//前序遍历的第一个节点就是根节点的值,找中序遍历中根节点的位置
int rootinorder=0;
while(rootinorder<n){
if(inorder[rootinorder]==preorder[preleft]){
break;
}
++rootinorder;
}
int size_left_subtree=rootinorder-inleft;
//得到左子树中的结点数目
//构建左子树
a->left=buildTreeCore(preorder,inorder,preleft+1,preleft+size_left_subtree,inleft,rootinorder-1);
//构建右子树
a->right=buildTreeCore(preorder,inorder,preleft+size_left_subtree+1,preright,rootinorder+1,inright);
return a;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(preorder.empty()||inorder.empty()) return NULL;
//可以保证下面的都至少有一个结点
return buildTreeCore(preorder,inorder,0,preorder.size()-1,0,inorder.size()-1);
}
};
如果已知中序和后序要确定先序:(似乎只要知道中序和另外一个,就可以确定这个二叉树了)
typedef struct TreeNode{
int val;
TreeNode* left;
TreeNode* right;
} TreeNode;
void preOrderTraverse(TreeNode* root){
if(root==NULL) return;
cout<<root->val<<" ";
preOrderTraverse(root->left);
preOrderTraverse(root->right);
}
TreeNode* buildTree(const vector<int>& inorder,const vector<int>& postorder,int inleft, int inright,int postleft,int postright){
int n=inorder.size();
if(inleft>inright) return NULL;
if(postleft>postright) return NULL;
TreeNode* a=new TreeNode();//
a->val=postorder[postright];
int rootinorder=0;
while(rootinorder<n){
if(inorder[rootinorder]==postorder[postright]){
break;
}
rootinorder++;
}
//得到左子树的节点数目
int size_left_subtree=rootinorder-inleft;
a->left=buildTree(inorder,postorder,rootinorder-size_left_subtree,rootinorder-1,postleft,postleft+size_left_subtree-1);
a->right=buildTree(inorder,postorder,rootinorder+1,inright,postleft+size_left_subtree,postright-1);
return a;
}
int main(){
vector<int> inorder={9,3,15,20,7};
vector<int> postorder={9,15,7,20,3};
int n=inorder.size();
TreeNode* root=buildTree(inorder,postorder,0,n-1,0,n-1);
preOrderTraverse(root);
return 0;
}