Binary Tree ADT and Tree Node ADT: Page 1 of 61

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 61

Binary Tree ADT and Tree Node ADT

public interface TreeNode {


public String getNodeKey();
public boolean equalTo(TreeNode N);
}

public interface BinaryTree {


public TreeNode root();
public BinaryTree leftSubtree();
public BinaryTree rightSubtree();
public boolean isEmpty();
public boolean equalTo(BinaryTree t);
}

Page 1 of 61
Tree Node ADT and Its Implementations

public interface TreeNode {


public String getNodeKey();
public boolean equalTo(TreeNode N);
}

Implementations:

public class OrdinaryTreeNode implements TreeNode {



}
public class SpecialErrTreeNode implements TreeNode {

}

Page 2 of 61
Binary Tree ADT and Its Implementations

public interface BinaryTree {


public TreeNode root();
public BinaryTree leftSubtree();
public BinaryTree rightSubtree();
public boolean isEmpty();
public boolean equalTo(BinaryTree t);
}

Implementations:

public class EmptyBinaryTree implements BinaryTree { … }

public class NonemptyBinaryTree implements BinaryTree { … }

Page 3 of 61
Binary Tree ADT and Its Implementations

public class EmptyBinaryTree implements BinaryTree { … }


public class NonemptyBinaryTree implements BinaryTree { … }

t1
TreeNode n1;
BinaryTree t1, t2, t3, t4;
n1
… t2
t1 = new EmptyBinaryTree();
… t3 t4
t2 = new NonemptyBinaryTree(n1, t3, t4);

Page 4 of 61
Binary Tree ADT and Its Implementations

public class EmptyBinaryTree implements BinaryTree { … }


public class NonemptyBinaryTree implements BinaryTree { … }

t1
TreeNode n1;
BinaryTree t1, t2; t2 n1


t1 = new EmptyBinaryTree();
t2 = new NonemptyBinaryTree(n1,
new EmptyBinaryTree(),new EmptyBinaryTree());

Page 5 of 61
Binary Search Trees
0123849
John/NA/CSC
 Key values are
unique.
 At every node,
0114938 0150957
Mary/CC/CEG May/NA/IEG
the key value
must be
greater than all
the keys in the
0120739 0147723 0160039
Tom/SC/INE Sue/UC/IDE Will/CC/CSC
left subtree,
and less than
all the keys in
0120730 0134219 0170980 the right
Jack/SC/ELE Ben/CC/ACE Bob/UC/SEG subtree.
Page 6 of 61
How are Binary Search Trees constructed?

Page 7 of 61
Constructing a Binary Search Tree

0123849

0123849

Empty tree Tree with one node

“Obtain a tree with a node inserted into an empty tree”

Page 8 of 61
Constructing a Binary Search Tree

0123849

0123849

Empty tree Tree with one node

“Obtain a tree with a node inserted into an empty tree”

Page 9 of 61

BinaryTree t1, t2;
TreeNode n1;

n1 = new OrdinaryTreeNode(…);

t1 = new EmptyBinaryTree();
t2 = t1.insertNode(n1);

Page 10 of 61
public interface TreeNode {
public String getNodeKey();
}

