0% found this document useful (0 votes)
16 views89 pages

基础班 10 Tree & Graph

Uploaded by

susij
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
16 views89 pages

基础班 10 Tree & Graph

Uploaded by

susij
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 89

Tree & Graph

1
Tree

2
What is tree?
A tree data structure can be defined recursively (locally) as a
collection of nodes (starting at a root node), where each
node is a data structure consisting of a value, together with a
list of references to nodes (the "children"), with the
constraints that no reference is duplicated, and none points
to the root.

3
What is tree?
A tree data structure can be defined recursively (locally) as a
collection of nodes (starting at a root node), where each
node is a data structure consisting of a value, together with a
list of references to nodes (the "children"), with the
constraints that no reference is duplicated, and none points
to the root.

4
A data structure made up of nodes or vertices and directed
edges without having any cycle.

5
A data structure made up of nodes or vertices and directed
edges without having any cycle.

5
Types of Tree

RB Tree AVL B Tree

BST
Binary Tree Trie Tree
Tree

6
When to Use Tree
Simulating a hierarchical tree structure
File System, HTML, Compiler Pattern Recognition,
etc.
Simulating search space for solutions
DFS, BFS, Decision Tree, etc.
Performance Improvement
Red Black Tree, AVL, B/B+ Tree, etc.

7
Terminologies
Node
A
Root, Leaf (external node)
Relations
Parent, Child B C
Siblings
Ancestor, Descendant D E F G
Subtree
H I J

8 . 1
Terminologies
Edge (N - 1)
Path A
Height
Depth B C
Level

D E F G

H I J

8 . 2
Node
The depth of a node is the number of edges from
the node to the tree's root node.
A root node will have a depth of 0.
The height of a node is the number of edges on
the longest path from the node to a leaf.
A leaf node will have a height of 0.

Tree
The height of a tree would be the height of its root node,
or equivalently, the depth of its deepest node.
Note that depth doesn't make sense for a tree.

height depth level of a tree


8 . 3
Node
The depth of a node is the number of edges from
the node to the tree's root node.
A root node will have a depth of 0.
The height of a node is the number of edges on
the longest path from the node to a leaf.
A leaf node will have a height of 0.

Tree
The height of a tree would be the height of its root node,
or equivalently, the depth of its deepest node.
Note that depth doesn't make sense for a tree.
what is the max number of nodes a tree can have if the height of the tree is h?
height depth level of a tree
8 . 3
Binary Tree
Each node has at most two children.
left child, right child.
left subtree, right subtree

9
Types of Binary Tree
Complete Binary Tree
In which every level, except possibly the
last, is completely filled, and all nodes
are as far left as possible.
High Performance
Full Binary Tree
Perfect Binary Tree

10
Properties of Binary Tree
At Level i, at most 2^i nodes
A tree with height k, at most ceil(2^(k+1))-1 nodes
Complete binary tree
With n nodes, the height will be log2 (n + 1) − 1
number nodes from the root, then for node k, its
children would be 2*k+1 and 2*k + 2

11
Binary Tree in Code
class TreeNode {
int val;
TreeNode left;
TreeNode right;

public TreeNode(int val_) {


val = val_;
left = null;
right = null;
}
}

12
Binary Tree in Code
class Solution {
// Please implement this function.
public void function(TreeNode root);
}

13
Traversal of a Binary Tree
Traversal is the basic operation for almost all binary tree
problems.
Breadth First Search
LevelOrder
Depth First Search
PreOrder, InOrder, PostOrder

14
Traversal of a Binary Tree
Traversal is the basic operation for almost all binary tree
problems.
Breadth First Search
LevelOrder
Depth First Search
PreOrder, InOrder, PostOrder
BFS: search level by level (increasing
distance).
DFS: search as far as possible for one
direction.

14
Traversal of a Binary Tree
Traversal is the basic operation for almost all binary tree
problems.
Breadth First Search
LevelOrder
Depth First Search Parent Node

PreOrder, InOrder, PostOrder

