1.1链式存储
第⼀⾏⼀个整数n,表⽰结点数。
之后n⾏,第⾏两个整数l 、r,分别表⽰结点i的左右⼦结点编号。若l=0则表⽰⽆左
⼦结点,同理。
#include<iostream>
using namespace std;
const int N = 1e5 + 10;
int l[N];
int r[N];
int main()
{
int n = 0;
cin >> n;
for (int i = 1; i <= n; i++)
{
// 存下 i 号结点的左右孩⼦
cin >> l[i] >> r[i];
}
return 0;
}
2.二叉树的遍历
2.1 深度优先遍历
不同于常规树的深度优先遍历,⼆叉树因其独特的性质可以划分成三种深度优先遍历:先序遍历,中序遍历,和后序遍历。其中,三种遍历⽅式的不同在于处理根节点的时机。
对于⼀棵⼆叉树⽽⾔,整体可以划分成三部分:根节点+左⼦树+右⼦树:
• 先序遍历的顺序为:根+左+右;
• 中序遍历的顺序为:左+根+右;
• 后序遍历的顺序为:左+右+根。
#include<iostream>
using namespace std;
const int N = 1e5 + 10;
int l[N];
int r[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()
{
int n = 0;
cin >> n;
for (int i = 1; i <= n; i++)
{
// 存下 i 号结点的左右孩⼦
cin >> l[i] >> r[i];
}
dfs1(1);//先序
dfs2(1);//中序
dfs3(1);//后序
return 0;
}
2.2 宽度优先遍历
这个就和常规的树的遍历⽅式⼀样,直接⽤队列帮助层序遍历即可。
#include<iostream>
#include<queue>
using namespace std;
const int N = 1e5 + 10;
int l[N];
int r[N];
void bfs()
{
queue<int>q;
q.push(1);
while (q.size())
{
auto p = q.front(); q.pop();
cout << p;
// 左右孩⼦⼊队
if (l[p]) q.push(l[p]);
if (r[p]) q.push(r[p]);
}
cout << endl;
}
int main()
{
int n = 0;
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> l[i] >> r[i];
}
bfs();
return 0;
}