原题来自维基OI
题目描述:求一棵二叉树的前序遍历,中序遍历和后序遍历.
输入描述:
第一行一个整数n,表示这棵树的节点个数.
接下来n行每行2个整数L和R.第i行的两个整数Li和Ri代表编号为i的节点的左儿子编号和右儿子编号.
输出描述:
输出一共三行,分别为前序遍历,中序遍历和后序遍历.编号之间用空格隔开.
求一棵二叉树的前序遍历,中序遍历和后序遍历.
对于一棵二叉树的任意一个结点的遍历,有三个操作:
1.访问该结点本身
2.遍历该结点的左子树
3.遍历该结点的右子树
二叉树的前序遍历,就是从根结点开始,对每个结点按照1>2>3的顺序操作,一直到叶结点为止.
同理:
二叉树的中序遍历,对每个结点按照2>1>3的顺序操作,一直到叶结点为止.
二叉树的后序遍历,对每个结点按照3>2>1的顺序操作,一直到叶结点为止.
所以代码可以用递归来写,AC代码如下:
#include <iostream> using namespace std; int tree[21][2];/* 二维数组tree,储存了输入的二叉树 */ int res[20];/* 每次遍历,都把结果存到里面 */ int j = -1; void setzero()/* 把res每个元素设置为0,把j设为-1,并换行 */ { for (int i = 0; i<= 20; i++) { res[i] = 0; } j = -1; cout << '\n'; } void output()/* 输出res,相邻的元素之间加上空格 */ { for (int i = 0; i <= j; i++) { if (i == j) { cout << res[i]; } else { cout << res[i] << ' '; } } } void rfs(int n)/* 先序遍历,n是指节点编号,下同 */ { j = j + 1; res[j] = n;/* 把该节点存到res最后一个 */ if (tree[n][0] > 1) { rfs(tree[n][0]);/* 如果有左子树,对左子树执行rfs */ } if (tree[n][1] > 1) { rfs(tree[n][1]);/* 如果有右子树,对右子树执行rfs */ } } void rms(int n)/* 中序遍历 */ { if (tree[n][0] > 1) { rms(tree[n][0]);/* 如果有左子树,对左子树执行rfs */ } j = j + 1; res[j] = n;/* 把该节点存到res最后一个 */ if (tree[n][1] > 1) { rms(tree[n][1]);/* 如果有右子树,对右子树执行rfs */ } } void rls(int n)/* 后序遍历 */ { if (tree[n][0] > 1) { rls(tree[n][0]);/* 如果有左子树,对左子树执行rfs */ } if (tree[n][1] > 1) { rls(tree[n][1]);/* 如果有右子树,对右子树执行rfs */ } j = j + 1; res[j] = n;/* 把该节点存到res最后一个 */ } int main() { int n; cin >> n; for (int i = 1; i <= n; i++) { cin >> tree[i][0] >> tree[i][1];/* 读入二叉树 */ } rfs(1);/* 先序遍历 */ output();/* 输出 */ setzero();/* 清零 */ rms(1);/* 中序遍历 */ output();/* 输出 */ setzero();/* 清零 */ rls(1);/* 后序遍历 */ output();/* 输出 */ return 0; }
写代码的过程很曲折,主要是自己容易在一些细节上出问题,这个毛病一定要改.
中间定义了很多函数,不知道这样是否符合规范,个人比较喜欢这样,如果有不合理的地方,敬请批评指正.