今天开启新篇章,进入树这一数据结构,主要是递归操作。
二叉树作为树的代表,是一种常用的数据结构,其所有节点的度最多为2。
- 二叉树的三种遍历
先序遍历:根、左、右
中序遍历:左、根、右
后序遍历:左、右、根
记忆技巧:左右位置相对不变,根的位置与之遍历名字相对应。
先序遍历是在 递 的过程中输出节点,中序与后序则是在 归 的过程中输出节点
二叉树求高度与求节点数则是在 归 过程中通过相应的计数操作得到
先序遍历图(中、后同理):
package com.day11;
/**
* 存储char类型元素的二叉树.
*/
public class day11_BinaryCharTree {
/**
* The value in char.
*/
char value;
/**
* The left child.
*/
day11_BinaryCharTree left;
/**
* The right child
*/
day11_BinaryCharTree right;
/**
* ********************
* 构造方法.
*
* @param value The value.
* ********************
*/
public day11_BinaryCharTree(char value) {
this.value = value;
left = null;
right = null;
}//of day11_BinaryCharTree
/**
* ********************
* 静态方法构造出一个用于测试的二叉树
* ********************
*/
public static day11_BinaryCharTree manualConstructTree() {
day11_BinaryCharTree tempA = new day11_BinaryCharTree('a');
day11_BinaryCharTree tempB = new day11_BinaryCharTree('b');
day11_BinaryCharTree tempC = new day11_BinaryCharTree('c');
day11_BinaryCharTree tempD = new day11_BinaryCharTree('d');
day11_BinaryCharTree tempE = new day11_BinaryCharTree('e');
day11_BinaryCharTree tempF = new day11_BinaryCharTree('f');
day11_BinaryCharTree tempG = new day11_BinaryCharTree('g');
tempA.left = tempB;
tempA.right = tempC;
tempC.left = tempE;
tempB.right = tempD;
tempD.left = tempF;
tempD.right = tempG;
return tempA;
}//of manualConstructTree
/**
* ********************
* 先序遍历.
* ********************
*/
public void preOrderVisit() {
System.out.print("" + value + " ");
if (left != null) {
left.preOrderVisit();
}//of if
if (right != null) {
right.preOrderVisit();
}//of if
}//of preOderVisit
/**
* ********************
* 中序遍历.
* ********************
*/
public void inOrderVisit() {
if (left != null) {
left.inOrderVisit();
} // Of if
System.out.print("" + value + " ");
if (right != null) {
right.inOrderVisit();
} // Of if
}// Of inOrderVisit
/**
* ********************
* 后序遍历.
* ********************
*/
public void postOrderVisit() {
if (left != null) {
left.postOrderVisit();
} // Of if
if (right != null) {
right.postOrderVisit();
} // Of if
System.out.print("" + value + " ");
}// Of postOrderVisit
/**
* ********************
* 求二叉树的深度
*
* @return 深度值.
* ********************
*/
public int getDepth() {
int leftdeep = 0;
int rightdeep = 0;
if (left != null) {
leftdeep = left.getDepth();
}//of if
if (right != null) {
rightdeep = right.getDepth();
}//of if
return leftdeep > rightdeep ? leftdeep + 1 : rightdeep + 1;
}//of getDepth
/**
* ********************
* 求二叉树的节点数.
*
* @return 节点数.
* ********************
*/
public int getNumNodes() {
// It is a leaf.
if ((left == null) && (right == null)) {
return 1;
} // Of if
// The number of nodes of the left child.
int tempLeftNodes = 0;
if (left != null) {
tempLeftNodes = left.getNumNodes();
} // Of if
// The number of nodes of the right child.
int tempRightNodes = 0;
if (right != null) {
tempRightNodes = right.getNumNodes();
} // Of if
// The total number of nodes.
return tempLeftNodes + tempRightNodes + 1;
}// Of getNumNodes
/**
* ********************
* 程序入口.
*
* @param args 暂未使用.
* ********************
*/
public static void main(String args[]) {
day11_BinaryCharTree tempTree = manualConstructTree();
System.out.println("\r\n先序遍历:");
tempTree.preOrderVisit();
System.out.println("\r\n中序遍历:");
tempTree.inOrderVisit();
System.out.println("\r\n后序遍历:");
tempTree.postOrderVisit();
System.out.println("\r\n\r\n高度: " + tempTree.getDepth());
System.out.println("节点数: " + tempTree.getNumNodes());
}// Of main
}//of day11_BinaryCharTree
运行结果:
总结:递归的代码依然简洁,也是一如既往的烧脑细胞,求高度的代码在递的过程中不做操作,在归的过程中就相当厉害了
在归的过程从叶子节点开始,反着推上去,每个节点都取左右孩子里最大值并加一
求总结点数的代码与求高度本质上我感觉没有啥区别,都是归的过程中“计数”,我自己写的时候尝试在递去过程中直接计数,不过后来发现有问题。
在类里设置静态变量 nodes,在递去的过程中直接修改nodes来计数,但是随后发现在递归的方法中没办法维护这个nodes,还需要单独写个方法来reset nodes,不然就是一次性计数。
定义静态变量作为计数器
递去过程中修改nodes,最后直接返回nodes
手动维护nodes