二叉树节点:
1
2
3
4
5
6
7
8
9
|
class BinaryTreeNode {
int val;
BinaryTreeNode left;
BinaryTreeNode right;
public BinaryTreeNode(int val) {
this.val = val;
}
}
|
访问节点操作
1
2
3
|
void visit(BinaryTreeNode node) {
System.out.print(node.val + " ");
}
|
二叉树节点数目
- 如果是空树:返回0
- 如果不是空树:节点数 = (左子树节点数)+(右子数节点数) + 1
1
2
3
4
5
6
|
int TreeNodeCount(BinaryTreeNode root) {
if (root == null) {
return 0;
}
return TreeNodeCount(root.left) + TreeNodeCount(root.right) + 1;
}
|
求二叉树深度
- 如果是空树:返回0
- 如果不是空树:深度 = Max(左子树深度,右子树深度) + 1
1
2
3
4
5
6
7
8
|
int TreeDepth(BinaryTreeNode root) {
if (root == null) {
return 0;
}
int leftDepth = TreeDepth(root.left);
int rightDepth = TreeDepth(root.right);
return leftDepth > rightDepth ? (leftDepth + 1) : (rightDepth + 1);
}
|
前序遍历
- 如果是空树:return
- 如果不是空树:根->左->右
1
2
3
4
5
6
7
8
|
void preOrderTraverse(BinaryTreeNode root) {
if (root == null) {
return;
}
visit(root); //访问根节点
preOrderTraverse(root.left); //前序遍历左子树
preOrderTraverse(root.right); //前序遍历右子树
}
|
非递归算法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
void preOrderByStack(Node head) {
if (head == null) {
return;
}
Stack<Node> stack = new Stack<>();
Node cur = head;
while (!stack.isEmpty() || cur != null) {
while (cur != null) {
System.out.print(cur.val + " "); //如果要改为中序遍历, 只用将这行移到 cur=stack.pop(); 后面
stack.push(cur);
cur = cur.left;
}
if (!stack.isEmpty()) {
cur = stack.pop();
cur = cur.right;
}
}
}
|
中序遍历
- 如果是空树:return
- 如果不是空树:左->根-右
1
2
3
4
5
6
7
8
|
void inOrderTraverse(BinaryTreeNode root) {
if (root == null) {
return;
}
inOrderTraverse(root.left); //中序遍历左子树
visit(root); //访问根节点
inOrderTraverse(root.right); //中序遍历右子树
}
|
后序遍历
- 如果是空树:return
- 如果不是空树:左->右->根
1
2
3
4
5
6
7
8
|
void postOrderTraverse(BinaryTreeNode root) {
if (root == null) {
return;
}
postOrderTraverse(root.left); //后序遍历左子树
postOrderTraverse(root.right); //后序遍历右子树
visit(root); //访问根节点
}
|
层序遍历(从上到下,从左到右)
- 使用队列实现:
- 队列初始化:将根节点入队
- 当队列不为空:弹出一个节点,访问,若左节点或右节点不为空,将其入队
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
void levelTraverse(BinaryTreeNode root){
if (root == null) {
return;
}
Queue<BinaryTreeNode> queue = new ArrayDeque<>();
queue.add(root);
while (!queue.isEmpty()) {
BinaryTreeNode node = queue.poll();
visit(node);
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
}
}
|
数组版
1
2
3
4
5
6
7
8
9
10
11
|
def level_tranvel(root):
row=[root]
while row:
new_row=[]
for item in row:
print(item.data)
if item.left:
new_row.append(item.left)
if item.right:
new_row.append(item.right)
row = new_row
|
队列版
1
2
3
4
5
6
7
8
9
10
|
def level_tranvel(root):
if not root:
return
que = deque()
que.append(root)
while len(que)>0:
node = que.popleft()
print(node.data)
if node.left: que.append(node.left)
if node.right: que.append(node.right)
|
重建二叉树
根据前序遍历和中序遍历的结果重建二叉树
通过前序遍历的第一个元素为树的根找到根节点,然后在中序遍历中找到根节点的位置就能确定树的左右子树的节点数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
BinaryTreeNode reConstructBinaryTree(int[] pre, int[] in) {
if (pre == null || in == null || pre.length <= 0 || in.length <= 0) {
return null;
}
//储存根节点
BinaryTreeNode root = new BinaryTreeNode(pre[0]);
int rootPositionInOrder = -1;
//查找根节点在中序遍历的位置
for (int i = 0; i < in.length; i++) {
if (root.val == in[i]) {
rootPositionInOrder = i;
break;
}
}
if (rootPositionInOrder == -1) {
return null;
}
//确定左子树节点数
int numOfLeft = rootPositionInOrder;
//存储左子树前序遍历结果
int[] leftPre = new int[numOfLeft];
for (int i = 0; i < numOfLeft; i++) {
leftPre[i] = pre[i + 1];
}
//储存左子树中序遍历结果
int[] leftIn = new int[numOfLeft];
for (int i = 0; i < numOfLeft; i++) {
leftIn[i] = in[i];
}
//重建左子树
root.left = reConstructBinaryTree(leftPre, leftIn);
//确定右子树节点数
int numOfRight = in.length - numOfLeft - 1;
//储存右子树前序遍历结果
int[] rightPre = new int[numOfRight];
for (int i = 0; i < numOfRight; i++) {
rightPre[i] = pre[i + numOfLeft + 1];
}
//储存右子树中序遍历结果
int[] rightIn = new int[numOfRight];
for (int i = 0; i < numOfRight; i++) {
rightIn[i] = in[i + numOfLeft + 1];
}
//重建右子树
root.right = reConstructBinaryTree(rightPre, rightIn);
return root;
}
|