树–》图的存储 (邻接表,邻接矩阵)
图的遍历方式:DFS,BFS
第一题:数叶子节点
求每一层叶子节点个数?
存储在cnt[N]中
用邻接表存储:
dfs(u,depth)
{
if(h[u]==-1)
{
cnt[depth]++;
max_depth=max(max_depth,depth);
return ;
}
for(int i=h[u];i!=-1;i=ne[i])
dfs(e[i],depth+1);
}
第二题:树的遍历
1.层序遍历 :BFS
2.前中后 :DFS
利用中序遍历和后续遍历构造树
再层序遍历输出
int build(int il,int ir,int pl,int pr)
{
int root=postorder[pr];
int k=pos[root];
if(il<k) l[root]=build(il,k-1,pl,pl+k-i-1);
if(k<ir) r[root]=build(k+1,pr,pl+k-i,pr-1);
return root;
}
第三题:树的最深的根
1.N个点,N-1条边。如果是同一个连通块,则是一颗树
2.遍历每个点做为根节点的最大高度
int dfs(int u,int father)
{
int depth=0;
for(int i=h[u];i!=-1;i=ne[i])
{
int j=e[i];
if(j==father) continue;
depth=max(depth,dfs(j,u)+1);
}
return depth;
}
第四题:判断二插搜索树
特点:左子树小于根,右子树大于根
二插搜索树的中序遍历一定有序。
转化:已经前序遍历和中序遍历 ==》判断他能否构造一颗树
bool build(int il,int ir,int pl,int pr,int type)
{
if(il>ir) return true;
int k;
if(type==0)
{
for(k=il;k<=ir ;k++)
if(inorder[k]==root)
break;
if(k>ir) return false;
}
else
{
for(int i=ir;i>=il;i--)
if(inorder[k]==root)
break;
if(k< il) break;
}
bool res=true;
if(!build(il,k-1,pl+1,pl+1+k-i-1,type)) flag=false;
if(!build(k+1,ir,pl+1+k-1-i+1,pr,type)) flag=false;
postorder[cnt++]=root;
return res;
}
第五题:完全二插搜索树
存储简单:一维数组就可以了
void dfs(int u,int k)
{
if(u*2<=n) dfs(u*2,k);
tr[u]=w[k++];
if(u*2+1<=n) dfs(u*2+1,k);
}
for(int i=0;i<n;i++) cin>>w[i];
sort(w,w+n);
int k=0;
dfs(1,k);
for(int i=1;i<=n;i++) cout<<tr[i]<<' ';
第六题:再次遍历二叉树
void main()
{
cin>>n;
int root;
int last=0,type;
stack<int> stk;
for(int i=0;i<n*2;i++)
{
string op;
cin>>op;
if(op=="Push")
{
int x;
cin>>x;
if(!last) root=x;
else
{
if(type==0) l[last]=x;
else r[last]=x;
}
stk.push(x);
last=x;
type=0;
}
else
{
last=stk.top();
stk.pop();
type=1;
}
}
}
AVL树