15
BFS of a Binary Tree
A

B C

D E F G

H I J

16 . 1
BFS of a Binary Tree
A
LevelOrder: A B C D E F G H I J
B C

D E F G

H I J

16 . 1
DFS of a Binary Tree
A

B C

D E F G

H I J

16 . 2
DFS of a Binary Tree
A
PreOrder: A B D E H I C F G J
B C

D E F G

H I J

16 . 2
DFS of a Binary Tree
A
PreOrder: A B D E H I C F G J
B C
InOrder: D B H E I A F C G J

D E F G

H I J

16 . 2
DFS of a Binary Tree
A
PreOrder: A B D E H I C F G J
B C
InOrder: D B H E I A F C G J

PostOrder: D H I E B F J G C A D E F G

H I J

16 . 2
How to traverse (DFS)?
Tree is a recursive data structure.
It's natural and straightforward to use recursion on such
data structures (like LinkedList)
public void traverse(ListNode head) { public void traverse(TreeNode root) {
visit(head); visit(root);
traverse(head.next); traverse(root.left);
} traverse(root.right);
}

17
PreOrder Traversal
public void preorder(TreeNode root) {
if(root != null) {
// Visit the node by printing the node data
System.out.printf("%d ",root.val);
preorder(root.left);
preorder(root.right);
}
}

18 . 1
InOrder Traversal
public void inorder(TreeNode root) {
if(root != null) {
inorder(root.left);
System.out.printf("%d ",root.val);
inorder(root.right);
}
}

18 . 2
PostOrder Traversal
public void postorder(TreeNode root) {
if(root != null) {
postorder(root.left);
postorder(root.right);
System.out.printf("%d ",root.val);
}
}

18 . 3
How to traverse (BFS)?
We can't visit each node once we meet them. Need to store
some node for future visit.
Queue will be needed to keep the order

19
LevelOrder Traversal
public void levelorder(TreeNode root) { // BFS
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);

while (!queue.isEmpty()) {
TreeNode top = queue.pop();
System.out.printf("%d ", top.val);
if (top.left != null) {
queue.offer(top.left);
}
if (top.right != null) {
queue.offer(top.right);
}
}
return;
}

20 . 1
LevelOrder Traversal
public void levelorder(TreeNode root) { // BFS
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
int level = 0;
while (!queue.isEmpty()) {
System.out.printf("Level %d\n", level++);
Queue<TreeNode> queue2 = new LinkedList<>();
while (!queue.isEmpty()) {
TreeNode top = queue.poll();
System.out.printf("%d ", top.val);
if (top.left != null) queue2.offer(top.left);
if (top.right != null) queue2.offer(top.right);
}
queue = queue2;
}
}

20 . 2
LevelOrder Traversal
public void levelorder(TreeNode root) { // BFS
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
queue.offer(null);
int level = 0;
while (!queue.isEmpty()) {
TreeNode top = queue.poll();
if (top == null) {
System.out.printf("----Level %d\n", level++);
queue.offer(null);
} else {
System.out.printf("%d ", top.val);
if (top.left != null) queue.offer(top.left);
if (top.right != null) queue.offer(top.right);
}
}
}

20 . 3
LevelOrder Traversal
public void levelorder(TreeNode root) { // BFS
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
int level = 0;
int curLevelNum = 1;
while (!queue.isEmpty()) {
System.out.printf("Level %d\n", level++);
int nextLevelNum = 0;
while (curLevelNum-- != 0) {
TreeNode top = queue.poll();
System.out.printf("%d ", top.val);
if (top.left != null) {
queue.offer(top.left);
nextLevelNum++;
}
if (top.right != null) {
queue.offer(top.right);
nextLevelNum++;
}
}
curLevelNum = nextLevelNum;
}
}

20 . 4
Maximum Depth of Binary Tree
Given a binary tree, find its maximum depth.
The maximum depth is the number of nodes along the longest path
from the root node down to the farthest leaf node.