public interface BinaryTree {


public TreeNode root();
public BinaryTree leftSubtree();
public BinaryTree rightSubtree();
public boolean isEmpty();
public boolean equalTo(BinaryTree t);

/* new */ public BinaryTree insertNode(TreeNode N);

Page 11 of 61
Constructing a Binary Search Tree
0123849
0114938

0114938

Page 12 of 61
Constructing a Binary Search Tree
0123849
0120739

0114938

0120739

Page 13 of 61
Constructing a Binary Search Tree
0123849
0150957

0114938 0150957

0120739

Page 14 of 61
Constructing a Binary Search Tree
0123849
0160039

0114938 0150957

0120739 0160039

Page 15 of 61
and so on …

Page 16 of 61
Now, another viewpoint of node insertion.

Page 17 of 61
Constructing a Binary Search Tree

0120730

0123849
0120730

0114938 0150957

0120739 0147723 0160039

Page 18 of 61
Constructing a Binary Search Tree
0123849
0120730 0120730

0114938 0150957

0120739 0147723 0160039

Page 19 of 61
Constructing a Binary Search Tree
0123849
0120730

0114938 0150957

0120730

0120739 0147723 0160039

Page 20 of 61
Constructing a Binary Search Tree
0123849
0120730

0114938 0150957

0120739 0147723 0160039

0120730

Page 21 of 61
Constructing a Binary Search Tree
0123849
0120730

0114938 0150957

0120739 0147723 0160039

0120730

Page 22 of 61
/* For EmptyBinaryTree Class */

public class EmptyBinaryTree implements BinaryTree {



public BinaryTree insertNode(TreeNode n) {


return new NonemptyBinaryTree(n,
new EmptyBinaryTree(),
new EmptyBinaryTree());
}

Page 23 of 61
public class EmptyBinaryTree implements BinaryTree {
Note …
public BinaryTree insertNode(TreeNode n){
return new NonemptyBinaryTree(n,
new EmptyBinaryTree(),
 /* For */ }
new EmptyBinaryTree());

/* EmptyBinaryTree */ }

return new NonemptyBinaryTree(n,


new EmptyBinaryTree(),
new EmptyBinaryTree()));

0123849

0123849

Page 24 of 61 Empty tree Tree with one node


/* For NonemptyBinaryTree Class */
public class NonemptyBinaryTree implements BinaryTree {

public BinaryTree insertNode(TreeNode n) {
int sign = n.getNodeKey().compareTo(this.root().getNodeKey());
if (sign == 0)
return new NonemptyBinaryTree(n,
this.leftSubtree(), this.rightSubtree());
if (sign < 0)
return new NonemptyBinaryTree(this.root(),
this.leftSubtree().insertNode(n), this.rightSubtree());
return new NonemptyBinaryTree(this.root(),
this.leftSubtree(), this.rightSubtree().insertNode(n));
}
}

Page 25 of 61
 int sign = n.getNodeKey().compareTo(this.root().getNodeKey());
if (sign == 0) return new NonemptyBinaryTree(n, L, R));
if (sign < 0) return new NonemptyBinaryTree(r, L', R);
return new NonemptyBinaryTree(r, L, R'));
0123849

0114938 0150957

public class NonemptyBinaryTree implements BinaryTree {



0120739 0147723 0160039 public BinaryTree insertNode(TreeNode n) {
int sign = n.getNodeKey().compareTo(this.root().getNodeKey());
if (sign == 0) return new NonemptyBinaryTree(n,
this.leftSubtree(), this.rightSubtree());
if (sign < 0) return new NonemptyBinaryTree(this.root(),
this.leftSubtree().insertNode(n), this.rightSubtree());
0120730 return new NonemptyBinaryTree(this.root(),
this.leftSubtree(), this.rightSubtree().insertNode(n));
}
}
Page 26 of 61
BinaryTree method: findMinNode

0123849  Tree is nonempty:


 Left subtree
exists: find in
0114938 0150957
the left subtree
 Left subtree
does not exist:
0120739 0147723 0160039
root is the min
node!
0120730
 Tree is empty:
error.

Page 27 of 61
public interface BinaryTree {
public TreeNode root();
public BinaryTree leftSubtree();
public BinaryTree rightSubtree();
public boolean isEmpty();
public boolean equalTo(BinaryTree t);

public BinaryTree insertNode(TreeNode N);

/* new */ public TreeNode findMinNode();

Page 28 of 61
BinaryTree method: findMinNode

/* For NonemptyBinaryTree Class */

public class NonemptyBinaryTree implements BinaryTree {



 Tree is nonempty:
…  Left subtree
public TreeNode findMinNode() { exists: find in
the left
if (this.leftSubtree().isEmpty()) subtree
return this.root();  Left subtree
does not
return this.leftSubtree().findMinNode(); exist: root is
} the min node!

 Tree is empty:
} error.

Page 29 of 61
BinaryTree method: findMinNode

/* For EmptyBinaryTree Class */


public class EmptyBinaryTree implements BinaryTree {

…  Tree is nonempty:
 Left subtree
public TreeNode findMinNode() { exists: find in
return new SpecialErrTreeNode(); the left
subtree
}  Left subtree
does not
exist: root is
} the min node!

 Tree is empty:
error.

Page 30 of 61
BinaryTree method: Delete Node

0123849

0114938

0120739
 0150957

0147723 0160039

0120730

Page 31 of 61
public interface BinaryTree {
public TreeNode root();
public BinaryTree leftSubtree();
public BinaryTree rightSubtree();
public boolean isEmpty();
public boolean equalTo(BinaryTree t);

public BinaryTree insertNode(TreeNode N);


public TreeNode findMinNode();

/* new */ public BinaryTree deleteNode(TreeNode N);

Page 32 of 61
BinaryTree method: findMinNode

/* For EmptyBinaryTree Class */


public class EmptyBinaryTree implements BinaryTree {


public BinaryTree deleteNode(TreeNode N) {
throw new HeyException();
}

Page 33 of 61
BinaryTree method: Delete Node

0123849

0114938

0120739 0147723 0160039

0120730

Page 34 of 61
BinaryTree method: Delete Node

0123849

0114938

0120739 0147723 0160039

0120730

Page 35 of 61
BinaryTree method: Delete Node

Node deletion is not trivial!


Node deletion is hard!

Page 36 of 61
BinaryTree method: Delete Node
CASE 1

 If the node to be deleted is


NOT the root, then it is
easy.

1. Delete the node from


the left/right subtree.
2. Replace the subtree.

Page 37 of 61
BinaryTree method: Delete Node
CASE 2a

 If the node to be deleted IS


the root, and the root has
no child, then it is easy.

1. Return an empty binary


tree.

Page 38 of 61
BinaryTree method: Delete Node

 CASE 2b

If the node to be deleted IS


the root, and the root has
1 child, then it is easy.

1. Return the left/right


subtree.

Page 39 of 61
BinaryTree method: Delete Node

 CASE 2c

If the node to be deleted IS


the root, and the root has
2 children, then it is easy.

1. Find the node with the


smallest key in the
right subtree.
2. Delete it from the right
subtree.
3. Use it as the root.
Page 40 of 61
/* For NonemptyBinaryTree Class */
public BinaryTree deleteNode(TreeNode n) {
int sign = n.getNodeKey().compareTo(this.root().getNodeKey());

/* Case 1 */ if (sign<0) return new NonemptyBinaryTree(this.root(),


this.leftSubtree().deleteNode(n),
this.rightSubtree());
/* Case 1 */ if (sign>0) return new NonemptyBinaryTree(this.root(),
this.leftSubtree(),
this.rightSubtree().deleteNode(n));


Page 41 of 61
/* Case 2c */
if (!this.leftSubtree().isEmpty() && !this.rightSubtree().isEmpty()) {
TreeNode M = this.rightSubtree().findMinNode();
return new NonemptyBinaryTree(M,
this.leftSubtree(), this.rightSubtree().deleteNode(M));
};

Page 42 of 61
/* Cases 2a and 2b */
if (this.rightSubtree().isEmpty())
return this.leftSubtree();
else
return this.rightSubtree();
}

Page 43 of 61
/* For NonemptyBinaryTree Class */
public class NonemptyBinaryTree implements BinaryTree {

public BinaryTree deleteNode(TreeNode n) {
int sign = n.getNodeKey().compareTo(this.root().getNodeKey());
if (sign<0) return new NonemptyBinaryTree(this.root(),
this.leftSubtree().deleteNode(n), this.rightSubtree());
if (sign>0) return new NonemptyBinaryTree(this.root(),
this.leftSubtree(), this.rightSubtree().deleteNode(n));
if (!this.leftSubtree().isEmpty() && !this.rightSubtree().isEmpty()) {
TreeNode M = this.rightSubtree().findMinNode();
return new NonemptyBinaryTree(M,
this.leftSubtree(), this.rightSubtree().deleteNode(M));
};
if (this.rightSubtree().isEmpty())
return this.leftSubtree();
else
return this.rightSubtree();
}

Page 44 of 61
The Binary Tree ADT

As we have been doing, we define Binary Trees and Tree


Nodes to be Abstract Data Types.
ro o t

leftSubtree
findMinNode

Page 45 of 61
*
public interface TreeNode {
public String getNodeKey();
public boolean equalTo(TreeNode N);
}
public interface BinaryTree {
public TreeNode root();
public BinaryTree leftSubtree();
public BinaryTree rightSubtree();
public boolean isEmpty();
public boolean equalTo(BinaryTree t);
public BinaryTree insertNode(TreeNode N);
public TreeNode findMinNode();
public BinaryTree deleteNode(TreeNode N);
}

Page 46 of 61
How to implement the Tree Node ADT and the Binary Tree
ADT?.

Page 47 of 61
Implementation of the Tree Node ADT

We consider tree nodes with character strings as keys, and


objects as data.

public class OrdinaryTreeNode implements TreeNode {


private String key;
private Object contents;

}
0123849 "0123849"
(data)
(data)

Page 48 of 61
public class OrdinaryTreeNode implements TreeNode {
private String key;
private Object contents;
public OrdinaryTreeNode(String k, Object c) {
this.key = k; this.contents = c;
}
public String getNodeKey() {
return this.key;
}
public boolean equalTo(TreeNode N) {
return key.equals(N.getNodeKey());
/* Well, … */
} 0123849

} (data) "0123849"
Page 49 of 61
(data)
public class SpecialErrTreeNode implements TreeNode {

public String getNodeKey() {


throw new HeyException();
}

public boolean equalTo(TreeNode N) {


return N instanceof SpecialErrTreeNode;
}

Page 50 of 61
Implementation of the Binary Tree ADT

public class EmptyBinaryTree implements BinaryTree {

public TreeNode root() { throw new HeyException(); }


public BinaryTree leftSubtree() { throw new HeyException(); }
public BinaryTree rightSubtree() { throw new HeyException(); }

public boolean isEmpty() { return true; }


public boolean equalTo(BinaryTree t) { … }

public BinaryTree insertNode(TreeNode n) { … }


public BinaryTree deleteNode(TreeNode N) { … }
public TreeNode findMinNode() { … }

Page 51 of 61
Implementation of the Binary Tree ADT

A nonempty binary tree consists of three components: the


root, the left subtree, and the right subtree.

public class NonemptyBinaryTree implements BinaryTree {


private TreeNode Root;
private BinaryTree Left;
private BinaryTree Right;

}; L

L R
R

Page 52 of 61
Constructor for NonemptyBinaryTree

BinaryTree t1 = new NonemptyBinaryTree(n1, t1, t2);

public NonemptyBinaryTree(TreeNode N, BinaryTree L, BinaryTree R) {


this.Root = N;
this.Left = L; L R

this.Right = R;
}

L
L R
R

Page 53 of 61
public TreeNode root() {
return this.Root; L R
}

public BinaryTree leftSubtree() {


return this.Left;
}
L

public BinaryTree rightSubtree() { R

return this.Right;
}

public boolean isEmpty() {


return false;
}

Page 54 of 61
/* For EmptyBinaryTree Class */

public boolean equalTo(BinaryTree t) {


return t.isEmpty();
}

/* For NonemptyBinaryTree Class */

public boolean equalTo(BinaryTree t) {


if (t.isEmpty()) return false;
return this.root().equalTo(t.root()) &&
this.leftSubtree().equalTo(t.leftSubtree()) &&
this.rightSubtree().equalTo(t.rightSubtree());
}

Page 55 of 61
We now show the complete listing of the implementations.

Page 56 of 61
/* EmptyBinaryTree class */
public class EmptyBinaryTree implements BinaryTree {

public TreeNode root() {


throw new HeyException();
}
public BinaryTree leftSubtree() {
throw new HeyException();
}
public BinaryTree rightSubtree() {
throw new HeyException();
}
public boolean isEmpty() {
return true;
}

Page 57 of 61
public boolean equalTo(BinaryTree t) {
return t.isEmpty();
}
public BinaryTree insertNode(TreeNode n) {
return new NonemptyBinaryTree(n,
new EmptyBinaryTree(), new EmptyBinaryTree());
}
public BinaryTree deleteNode(TreeNode N) {
throw new HeyException();
}
public TreeNode findMinNode() {
return new SpecialErrTreeNode();
}

Page 58 of 61
/* NonemptyBinaryTree class */
public class NonemptyBinaryTree implements BinaryTree {

private TreeNode Root;


private BinaryTree Left;
private BinaryTree Right;

public NonemptyBinaryTree(TreeNode N, BinaryTree L, BinaryTree R) {


this.Root = N; this.Left = L; this.Right = R;
}

public TreeNode root() {


return this.Root;
}

Page 59 of 61
public BinaryTree leftSubtree() {
return this.Left;
}
public BinaryTree rightSubtree() {
return this.Right;
}
public boolean isEmpty() {
return false;
}
public boolean equalTo(BinaryTree t) {
if (t.isEmpty()) return false;
return this.root().equalTo(t.root()) &&
this.leftSubtree().equalTo(t.leftSubtree()) &&
this.rightSubtree().equalTo(t.rightSubtree());
}

Page 60 of 61
public BinaryTree insertNode(TreeNode n) {
… /* Please refer to the last lecture’s notes. */
}

public BinaryTree deleteNode(TreeNode n) {


… /* Please refer to the last lecture’s notes. */
}

public TreeNode findMinNode() {


… /* Please refer to the last lecture’s notes. */
}

Page 61 of 61

You might also like