二叉树(静态实现)
一般存储方法
struct node
{
int v,l,r;
node(){l = r = -1;}
}tree[N];
int idx;
or
int tree[N];//tree[i]的左儿子 :tree[2 * i] 右儿子:tree[2 * i + 1],根节点下标为1
结构体数组idx的用法
tree[idx ++] = {v,l,r};
//相当于 动态建树中的动态申请空间
遍历
访问二叉树时输出顺序:
前序遍历:根节点、左子树、右子树
中序遍历:左子树、根节点、右子树
后序遍历:左子树、右子树、根节点
层序遍历:逐层遍历
递归版
前序遍历
vector<int> a;
void dfs(int u)
{
int l = t[u].l,r = t[u].r;
a.push_back(t[u].v);
if(l != -1) dfs(l);
if(r != -1) dfs(r);
}
中序遍历
vector<int> a;
void dfs(int u)
{
int l = t[u].l,r = t[u].r;
if(l != -1) dfs(l);
a.push_back(t[u].v);
if(r != -1) dfs(r);
}
后序遍历
vector<int> a;
void dfs(int u)
{
int l = t[u].l,r = t[u].r;
if(l != -1) dfs(l);
if(r != -1) dfs(r);
a.push_back(t[u].v);
}
非递归版
前序遍历
vector<int> order(int root)
{
vector<int> res;
stack<int> stk;
int t = root;
while(t != -1 || !stk.empty())
{
while(t != -1)
{
res.push_back(tree[t].v);
stk.push(t);
t = tree[t].l;
}
if(!stk.empty())
{
t = stk.top();
stk.pop();
t = tree[t].r;
}
}
return res;
}
中序遍历
vector<int> order(int root)
{
vector<int> res;
stack<int> stk;
int t = root;
while(t != -1 || !stk.empty())
{
while(t != -1)
{
stk.push(t);
t = tree[t].l;
}
if(!stk.empty())
{
t = stk.top();
res,push_back(tree[t].v);
t = tree[t].r;
}
}
return res;
}
后序遍历
vector<int> order(int root)
{
vector<int> res;
stack<int> stk;
int t = root;
while(t != -1 || !stk.empty())
{
while(t != -1)
{
res.push_back(tree[t].v);
stk.push(t);
t = tree[t].r;
}
if(!stk.empty())
{
t = stk.top();
stk.pop();
t = tree[t].l;
}
}
reverse(res.begin(),res.end());
return res;
}
层序遍历
vector<int> bfs(int root)
{
vector<int> res;
queue<int> q;
q.push(root);
while(q.size())
{
int t = q,front();
q.pop();
int l = tree[t].l, r = tree[t].r;
res.push_back(tree[t].v);
if(l != -1) q.push(l);
if(r != -1) q.push(r);
}
return res;
}
已知前序、中序遍历构建二叉树
int idx;
int creat(int prel,int prer,int inl,int inr)
{
if(prel > prer) return -1;
int t = idx;
tree[idx ++].v = pre[prel];
int k ;
for(k = inl;k <= inr;k ++)
if(in[k] == pre[prel]) break;
int num = k - inl;
tree[t].l = creat(prel + 1,prel + num,inl,k - 1);
tree[t].r = creat(prel + num + 1,prer,k + 1,inr);
return t;
}
已知后序、中序遍历构建二叉树
int idx;
int creat(int postl,int postr,int inl,int inr)
{
if(postl > postr) return -1;
int t = idx;
tree[idx ++] = post[postr];
int k;
for(k = inl;k <= inr;k ++)
if(in[k] == post[postr]) break;
int num = k - inl;
tree[t].l = creat(postl,postl + num - 1,inl,k - 1);
tree[t].r = creat (postl + num,postr - 1,k + 1,inr);
return t;
}
镜像建树思路
法一:
在建树的时候左右对调,原本该连在左子树的东西连在右子树上,原本该连在右子树的东西连在左子树上,
例:
已知前序、中序遍历镜像构建构建二叉树
int idx;
int creat(int prel,int prer,int inl,int inr)
{
if(prel > prer) return -1;
int t = idx;
tree[idx ++].v = pre[prel];
int k ;
for(k = inl;k <= inr;k ++)
if(in[k] == pre[prel]) break;
int num = k - inl;
tree[t].r = creat(prel + 1,prel + num,inl,k - 1);//只是在这里做了修改
tree[t].l = creat(prel + num + 1,prer,k + 1,inr);//只是在这里做了修改
return t;
}
法二:
写镜像函数
求高度
int dfs(int root)
{
int l = 0, r = 0;
if(tree[root].l != -1) l = dfs(tree[root].l);
if(tree[root].r != -1) r = dfs(tree[root].r);
return max(l,r) + 1;
}
求某个节点深度
int p[N];//p[i] 为 节点 i 的父节点。
int get_dep(int pos)
{
int t = pos,cnt = 0;
while(p[pos] != -1)
{
cnt ++;
pos = p[pos];
}
return cnt;
}
例题
先中序建树 + 求高度
后中序建树 + 层序遍历
中序遍历
镜像 + 层序 、中序遍历
最近公共祖先
镜像 + 层序遍历
完全二叉树的特殊建树方式 + 层序遍历[]
树的深搜 or 广搜