21 . 1
Maximum Depth of Binary Tree
Given a binary tree, find its maximum depth.
The maximum depth is the number of nodes along the longest path
from the root node down to the farthest leaf node.

public int maxDepth(TreeNode root) {


if (root == null) return 0;
int leftDepth = maxDepth(root.left);
int rightDepth = maxDepth(root.right);
return Math.max(leftDepth, rightDepth) + 1;
}

21 . 2
Maximum Depth of Binary Tree
Given a binary tree, find its maximum depth.
The maximum depth is the number of nodes along the longest path
from the root node down to the farthest leaf node.

public int maxDepth(TreeNode root) {


if (root == null) return 0;
return Math.max(maxDepth(root.left),
maxDepth(root.right)) + 1;
}

21 . 3
Minimum Depth of Binary Tree
Given a binary tree, find its minimum depth.
The minimum depth is the number of nodes along the shortest
path from the root node down to the nearest leaf node.

22 . 1
Minimum Depth of Binary Tree
Given a binary tree, find its minimum depth.
The minimum depth is the number of nodes along the shortest
path from the root node down to the nearest leaf node.
public int minDepth(TreeNode root) {
if (root == null) return 0;
int leftDepth = minDepth(root.left);
int rightDepth = minDepth(root.right);
return Math.min(leftDepth, rightDepth) + 1;
}

22 . 2
Minimum Depth of Binary Tree
Given a binary tree, find its minimum depth.
The minimum depth is the number of nodes along the shortest
path from the root node down to the nearest leaf node.
public int minDepth(TreeNode root) {
if (root == null) return 0;
int leftDepth = minDepth(root.left);
int rightDepth = minDepth(root.right);
return Math.min(leftDepth, rightDepth) + 1;
}

Wrong Answer

22 . 2
Minimum Depth of Binary Tree
Given a binary tree, find its minimum depth.
The minimum depth is the number of nodes along the shortest
path from the root node down to the nearest leaf node.
public int minDepth(TreeNode root) {
if (root == null) return 0; A
int leftDepth = minDepth(root.left);
int rightDepth = minDepth(root.right);
return Math.min(leftDepth, rightDepth) + 1;
}
B
Wrong Answer
C

22 . 3
Minimum Depth of Binary Tree
Given a binary tree, find its minimum depth.
The minimum depth is the number of nodes along the shortest
path from the root node down to the nearest leaf node.
public int minDepth(TreeNode root) {
if (root == null) { A
return 0;
}
if (root.left == null && root.right == null) {
return 1;
}
if (root.left == null && root.right != null) {
B
return minDepth(root.right) + 1;
}
if (root.left != null && root.right == null) {

}
return minDepth(root.left) + 1;
C
return Math.min(minDepth(root.left),
minDepth(root.right)) + 1;
}

22 . 4
Minimum Depth of Binary Tree
Given a binary tree, find its minimum depth.
The minimum depth is the number of nodes along the shortest
path from the root node down to the nearest leaf node.
public int minDepth(TreeNode root) {
if (root == null) { A
return 0;
}
int leftDepth = minDepth(root.left);
int rightDepth = minDepth(root.right);
if (leftDepth == 0) {
return rightDepth + 1;
B
} else if (rightDepth == 0) {
return leftDepth + 1;
}

}
return Math.min(leftDepth, rightDepth) + 1;
C

22 . 5
Minimum Depth of Binary Tree
public int minDepth(TreeNode root) {
if (root == null) return 0;
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(root);
int minDepth = 1;
while (!queue.isEmpty()) {
Queue<TreeNode> queue2 = new LinkedList<TreeNode>();
while (!queue.isEmpty()) {
TreeNode top = queue.poll();
if (top.left == null && top.right == null) {
return minDepth;
}
if (top.left != null) {
queue2.offer(top.left);
}
if (top.right != null) {
queue2.offer(top.right);
}
}
minDepth++;
queue = queue2;
}
return minDepth;
}

