一、二叉树的概念
1.二叉树的定义


#include <iostream>
using namespace std;
const int N=1e6+10;
int l[N],r[N];
int n;
int main()
{cin >> n;for(int i=1;i<=n;i++){cin >> l[i] >> r[i];}return 0;
}
3.二叉树的遍历
#include <iostream>
using namespace std;
const int N=1e6+10;
int l[N],r[N];
int n;
//先序遍历
void dfs1(int u)
{if(u==0)return;cout << u << " ";dfs1(l[u]);dfs1(r[u]);
}
//中序遍历
void dfs2(int u)
{if(u==0)return;dfs2(l[u]);cout << u << " ";dfs2(r[u]);
}
//后序遍历
void dfs3(int u)
{if(u==0)return;dfs3(l[u]);dfs3(r[u]);cout << u << " ";
}
int main()
{cin >> n;for(int i=1;i<=n;i++){cin >> l[i] >> r[i];}dfs1(1);cout << endl;dfs2(1);cout << endl;dfs3(1);cout << endl;return 0;
}
(2)宽度优先遍历
#include <iostream>
#include <queue>
using namespace std;
const int N=1e6+10;
int l[N],r[N];
int n;
queue<int> q;
//先序遍历
void dfs1(int u)
{if(u==0)return;cout << u << " ";dfs1(l[u]);dfs1(r[u]);
}
//中序遍历
void dfs2(int u)
{if(u==0)return;dfs2(l[u]);cout << u << " ";dfs2(r[u]);
}
//后序遍历
void dfs3(int u)
{if(u==0)return;dfs3(l[u]);dfs3(r[u]);cout << u << " ";
}
//宽度优先遍历
void bfs()
{q.push(1);while(q.size()){int u=q.front();cout << u << " ";q.pop();if(!l[u])q.push(l[u]);if(!r[u])q.push(r[u]);}
}
int main()
{cin >> n;for(int i=1;i<=n;i++){cin >> l[i] >> r[i];}dfs1(1);cout << endl;dfs2(1);cout << endl;dfs3(1);cout << endl;bfs();cout << endl;return 0;
}
四、相关的算法题
1.
#include <iostream>
using namespace std;
const int N=300;
char l[N],r[N];
int n;
char root;
void dfs(char root)
{if(root=='*')return;cout << root;dfs(l[root]);dfs(r[root]);
}
int main()
{cin >> n >> root;cin >> l[root] >> r[root];for(int i=2;i<=n;i++){char t;cin >> t;cin >> l[t] >> r[t];}dfs(root);return 0;
}

#include <iostream>
using namespace std;
const int N=1e6+10;
int l[N],r[N];
int n;
int dfs(int u)
{if(u==0)return 0;return max(dfs(l[u]),dfs(r[u]))+1;
}
int main()
{cin >> n;for(int i=1;i<=n;i++){cin >> l[i] >> r[i];}cout << dfs(1) << endl;return 0;
}


#include <iostream>
#include <string>
using namespace std;
string a,b;
void dfs(int l1,int r1,int l2,int r2)
{if(l1>r1)return;// 当区间不合法时,返回cout << b[r2];//找到根结点并输出 int p=l1;while(a[p]!=b[r2])p++;//找到中序排列的根结点 dfs(l1, p - 1, l2, l2 + p - l1 - 1); // 递归处理左子树dfs(p + 1, r1, l2 + p - l1, r2 - 1); // 递归处理右子树
}
int main()
{cin >> a >> b;dfs(0,a.size()-1,0,b.size()-1);return 0;
}
其实就是通过后序排列先找到头结点,再找到中序排列中头结点的位置,就能将中序排列分为左子树和右子树,在通过区间的长度得出每个区间的范围下标就可以了。当然这种题肯定不止一种,但我们需要确保有中序排列,因为有了它我们才可以通过头结点来分区。
4.


#include <iostream>
#include <vector>
#include <queue>
using namespace std;
const int N=110;
vector<int> t[N];
int n,u,v;
queue<int> q;
int fa[N],dist[N];
int Dist;
int dfs(int x)
{//方法一 if(!t[x].size())return 1;if(t[x].size()==1)return dfs(t[x][0])+1;return max(dfs(t[x][0]),dfs(t[x][1]))+1;//方法二 int ret=0;for(auto i:t[x]){ret=max(ret,dfs(i));}return ret+1;
}
int bfs()
{int ret=0;q.push(1);while(q.size()){int sz=q.size();ret=max(ret,sz); while(sz--){int m=q.front();q.pop();for(auto i:t[m]){q.push(i);}}}return ret;
}
int main()
{cin >> n;for(int i=1;i<n;i++){cin >> u >> v;t[u].push_back(v);fa[v]=u;}cout << dfs(1) << endl;cout << bfs() << endl;int a,b;cin >> a >> b;while(a!=1){
// dist[fa[a]]=dist[a]+1;
// a=fa[a];Dist++;a=fa[a];dist[a]=Dist;}Dist=0;while(!dist[b]&&b!=1){b=fa[b];Dist++;}cout << dist[b]*2+Dist << endl;return 0;
}
本题由三部分组成。第一部分是求二叉树的深度,和之前的思路是一样的,就是拆解为子树的深度再加1。方法一就是将所有情况分成三种进行操作,分别是有两个孩子,有一个孩子或者是没有孩子,进行递归。方法二就是设置一个变量ret,通过max找出子树中的最大深度再加上1,进行递归。第二部分的思路和宽度优先遍历差不多,通过队列来实现,通过q.size()得出每一行的宽度,这个宽度还有一个作用,就是进行n次操作从而使当前行的元素全部取出,并使下一行的元素进入队列。这样循环往复,我们就能使ret和size进行取大,找出最大的宽度。第三部分就是通过向上不断找父结点,再之前记录每个结点的父结点,再用一个数组来记录到这个结点的距离。我们再从第二个点开始找,第一个重叠的位置,就是两者的最近公共祖先。