Sie sind auf Seite 1von 13

Tree

General Tree: A general tree is a tree in which the number of childs of any node is n (where
n is a positive integer). It is also known as n-array tree.

Binary Tree: A general tree becomes binary tree in which n is restricted to 2. Any single
node of a binary tree is allowed to have a maximum of two childs.

A binary tree is,
empty, that is, it has no nodes, or,
it consists of a node called the root and two disjoint binary trees called the left subtree
and the right subtree.
Complete binary tree (CBT): A binary tree is called CBT, if all the leaves are at the same
level and all the non leaf nodes have got exactly 2 childs. An example of a CBT is as shown
below.
(A)
/ \
(B) (C)
/ \ / \
(D) (E) (F) (G)

Full binary tree (FBT): A binary tree is called FBT, if it is complete till the penultimate level
and in the last level, the nodes occur starting from as far left as possible.
(A)
/ \
(B) (C)
/ \ / \
(D) (E) (F) (G)
/
(H)
Following is not a FBT. Data value, H, did not occupy the left most available position
(A)
/ \
(B) (C)
/ \ / \
(D) (E) (F) (G)
\
(H)
Strictly binary tree (SBT): A binary tree is called SBT, if each node has got 0 or 2 childs.
Following are few examples of SBT.
(A) (A)
/ \ / \
(B) (C) (B) (C)
/ \ / \ / \
(D) (E)(F) (G) (D) (E)
/ \
(H) (I)
Traversal: The process of reaching to each node at least once is called the traversal of the
binary tree. A binary tree can be traversed in 3 different ways, Inorder traversal, Preorder
traversal and Postorder traversal. These traversal techniques are not substitutes to on
another but are different types of accessing the nodes. Different circumstances / applications
require different types of traversals.
Inorder traversal: The Inorder traversal specifies that nodes are visited in the order of left,
root, right. The method to traverse can be formally described using the following sequence
of steps:
Traverse the left subtree in Inorder.
Visit the root node
Traverse the right subtree Inorder.

(A)
/ \
(B) (C)
/ \ / \
(D) (E)(F) (G)

For the binary tree shown above, starting at the root of the tree, the sequence of steps taken
would be as shown.
move to the left sub-tree of A, which is the node B
move to the left sub-tree of B, which is the node D
the left sub-tree of D is empty, so visit D (which is the root having empty left sub
tree.)
there is no right sub-tree of D, to visit
now visit B, the root of the sub-tree in which D is the left branch
now move to E, the right sub-tree
there is no left-sub tree to E, so visit E
there is no right sub-tree to E, to visit
move back to root of the tree, as the left subtree is traversed
visit the root, A
move to the right subtree of A, which is the node C
move to the left subtree of C, which is the node F
there is no left sub-tree to F so visit F
there is no right sub-tree of F, to visit
now visit C, the root of the sub-tree in which F is the left branch
now move to G, the right sub-tree
there is no left-sub tree to G, so visit G
All the nodes are visited, traversal completes.
This method visits the nodes in the order of D, B, E, A, F, C, G.
Here, Visiting a node, is considered as printing the data value on the screen. Alternatively,
it could be defined as anything that needs to be done with the visited node.
Preorder traversal: The Preorder traversal specifies that nodes are visited in the order of
root, left, right The method to traverse can be formally described using the following
sequence of steps:
Visit the Root
Traverse the left subtree in pre-order
Traverse the right subtree in pre-order

(A)
/ \
(B) (C)
/ \ / \
(D) (E) (F) (G)
For the above binary tree, this method visits the nodes in the order of A, B, D, E, C, F, G.
Postorder traversal: The postorder traversal specifies that nodes are visited in the order of
left, right, root. The method to traverse can be formally described using the following
sequence of steps:
Traverse the left subtree in post-order
Traverse the right subtree in post-order
Visit the Root

(A)
/ \
(B) (C)
/ \ / \
(D) (E) (F) (G)
For the above binary tree, this method visits the nodes in the order of D, E, B, F, G, C, A.
Representation: Binary tree can be represented using arrays or using linked representation

Array Representation of Binary Trees
Node values are stored in a sequential manner using one dimensional array.
Root is stored at A[0].
First-level nodes are stored at A[1] and A[2].
Second-level nodes are stored at A[3], A[4], A[5], and A[6].
This representation proves very efficient for complete and for full binary trees.
Very suitable when direct access to node data is required.
(A)
/ \
(B) (C)
/ \ / \
(D) (E) (F) (G)

Array, A



(A)
/ \
(B) (C)
/ \
(D) (E)

Array, A



Array location is wasted for a non-existing node, as in the case of A[4] and A[5].
Non existing node value is represented as NULL.
If a node exists at A[i] then its,

- Left child index
2 * i + 1
undefined if 2 * i + 1 >= Number of nodes
- Right child index
2 * i + 2
undefined if 2 * i + 2 >= Number of nodes
- Parent index
int((i - 1)/2)
undefined if i = 0, because there exists no parent for the root node
Linked list representation of binary trees

