二叉树的存储与操作
二叉树的存储结构
- 顺序存储
即将左孩子存储在2i,将右孩子存储在2i+1
比较适合完全二叉树,对于非完全二叉树有空间浪费
- 链接存储
二叉链表:left data right
三叉链表:left data parent right
二叉树的遍历及递归算法
先序遍历
1 2 3 4 5 6 7
| void Preorder(TreeNode* t) { if(t==NULL) return; visit(t->data); Preorder(t->left); Preorder(t->right); }
|
中序遍历
1 2 3 4 5 6 7
| void Inorder(TreeNode* t) { if(t==NULL) return; Preorder(t->left); visit(t->data); Preorder(t->right); }
|
后序遍历
1 2 3 4 5 6 7
| void Postorder(TreeNode* t) { if(t==NULL) return; Preorder(t->left); Preorder(t->right); visit(t->data); }
|
遍历的非递归算法
先序遍历

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| void Preorder(TreeNode* t) { Stack S; TreeNode* p=t; while(true) { while(p!=NULL) { visit(p->data); S.push(p); p=p->left; } if(S.empty()) return; p=S.pop(); p=p->right; } }
|
中序遍历

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| void InOrder(TreeNode* t) { Stack S; TreeNode p=t; while(true) { while(p!=NULL) { S.push(p); p=p->left; } if(S.empty()) return; p=S.pop(); visit(p->data); p=p->right;
} }
|
后序遍历

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| void PostOreder(TreeNode* t) { Stack S; TreeNode* p=t; TreeNode* pre=NULL; while(true) { while(p!=NULL) { S.push(p); p=p->left; } if(S.empty()) return; p=S.peak(); if(p->right==NULL||p->right==pre) { p=S.pop(); visit(p->data); pre=p; p=NULL; } else p=p->right; } }
|
层次遍历

1 2 3 4 5 6 7 8 9 10 11 12
| void LevelOrder(TreeNode* t) { Quene Q; if(t!=NULL) Q.enquene(t); while(!Q.empty()) { TreeNode* p=Q.dequeue(); visit(p->data); if(p->left) Q.enqueue(p->left); if(p->right) Q.enqueue(p->right); } }
|
辅助队列的规模
最大规模:n/2(向上取整)
统计每层结点信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| int LeafInEachLevel(TreeNode* root,int leafnum[]) { if(root==NULL) return -1; Queue q; int level=0; q.enqueue(root); while(!q.empty()) { int size=q.size(); for(int i=0;i<size;i++) { TreeNode* p=q.dequeue(); if(p->left==NULL&&p->right==NULL) leafnum[level]++; if(p->left) q.enqueue(p->left); if(p->right) q.enqueue(p->right); } level++; } return level-1; }
|
二叉树的重建与计数
二叉树的重建
中根序列和任意一种遍历序列都可以唯一确定一棵二叉树
给定二叉树的先根序列和中根序列, 编写程序构建二叉树。
【 大 厂 面 试 题 、 华 中 科 技 大 学 考 研 复 试 机 试 题 、
OpenJudgeP0570、 LeetCode105】

1 2 3 4 5 6 7 8 9 10 11
| TreeNode* buildtree(char* preorder,char* inorder,int n) { if(n<=0) return NULL; char rootval=preorder[0]; TreeNode* root=new TreeNode; root->val=rootval; int k=find(inorder,n,rootval); root->left=buildtree(&preorder[1],&inorder[0],k); root->right=buildtree(&preorder[k+1],&inorder[k+1],n-k-1); return root; }
|
二叉树的计数
Cantalan(n)

二叉树的其他操作
解决二叉树问题的一般框架
算法 f(root)
{
可在此处处理根节点
f(root->left);
可在此处处理根节点
f(root->right)
可在此处处理根节点
return;
}
如,在二叉树中搜索给定结点的父结点
1 2 3 4 5 6 7 8 9
| TreeNode* Father(TreeNode* root,TreeNode* p) { if(root==NULL||p==root) return NULL; if(root->left==p||root->right==p) return root; TreeNode* fa=Father(root->left,p); if(fa!=NULL) return fa; return Father(root->right,p);
}
|
创建二叉树
通过一种遍历序列不能唯一确定二叉树,因为在二叉树中,有的节点之左/右指针为空,这在先根序列中不能被体现。
增强先根序列:空指针处用#表示
根据增强先根序列创建二叉树
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| char s[N]; int k=0; TreeNode* CreateBinTree(char preorder[]) { char ch=preorder[k++]; if(ch=='#') return NULL; TreeNode* t=new TreeNode; t->data=ch; t->left=CreateBinTree(preorder); t->right=CreateBinTree(preorder); return t; } int main() { scanf("%s",s); TreeNode* root=CreateBinTree(s); }
|
上机实验常用创建形式
1 2 3 4 5 6 7 8 9 10 11
| TreeNode* CreateBinTree() { int k; cin>>k if(k==0) return NULL; TreeNode* t=new TreeNode; t->data=k; t->left=CreateBinTree(); t->right=CreateBinTree(); return t; }
|
二叉树中、先、后根序列的首末结点

中根序列
第一个结点,向左走到头
最后一个结点,同理,向右走到头
先根序列
第一个结点,root
最后一个节点:从根节点开始沿右分支找第一个叶结点,若找不到则在最右边结点的左子树沿右分支找叶结点
后根序列
第一个结点:从根节点开始沿左分支找第一个叶结点,若找不到则在最左边结点的右子树沿左分支找叶结点
最后一个节点:root
二叉树的路径
输出从根到叶的所有路径,k为递归深度
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| void findpath(TreeNode* t,int path[],int k) { if(t==NULL) return; path[k]=t->data; if(t->left==NULL&&t->right==NULL) { for(int i=0;i<k;i++) printf("%d ",path[i]); printf("\n"); return; } findpath(t->left,path,k+1); findpath(t->right,path,k+1); }
|
输出从根到数据值为x的一条路径,k为递归深度
1 2 3 4 5 6 7 8 9 10 11 12 13
| void FindPath(TreeNode* t,vector<int>path,int k,int x,vector<int>&path) { if(t==NULL) return; path.push_back(t->val); if(t->val==x) { for(int i=0;i<=k;i++) path.push_back(path[i]); return; } FindPath(t->left,path,k+1,x,path); FindPath(t->right,path,k+1,x,path); }
|
二叉树的公共祖先
1 2 3 4 5 6 7 8 9 10 11 12
| TreeNode* Traversal(TreeNode*root,int a,int b) { if(root==NULL) return NULL; if(root->val==a||root->val==b) return root; TreeNode* left=Traversal(root->left,a,b); TreeNode* right=Traversal(root->right,a,b); if(left!=NULL&&right!=NULL) return root; else if(left!=NULL&&right==NULL) return left; else if(left==NULL&&right!=NULL) return right; else return NULL; }
|