22 . 6
Same Tree
Given two binary trees, write a function to check if they are equal
or not.
Two binary trees are considered equal if they are structurally
identical and the nodes have the same value.

23 . 1
Same Tree
Given two binary trees, write a function to check if they are equal
or not.
Two binary trees are considered equal if they are structurally
identical and the nodes have the same value.

Base case: one of the roots is null.


Recursion rules for isSame(root1, root2)
root1.val = root2.val
isSame(root1.left, root2.left)
isSame(root1.right, root2.right)

23 . 2
Same Tree
Given two binary trees, write a function to check if they are equal
or not.
Two binary trees are considered equal if they are structurally
identical and the nodes have the same value.
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p == null && q == null) {
return true;
} else if (p == null || q == null) {
return false;
}
return p.val == q.val
&& isSameTree(p.left, q.left)
&& isSameTree(p.right, q.right);
}

23 . 3
Symmetric Tree
Given a binary tree, check whether it is a mirror of itself (ie,
symmetric around its center).

1 1 1 1
/ \ / \ / \ / \
2 2 2 2 2 2 2 2
/ \ / \ / \ / \ \ \ / \
3 4 4 3 4 3 4 3 3 3 3 3
True False False True

24 . 1
Symmetric Tree
Given a binary tree, check whether it is a mirror of itself (ie,
symmetric around its center).

Root is Symmetric 1 1
/ \ / \
root.left is symmetric to root.right
2 2 2 2
A is symmetric to B \ \ / \
A.val == B.val 3 3 3 3
A.left is symmetric to B.right False True
A.right is symmetric to B.left

24 . 2
Symmetric Tree
public boolean isSymmetric(TreeNode root) {
if (root == null) {
return true;
}
return isSymmetric(root.left, root.right);

}
public boolean isSymmetric(TreeNode left, TreeNode right) {
if (left == null && right == null) {
return true;
}
if (left == null || right == null) {
return false;
}
return left.val == right.val
&& isSymmetric(left.left, right.right)
&& isSymmetric(left.right, right.left);
}

24 . 3
Path Sum
Given a binary tree and a sum, determine if the tree has a root-to-
leaf path such that adding up all the values along the path equals
the given sum.

5 Sum: 22 --> True


/ \ (5 - 4 - 11 - 2)
4 8
/ / \
11 13 4
/ \ \
7 2 1

25 . 1
Path Sum
Given a binary tree and a sum, determine if the tree has a root-to-
leaf path such that adding up all the values along the path equals
the given sum.

5 Except picking from all of numbers, only


/ \ path from root to leaf is acceptable.
4 8 hasSum(TreeNode root, int sum)
/ / \
Base case: root is leaf.
11 13 4
hasSum(root, sum) = hasSum(root.left,
/ \ \
7 2 1 sum-root.val) || hasSum(root.right,
sum-root.val)

25 . 2
Path Sum
Given a binary tree and a sum, determine if the tree has a root-to-
leaf path such that adding up all the values along the path equals
the given sum.

5 public boolean hasPathSum(TreeNode root, int sum) {


if (root == null) {
/ \ }
return false;

4 8 if (root.left == null && root.right == null) {


if (sum == root.val) {
/ / \ return true;
}
11 13 4 return false;
}
/ \ \ return hasPathSum(root.left, sum - root.val) ||
hasPathSum(root.right, sum - root.val);
7 2 1 }

25 . 3
Path Sum II
Given a binary tree and a sum, find all root-to-leaf paths
where each path's sum equals the given sum.

25 . 4
public List<List<Integer>> pathSum(TreeNode root, int sum) {
List<List<Integer>> results = new ArrayList<>();
pathSum(results, new ArrayList<Integer>(), root, sum);
return results;
}

private void pathSum(List<List<Integer>> results,


List<Integer> path, TreeNode root, int sum){
if (root == null) {
return;
}
sum -= root.val;
if (root.left == null && root.right == null) {
if (sum == 0){
path.add(root.val);
results.add(new ArrayList<Integer>(path));
path.remove(path.size() - 1);
}
return;
}

path.add(root.val);
pathSum(results, path, root.left, sum);
pathSum(results, path, root.right, sum);
path.remove(path.size() - 1);
}