In this representation, each of the tree nodes is represented as a memory unit (also
called as node) contains a data field and two pointers.
Data field contains the node value, one pointer (also called left pointer) is used to hold
the address the address of the left subtree and the other pointer (also called right
pointer) is used to hold the address of the right subtree.
Leaf node has a NULL left and right pointer.
(A)
/ \
(B) (C)
/ \ / \
(D) (E)(F) (G)
Binary search tree
A binary tree is called a binary search tree (BST), if it complies with the following properties:
The data stored at each node has a distinguished key, which is unique in the tree.
(Duplication of data values is not allowed.)
The data stored at each node is less than all data values occurring in its right subtree
and greater than all data values occurring in its left subtree.
Following is an example of a BST.
(29)
/ \
(11) (41)
/ \ /
(7) (17) (31)
/
(13)

The inorder traversal of the BST, visits the nodes in the order of their data values. Thus, the
output produced by such a traversal is sorted by the data values.

For the above-mentioned reason, the following are considered two same binary search trees,
even though they form two different binary trees.


(13) (11)
/ \ / \
(7) (17) (7) (17)
\ /
(11) (13)


Following operations can be performed on a BST.

Search(data): Looks up a data value in the BST and returns a pointer to the corresponding
node. If the data value is not present, it returns a NULL.
Insert(data): It adds a node containing data to the BST. The new node does not violate the
definition of the BST.

Delete(data): Deletes a node containing data, from the BST. The new node does not violate
the definition of the BST.

IsEmpty(): It tests whether the BST is empty.

Count(): It counts the number of nodes present in the BST.

Other operations may include, finding smallest data value, finding greatest data value,
finding the height etc.

Search: The search starts from the root of the BST and navigates through the tree
recursively. The method can be described in the following steps.
If the current node is NULL then return NULL (Unsuccessful search).
Else if the current node's data matches the input data then return the pointer to the
current node.
Else if the current node's data is more than the input data then recursively search the
left subtree.
Else recursively search the right subtree.

Insert: The insert operation can be described in the following steps.
1. Special case. If the tree is empty as it is in the very beginning create a new node
and make it the root of the tree.
2. Otherwise, with the help of a pointer, t, point to the root.
3. While (t is not NULL) and (the data of t is not a match with the input data):
a. if t's data is less than the input data then let t point to its right child.
b. if t's key is greater than the insert key then let t point to its left child
4. If a match was not found than allocate a new leaf for the insertion.
5. At the end, initialize all the pointers to NULL in all the leafs of the tree.

Following the above steps, a BST can be constructed with the following sequence of data
values: 29, 41, 31, 11, 7, 17, 13.

(i) Insert(29)
(29)



(ii)Insert(41)

(29)
\
(41)


(iii)Insert(31)

(29)
\
(41)
/
(31)
(iv)Insert(11)

(29)
/ \
(11) (41)
/
(31)
(v)Insert(7)

(29)
/ \
(11) (41)
/ /
(7) (31)
(vi)Insert(17)
(29)
/ \
(11) (41)
/ \ /
(7) (17) (31)
(vii)Insert(13)
(29)
/ \
(11) (41)
/ \ /
(7) (17) (31)
/
(13)

Delete: The delete operation has to take into consideration 3 possibilities.
A leaf can be simply removed
If a node to be deleted has 1 child, left or right, then the node is deleted and is
replaced by its child.
If a node to be deleted has 2 childs then,
a. delete the node and replace it with the smallest child in its right subtree, or
b. delete the node and replace it with the largest child in its left subtree.


Delete(14)

(9) (9)
/ \ / \
(3) (22) ===> (3) (22)
/ \ / / \
(2) (6) (14) (2) (6)
/ /
(4) (4)


Delete(22)
(9) (9)
/ \ / \
(3) (22) ===> (3) (14)
/ \ / / \
(2) (6) (14) (2) (6)
/ /
(4) (4)
Delete(3)
(9) (9)
/ \ / \
(3) (22) Using 3(b) (4) (22)
/ \ / ===> / \ /
(2) (6) (14) (2) (6) (14)
/
(4)

(9) (9)
/ \ / \
(3) (22) Using 3(a) (2) (22)
/ \ / ===> \ /
(2) (6) (14) (6) (14)
/ /
(4) (4)
The shape of the BST is decided by the order in which the data values appear. If the data
values appear in the order, 4, 2, 6, 1, 3, 5, 7, then the resultant tree may be a complete
binary tree as shown.

(4)
/ \
(2) (6)
/ \ / \
(1) (3) (5) (7)


If the data values appear in the order 1, 2, 3, 4, 5, 6, 7, then the resultant tree may be as
shown.

(1)
\
(2)
\
(3)
\
(4)
\
(5)
\
(6)
\
(7)
Glossary

Leaf: It is also called a terminal node. A leaf is a node with no childs.

Root: The distinguished node of a tree. It is the origination point of the tree, and the only
node which has no parent.

