二叉树的遍历满足递归的形式
二叉树的遍历满足递归的思路,无论是先序的根左右,中序的左根右,还是后续的左右跟都是从根结点开始,对每个结点进行先序/中序/后序的遍历,每个结点都是如此,假如是先序根左右的遍历,我们先访问根结点,然后再是左结点,但是左结点没结束,对左结点又进行一遍根左右的遍历,那么对于左结点自己来说,他自己就是根结点了,然后进行根左右遍历,于是又对总根结点的左结点的左结点再来一次先序遍历…就这样一直把整个二叉树所有结点遍历完
该结点没有左右结点怎么办
以先序举例,假如该结点没有左结点,那就按照根左右的顺序,再访问右结点,要是右结点存在,就继续先序遍历,如果右结点不存在,则这层递归肯定是最里层的递归,该层递归到右结点不存在为结束,然后返回上一层递归,并从上层递归中左递归方法调用的下一行开始,也就是从上层递归中的右递归正式开始,换句话说就是从该层递归对应的双亲结点的右结点处继续先序遍历
不想将遍历出的数据直接输出控制台怎么办
我看过严蔚敏版的 C 语言数据结构,其中是把遍历的数据直接输出到控制台中,现在我有个需求就是想把递归遍历的结构保存到数组中,并且递归的返回值就是数组,我该怎么做呢?
由于递归就是在其方法中调用自己,实现这种[<[<[<[
层层嵌套的形式,当第四个[
执行完后,就到第三个[
,最后到第一个[
,第一个最下面返回一个数组即可,实际上每层都会返回数组。
- 如果我把数组放在递归方法中可以吗?
如果放在递归方法中,数组会被重复初始化,所以我把数组作为类的成员变量 - 下标在递归方法中声明可行吗?或者作为递归方法的形参呢?
如果放在递归方法中声名,同样重复初始化变量。如果作为形参呢?好像是可以的,然后仔细一想不行,因为下标是 int 类型的形参,在遍历的递归方法中作为参数传过去,递归方法中会调用自己这个方法,所以作为浅拷贝代表的 int 形参在被调用的递归方法中不管怎么变化,跳出这层递归返回上一层,该下标又还原了,所以也不行。所以怎么办呢,下标 index 直接声明为 static 就行,这样也不用作为形参去传了 - 其他注意
最外层递归的 return 返回数组前要记得把 index 重置为 0,因为我在使用完先序遍历之后也有可能想再使用中序遍历或后序遍历,所以这个 index 要重置为 0
// 结点
class Node {
int data;
Node left = null;
Node right = null;
}
// 二叉树
public class BinaryTree {
// 根结点
private Node root;
// 输入的数组
private int[] arr_in;
// 输出的数组
private int[] arr_out;
// 记录数组下标
private static int index;
// 初始化
public BinaryTree(int[] arr) {
root = new Node();
this.arr_in = arr;
arr_out = new int[arr.length];
index = 0;
}
// 先序遍历二叉树(递归)根→左→右
public int[] preorderTraversalRecursion(Node r) {
if (r) {
arr_out[index++] = r.data;
preorderRecursion(r.left, index);
preorderRecursion(r.rigth, index);
}
if (index == arr_in.length)
index = 0;
return arr_out;
}
// 中序遍历二叉树(递归)左→根→右
public int[] inorderTraversalRecursion(Node r) {
if (r) {
inorderRecursion(r.left, index);
arr_out[index++] = r.data;
inorderRecursion(r.rigth, index);
}
if (index == arr_in.length)
index = 0;
return arr_out;
}
// 后序遍历二叉树(递归)左→右→根
public int[] postorderTraversalRecursion(Node r) {
if (r) {
postorderRecursion(r.left, index);
postorderRecursion(r.rigth, index);
arr_out[index++] = r.data;
}
if (index == arr_out.length)
index = 0;
return arr_out;
}
}