25 . 5
Binary Search Tree
30

18 34

13 24 31 40

22 27 47

visualization 26
Binary Search Tree
All subtrees are BST
All elements in left sub-tree is small than root
All elements in Right sub-tree is larger than root
If we do InOrder traversal, the result of BST is a
sorted array

27
Binary Search Tree
Find
Add
Remove

28
Binary Search Tree - Find
30
24: 30 -> 18 -> 24 -> true
42: 30 -> 34 -> 40 -> 47 -> false
18 34

13 24 31 40

22 27 47

29 . 1
Binary Search Tree - Find
public boolean find(int value, TreeNode root) {
TreeNode cur = root;
while(cur != null) {
if (val == cur.value) {
return true;
}
if (value < cur.val) {
cur = cur.leftNode;
} else {
cur = cur.rightNode;
}
}
return false;
}

29 . 2
Binary Search Tree - Find
public boolean find(int value, TreeNode root) {
TreeNode cur = root;
while(cur != null) {
if (val == cur.value) {
return true;
}
if (value < cur.val) {
cur = cur.leftNode;
} else {
cur = cur.rightNode;
}
}
return false;
} O(logN)

29 . 2
Binary Search Tree - Add
30
Add 42
30 -> 34 -> 40 -> 47,
18 34
doesn't exist.
Add 42 to 47's left.
13 24 31 40

22 27 47

30 . 1
Binary Search Tree - Add
30
Add 42
30 -> 34 -> 40 -> 47,
18 34
doesn't exist.
Add 42 to 47's left.
13 24 31 40

22 27 47

42

30 . 2
Binary Search Tree - Add
public boolean add(int value, TreeNode root) {
if (root == null) {
root = new TreeNode(value);
return true;
}
TreeNode cur = root;
while (cur != null) {
if (cur.val == value) {
return false;
}
if (value < cur.val) {
if (cur.leftNode != null) {
cur = cur.leftNode;
} else {
cur.leftNode = new TreeNode(value);
return true;
}
} else {
if (cur.rightNode != null) {
cur = node.rightNode;
} else {
cur.rightNode = new TreeNode(value);
return true;
}
}
}
return false;
}
30 . 3
Binary Search Tree - Add
public boolean add(int value, TreeNode root) {
if (root == null) {
root = new TreeNode(value);
return true;
}
TreeNode cur = root;
while (cur != null) {
if (cur.val == value) {
return false;
}
if (value < cur.val) {
if (cur.leftNode != null) {
cur = cur.leftNode;
} else {
cur.leftNode = new TreeNode(value);
return true;
}
} else {
if (cur.rightNode != null) {
cur = node.rightNode;
} else {
cur.rightNode = new TreeNode(value);
return true;
}
}
}
return false;
} O(logN)
30 . 3
Binary Search Tree - Remove
30
Remove 27
30 -> 18 -> 24 -> 27, exist,
18 34
Remove
Remove 30 ?
13 24 31 40

22 27 47

42

31 . 1
Binary Search Tree - Remove
Remove one TreeNode Q
If the node Q is a leaf
If the node Q has one child R
the child is left child
the child is right child
If the node Q has two children R1, R2

31 . 2
Binary Search Tree - Remove
P P P P

Q Q Q Q

R R R R

31 . 3
Binary Search Tree - Remove
P P P P

Q Q Q Q

R R R R

P<R<Q P<Q<R R<Q<P Q<R<P

31 . 3
Binary Search Tree - Remove
P P P P

Q Q Q Q

R R R R

P<R<Q P<Q<R R<Q<P Q<R<P

Just use R to replace Q


31 . 3
Binary Search Tree - Remove
P
If we remove Q, which is the
best substitute?
Q

R1 R2