Parent: It is also called non-leaf or non terminal node. A node is called a parent if it has got
1 or more childs. B is the parent to D and E, similarly, c is the parent to F and G, and so on.

Child: A node connected to a higher level node is called the child to its higher level node.
Every node, except the root, is the child of some parent. D and E are childs of B, B and C or
childs of A, and so on.

Level of a Node: A set of nodes are supposed to be at the same level if all of them have
same number of edges between them and the root node. There is small confusion over the
level at which level the root node exists. One camp says, root exists at level 0, and the other
equally efficient camp says, root exists at level 1.

Depth: Depth of a tree is same as height of the tree. Depth of a node is the count of number
of edges between the root node and the node being considered.

Height: Height is defined as the count of number of edges between the root node and the
node at the lowest level. For the above tree, the height is 2.

Ancestor: A higher level node is called an ancestor to all of its lower level nodes, such that a
path exists between the higher level node the lower level node.

Sibling: A set of nodes are called siblings if they share the same parent. F and G are
siblings, as they have a common parent, C.

Program

#include <stdio.h>
#define SIZE 25
struct list
{
struct list *lptr;
int data;
struct list *rptr;
};

typedef struct list node;

node *root = NULL;

node *tree(char c)
{
char lans, rans;
node *temp;
if (!((c == 'Y') || (c == 'y')))
return NULL;
else
{
temp = (node *) malloc(sizeof(node));
printf("Enter the node value : ");
scanf("%d", &temp->data);

printf("Any left child to %d ? (y/n) : ", temp->data);
scanf("%c",&lans);
temp->lptr = tree(lans);

printf("Any right child to %d ? (y/n) : ", temp->data);
scanf("%c",&rans);
temp->rptr = tree(rans);

return(temp);
}
}

void inorder(node *root)
{
node *temp = root;

if (temp != NULL)
{
inorder(temp->lptr);
printf("%d\t",temp->data);
inorder(temp->rptr);
}
} /* end of inorder() */

void preorder(node *root)
{
node *temp = root;

if (temp != NULL)
{
printf("%d\t",temp->data);
preorder(temp->lptr);
preorder(temp->rptr);
}
} /* end of preorder() */

void postorder(node *root)
{
node *temp = root;

if (temp != NULL)
{
postorder(temp->lptr);
postorder(temp->rptr);
printf("%d\t",temp->data);
}
} /* end of postorder() */

int leafnodes(node *root)
{
node *temp = root;

if (temp == NULL)
return(0);
else if ((temp->lptr != NULL) || (temp->rptr != NULL))
return( 0 + leafnodes(temp->lptr) + leafnodes(temp->rptr));
else
return(1);

} /* end of leafnodes() */

int nleafnodes(node *root)
{
node *temp = root;

if (temp == NULL)
return(0);
else if ((temp->lptr != NULL) || (temp->rptr != NULL))
return(1 + nleafnodes(temp->lptr) + nleafnodes(temp->rptr));
else
return(0);

} /* end of nleafnodes() */

int totalnodes(node *root)
{
node *temp = root;

if (temp == NULL)
return(0);
else
return(1 + totalnodes(temp->lptr) + totalnodes(temp->rptr));
} /* end of totalnodes() */

void menu()
{
printf("Following operations are provided by this program : \n");
printf("1. Inorder\n");
printf("2. Preorder\n");
printf("3. Postorder\n");
printf("4. Leaf nodes\n");
printf("5. Non-leaf nodes\n");
printf("6. Total nodes \n");
printf("7. Exit\n");
printf("Enter your choice : ");
}

void process()
{
int choice, count;
do
{
menu();
scanf("%d", &choice);
switch(choice)
{
case 1 : printf("The nodes visited as per inorder are,\n");
inorder(root);
printf("\n");break;

case 2 : printf("The nodes visited as per preorder are,\n");
preorder(root);
printf("\n");break;

case 3 : printf("The nodes visited as per Postorder are,\n");
postorder(root);
printf("\n");break;

case 4 : count = leafnodes(root);
printf("The no. of leaf nodes are %d.\n", count);
break;

case 5 : count = nleafnodes(root);
printf("The no. of non-leaf nodes are %d.\n", count);
break;

case 6 : count = totalnodes(root);
printf("Total no. of nodes are %d.\n", count);
break;

case 7 : printf("Program terminates.\n");
break;

default : printf(" Wrong choice. Try again.\n");

} /* end of switch */
} while(choice != 7);
} /* end of process() */

void main()
{
char c;
int choice;

printf("Any tree to enter (y/n) : ");
scanf("%c", &c);
if ((c == 'Y') || (c == 'y'))
{
root = tree(c);
process();
printf("Program rerminates. Bye.Bye.\n");
}
else
printf("Sorry, no tree to process.Try next time.\n");
} /* end of main() */

Exercises

Implement a function for non recursive inorder traversal.
Implement a function for non recursive preorder traversal.
Implement a function for non recursive postorder traversal.
Implement the above program without using any global variables.
Implement the above code with out using recursion.

Das könnte Ihnen auch gefallen