Download binarytree

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
Tree.
A nonlinear data structure with a node identified as a root with 0 or
n children each of which is a tree.
www.inf.u-szeged.hu
Note that a tree definition is essentially a recursive one. We’ll
study generalized tree as a data structure later on.
Binary Tree.
A special case of Tree.
A binary tree is either an empty tree or a tree comprising a root
node, left subtree and a right subtree. Each node has a maximum of
two children.
This is an empty binary tree at right.
Some more binary trees:
Single node binary
tree.
Two-node binary
trees.
Seven-node binary
tree.
Note that this is not a binary tree.
Every binary tree can have at most two subtrees: left and right. The
notion of parent, children, grand-parent, grand-children. Basically,
parent
Left Child
Right child
Child
A tree, if it’s not empty, begins at a root which is at level 0. The
children of the root are at level 1, and their children are at the next
level, and so on.
Notion of Identity, Equality and Isomorphism.
Two structures are identical if they share the same memory space.
For instance, variable x and its alias n share the same address. If
we change one, the other one changes automatically.
Two items are equal if they have same value. But once one of them
is changed, their values will differ.
Two items are isomorphic if they have the same structure. The
structures do not have the same values, but they are structurally
same.
a
b
d
a
b
e
c
f
isomorphic
c
not isomorphic
How many structurally different types of binary trees are possible
with, say, n nodes?
If n  1, only one tree.
With n  2 , only two trees.
With
a.
b.
c.
n  3 , we could have the following possibilities.
root node + 2 nodes on its LST (Left-side tree)
root node + 2 nodes on its RST (right-side tree)
root node + 1 node on its LST and 1 on its RST
For (a), number of isomorphically distinct tress: 2
For (b), number of isomorphically distinct tress: 2
For (c), number of isomorphically distinct tress: 1
Total count of binary trees: 5
One could proceed in this way to find the count of possible
binary trees for an arbitrary n .
The height of a tree is the maximum level that any of its node
attains. Also, recursively,
height(tree) = 1 + max (height(tree.left), height(tree.right))
height (root) = 0
A complete binary tree is one where every node except those at
the deepest layer (level) has precisely two children.
Let n(h) = total number of nodes in a complete binary tree of
height h. Then,
n(0)  1
n(h)  1  2n(h  1)
This shows that
n(h)  1  21  2 2  23  ...  2 h
 2 h 1  1
From this, we conclude:
Shortest binary tree with n nodes packed into it (the bushiest
tree) is of height h , where
h  log 2 (n  1)  1
The tallest binary tree with n nodes would be the one of height
n  1. Therefore, the height of any other binary tree would be
bounded between these two limits:
log 2 (n  1)  1  height (binary _ tree)  n  1
Creating a binary tree
A binary tree could be created in any fashion we like so long no
node within the tree is allowed to have more than two children.
Binary search tree is created with the following constraints:
a. The left_child[key] < root[key]
b. The right_child[key] > root[key]
c. The left and right subtrees of the root are again
binary search trees.
Unless indicated otherwise, our binary trees are going to be created
as binary search trees.
Check textbook or any reference book how to insert nodes
(objects) in a binary (search) tree.
A typical TreeNode of a binary tree is a class
class bin_tree {
private:
// The basic node of a tree
structure node {
node *left;
node *right;
int item;
};
// The root where the tree starts
node *root;
// Insert a new node into the tree
void insert(node *root, int item);
// Traverse the tree in a preorder mode
void preorder (node *root);
// Traverse the tree in an inorder mode
void inorder (node *root);
// Traverse tree in a postorder mode
void postorder (node *root);
node* find_max(node *root);
public:
bin_tree() {root = NULL;}
~bin_tree() {delete root;}
node* this_root() const {return root;}
void traverse_preorder() {preorder(root);}
void traverse_inorder() {inorder(root);}
void traverse_postorder() {postorder(root);}
};
The method insert that inserts a node in the tree is
void insert_node (node* root, int x)
{
node* p = new node;
p->item = x;
p->left = NULL;
p->right = NULL;
if (!root)
root = p;
else
if (x < root->item)
insert_node (root->left, x);
else
if (x > root->item)
insert_node (root->right, x);
else
cout << "Duplicate entry" <<endl;;
}
Method of traversals. A traversal of a list or a tree is the
specification of the visit sequence of its nodes. In binary trees,
three major ways tree nodes could be visited are: (in pseudo codes)
Preorder_traversal ::
If (root !=null) {
print (root.data);
preorder_traversal(root.left);
preorder_traversal(root.right);
}
Inorder_traversal ::
If (root !=null) {
inorder_traversal(root.left);
print(root.data);
inorder_traversal(root.right);}
Postorder_traversal ::
If (root !=null) {
postorder_traversal(root.left);
postorder_traversal(root.right);
print(root.data);
}
Other traversals could also be designed and under some
circumstances they might offer more appeal.
Consider the following.
 A preorder traversal always lists the root node first.
 A postorder traversal always lists the root node last.
 An inorder traversal always pits the traversal of its left