31 . 4
Binary Search Tree - Remove
P
If we remove Q, which is the
best substitute?
Q
The one before Q and
after Q in InOrder
R1 R2 Traversal.

31 . 5
Binary Search Tree - Remove
P
If we remove Q, which is the
best substitute?
Q
The one before Q and
after Q in InOrder
R1 R2 Traversal.

31 . 5
public static boolean remove(int value, Node root) {
if(root == null) return false;
if(root.data == value) {
root = removeNode(root);
return true;
}
Node node = root;
while(node != null) {
if(node.data > value) {
if(node.leftNode != null && node.leftNode.data != value) {
node = node.leftNode;
}
else if(node.leftNode == null) return false;
else {
node.leftNode = removeNode(node.leftNode);
return true;
}
}
else if(node.data < value) {
if(node.rightNode != null && node.rightNode.data != value) {
node = node.rightNode;
}
else if(node.rightNode == null) return false;
else {
node.rightNode = removeNode(node.rightNode);
return true;
}
}
else return false;
}
return false;
}

31 . 6
public static Node removeNode(Node node) {
if(node.leftNode == null && node.rightNode == null) {
return null;
}
else if(node.leftNode == null) {
return node.rightNode;
}
else if(node.rightNode == null) {
return node.leftNode;
}
else {
node.data = findAndRemove(node);
return node;
}
}

public static int findAndRemove(Node node) {


int result;
if(node.leftNode.rightNode == null) {
result = node.leftNode.data;
node.leftNode = node.leftNode.leftNode;
return result;
}
node = node.leftNode;
while(node.rightNode.rightNode != null) {
node = node.rightNode;
}
result = node.rightNode.data;
node.rightNode = node.rightNode.leftNode;
return result;
}

31 . 7
Binary Search Tree (*)
30 30

18 34 18 40

13 24 31 40 13 24 34 43

22 27 47 22 27 31 42 47

42
43
32
Binary Search Tree (*)
We know the search time is highly related to the height of
the tree. If we keep add and remove elements in the tree, the
tree will become unbalanced.

So we have Red-black tree and AVL tree, they could use


rotation and reconstruct to make the tree balance.

33
Types of Tree

RB Tree AVL B Tree

BST
Binary Tree Trie Tree
Tree

34
Graph

35
What is graph?
A graph data structure consists of a finite (and possibly
mutable) set of vertices or nodes or points, together with a set
of unordered pairs of these vertices for an undirected graph
or a set of ordered pairs for a directed graph.
These pairs are known as edges, arcs, or lines for an
undirected graph and as arrows, directed edges, directed arcs,
or directed lines for a directed graph.

36
Types of Graph
Undirected graph
Directed graph

37 . 1
Types of Graph
Directed graph
Directed Acylic Graph

37 . 2
Types of Graph
Directed graph
Directed Acylic Graph
DFS
Topological Sort

37 . 3
Graph Representation
GraphNode
There is no root in the graph
Need multiple nodes to represent a graph

class GraphNode {
int val;
List<GraphNode> neighbors;
}

38 . 1
Graph Representation
Adjacent matrices
|V| vertices, then |V|*|V| matrix of 0s and 1s for
the graph.

1 1 1
1 1
1 1
1
1 1

38 . 2
Graph Representation
Adjacent lists
|V| vertices, then |V| arraylist, each containing the
adjacent vertices.
2|E| space for undirected, and |E| space for
directed.
0: 1 2 3 5
1: 2 4
2: 3 5 6 7 8

38 . 3
Graph Traversal
DFS, BFS
Similar to Tree Traversal
There could be cycles in graph, so need to mark
nodes visited after visiting. Different from tree here.
3 states: not visited, visiting, visited

39
Homework (Optional)
Validate Binary Search Tree
Binary Tree Zigzag Level Order Traversal
Binary Tree Maximum Path Sum
Flatten Binary Tree To Linked List
Construct Binary Tree from Inorder and Postorder Traversal
Construct Binary Tree from Preorder and Inorder Traversal

40

You might also like