subtree at the left of the root and the right subtree at its
right.
Consequently, a preorder listing and an inorder listing of the same
tree could be used to reconstruct the tree if it were not known a
priori.
The same could be achieved with
a. postorder listing
b. inorder listing
Binary tree code.
This program generates a set of integer random numbers which are
then inserted into a binary tree one by one. Duplicate keys are
dropped. The tree is finally traversed in Preorder, Inorder and
Postorder traversal schemes. (This is in java)
import java.io.*;
import java.util.*;
import java.lang.Math;
public class Tree {
class TreeNode {
TreeNode left;
int data;
TreeNode right;
public TreeNode (int d) {
data=d;
left=right=null;
}
public void insert(int d){
if (d <data){
if (left == null)
left = new TreeNode(d);
else
left.insert(d);
}
else
if (d > data) {
if (right == null)
right= new TreeNode(d);
else
right.insert(d);
}
}
}
/* Now that a TreeNode is defined, we are going to
build a binary tree.
*/
private TreeNode root;
/* Construct an empty binary tree at the root
*/
public Tree () {root=null;}
/* Insert a new node in the binary tree. If the
root node is null, create the root node now.
*/
public void insertNode (int d){
if (root == null)
root = new TreeNode(d);
else
root.insert(d);
}
private void inOrderDriver(TreeNode node){
if (node == null)
return;
else {
inOrderDriver(node.left);
System.out.print(" "+node.data+" -> ");
inOrderDriver(node.right);
}
}
private void preOrderDriver(TreeNode node){
if (node == null)
return;
else {
System.out.print(" "+node.data+" -> ");
preOrderDriver(node.left);
preOrderDriver(node.right);
}
}
private void postOrderDriver(TreeNode node){
if (node == null)
return;
else {
postOrderDriver(node.left);
postOrderDriver(node.right);
System.out.print(node.data+" -> ");
}
}
public void
inOrderTraversal(){inOrderDriver(root);}
public void
preOrderTraversal(){preOrderDriver(root);}
public void
postOrderTraversal(){postOrderDriver(root);}
public static void main(String args []){
Tree thisTree = new Tree();
int i, j, k;
for (i=0; i<10; i++){
j=(int)(100*Math.random());
System.out.print(j+" ");
thisTree.insertNode(j);
}
System.out.println("\n\n");
// Traversal routines
System.out.println("Try Inorder
traversal.\n\n");
thisTree.inOrderTraversal();
System.out.println("\n
*****************\n");
System.out.println("Try Preorder
traversal.\n\n");
thisTree.preOrderTraversal();
System.out.println("\n
*****************\n");
System.out.println("Try Postorder
traversal.\n\n");
thisTree.postOrderTraversal();
System.out.println("\n");
}
}
OUTPUT:
74 33 9 83 87 22 92 41 18 92
Try Inorder traversal.
9 -> 18 -> 22 -> 33 -> 41 -> 74 -> 83 -> 87 -> 92 ->
*****************
Try Preorder traversal.
74 -> 33 -> 9 -> 22 -> 18 -> 41 -> 83 -> 87 -> 92 ->
*****************
Try Postorder traversal.
18 -> 22 -> 9 -> 41 -> 33 -> 92 -> 87 -> 83 -> 74 ->
Introducing more methods for binary tree.
a.
b.
c.
d.
e.
Compute the height of a binary tree recursively
Compute the number of nodes in a tree
Compute the number of leaves in a tree
Compute the number of single child parents
Compute the number of two children parents
We do the first three here!
import java.io.*;
import java.util.*;
import java.lang.Math;
public class Tree {
class TreeNode {
TreeNode left;
int data;
TreeNode right;
public TreeNode (int d) {
data=d;
left=right=null;
}
public void insert(int d){
if (d <data){
if (left == null)
left = new TreeNode(d);
else
left.insert(d);
}
else
if (d > data) {
if (right == null)
right= new TreeNode(d);
else
right.insert(d);
}
}
}
/* Now that a TreeNode is defined, we are going to
build a binary tree.
*/
private TreeNode root;
/* Construct an empty binary tree at the root
*/
public Tree () {root=null;}
/* Insert a new node in the binary tree. If the
root node is null, create the root node now.
*/
public void insertNode (int d){
if (root == null)
root = new TreeNode(d);
else
root.insert(d);
}
private void inOrderDriver(TreeNode node){
if (node == null)
return;
else {
inOrderDriver(node.left);
System.out.print(" "+node.data+" -> ");
inOrderDriver(node.right);
}
}
public void inOrderTraversal(){inOrderDriver(root);}
public int treeSize() {int k=treeSizeDriver(root);
return k;}
public int treeHeight() {int
k=treeHeightDriver(root);
return k;}
public int leafCount() {int k=leafCountDriver(root);
return k;}
// count the number of treenodes recursively
private int treeSizeDriver(TreeNode r) {
if(r == null)
return 0;
else
return(1 + treeSizeDriver(r.left)+
treeSizeDriver(r.right));
}
// Compute the height of the tree recursively
private int treeHeightDriver(TreeNode r) {
if (r == null)
return 0;
else
return
Math.max(treeHeightDriver(r.left),
treeHeightDriver(r.right))+1;
}
// Count the leaves of a tree recursively
private int leafCountDriver (TreeNode r) {
if (r == null)
return 0;
else
if (r.right==null && r.left==null)
return 1;
else
return leafCountDriver(r.left) +
leafCountDriver(r.right);
}
public static void main(String args []){
Tree thisTree = new Tree();
int i, j, k;
for (i=0; i<10; i++){
j=(int)(100*Math.random());
System.out.print(j+" ");
thisTree.insertNode(j);
}
System.out.println("\n\n");
System.out.println("Height of this tree: "+
thisTree.treeHeight()+'\n');
System.out.println("Node count in this tree: "+
thisTree.treeSize()+'\n');
System.out.println("Leaf count of this tree: "+
thisTree.leafCount()+'\n');
// Traversal routine
System.out.println("Inorder traversal profile: ");
System.out.println(" ");
thisTree.inOrderTraversal();
System.out.println(" ");
System.out.println("\n *****************\n");
System.out.println("\n");
}
}
OUTPUT:
3 93 58 50 85 22 90 55 61 12
Height of this tree: 6
Node count in this tree: 10
Leaf count of this tree: 4
Inorder traversal profile:
3 -> 12 -> 22 -> 50 -> 55 -> 58 -> 61 -> 85 -> 90 -> 93 ->
*****************
Let’s try to design a function that would interchange the two
subtrees of a binary tree.
Example.
A
A
B
D
B
C
E
C
D
E
The code for this:
public void interchange() {interchangeDriver(root);}
private void interchangeDriver(TreeNode r)
{
TreeNode tmp;
if (r != null) {
tmp=r.left;
r.left=r.right;
r.right=tmp;
interchangeDriver(r.left);
interchangeDriver(r.right);
}
}
Related documents