0% found this document useful (0 votes)
4 views30 pages

Week 6-2

Uploaded by

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

Week 6-2

Uploaded by

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

Trees

(part 2)
Chapter 4 textbook

Prepared by LC Kwek
Edited by NHAA
Objectives

• In this module we will


• implement in ANSI C a binary tree using array index referencing method
• implement in ANSI C a binary tree using array index calculation method

2/30
Introduction

• A tree can be made by using an array


• Advantage:
• Can be compact for static data set size
• Drawbacks:
• Difficult to increase tree size
• If the tree shrinks, difficult to decrease the number of nodes

3/30
Array with Index Referencing
Method
• An array of records is used, with each record contains the
information for one node i Data Left right
• data
• index of left child 0 - 1 2
• index of right child 1 + 3 4
• Example: Given the tree below 2 8 -1 -1
- 3 * 5 6
4 / 7 8
+ 8
5 5 -1 -1
6 3 -1 -1
* /
7 7 -1 -1
5 3 7 2 8 2 -1 -1
*denotes absence of a
4/30
child
Define a Node for a Binary Tree

• Linked list style vs. Array with index referencing style


Linked list Array with index referencing
struct Bin3Node{ struct Bin3Node{
char data; char data;
struct Bin3Node *left; int left;
struct Bin3Node *right; int right; Pointers replaced
}; }; with integers

5/30
Declare & Initialize the Tree
• Whole tree is one array, with each element tree
occupies 3 memory blocks '-'
• Can be declared and initialized all at once in 1
one line 2
'+'
3
4
'8'
-1
-1
'*'
5
6
'/'
7
8

6/30
How is the Traversal Done?
• Example: Function preorder called with
node = 0 (i.e., the root) i Data Left right
• visit tree[0].data: ‘-’ 0 - 1 2
• Recurs 0’s left child, node = 1, visit ‘+’ 1 + 3 4
• Recurs 1’s left child, node = 3, visit ‘*’
• Recurs 3’s left child, node = 5, visit ‘5’
2 8 -1 -1
• Recurs 5’s left child, node = -1, return 3 * 5 6
• Recurs 5’s right child, node = -1, return
4 / 7 8
• Continue with 3’s right child, etc.
5 5 -1 -1
6 3 -1 -1
7 7 -1 -1
8 2 -1 -1

7/30
Implementing a Binary Tree using
Array Index Referencing Method (1/4)

• The following program


• implements a binary tree using array index referencing
• traverses the tree in
• preorder
• inorder
• postorder
• prints the contents of each node

8/30
Implementing a Binary Tree using
Array Index Referencing Method (2/4)
1 /* Implementing a binary tree with array */
2 #include <stdio.h>
3 #define MAXNODES 9 Maximum number of nodes in tree specified
4 (major limitation of array based approach)
5 struct Node {
6 char data; Definition of a node of the tree;
7 int left; integer variables replace the
8 int right; pointers of LL implementation
9 };
10 struct Node tree[MAXNODES] = {
11 {'-', 1, 2},
12 {'+', 3, 4},
13 {'8',-1,-1},
14 {'*', 5, 6},
15 {'/', 7, 8}, Array of nodes declared as
16 {'5',-1,-1}, a global variable
17 {'3',-1,-1},
18 {'7',-1,-1},
19 {'2',-1,-1}
20 };
9/30
Implementing a Binary Tree using
Array Index Referencing Method (3/4)
21 void visit(char data);
22 void preorder(int node); int of an array index rather
23 void postorder(int node); than pointer is passed
24 void inorder(int node);
25 Same as in LL, except that
26 int main(void){ index of root is passed
27 printf("\nPreorder traversal:\t"); preorder(0);
28 printf("\nInorder traversal:\t"); inorder(0);
29 printf("\nPostorder traversal:\t"); postorder(0);
30 return(0);
31 }
32
33 void visit(char data){ printf("%c ", data); }
34
35 void preorder(int node){ Checks if node exists
36 if (node!=-1){
37 visit(tree[node].data); Access data stored in node
38 preorder(tree[node].left);
39 preorder(tree[node].right);
40 } Index of right child
41 } Access current node 10/30
Implementing a Binary Tree using
Array Index Referencing Method (4/4)
42 void postorder(int node){
43 if (node!=-1){
44 postorder(tree[node].left);
45 postorder(tree[node].right);
46 visit(tree[node].data);
47 }
48 }
49 void inorder(int node){
50 if (node!=-1){
51 inorder(tree[node].left);
52 visit(tree[node].data);
53 inorder(tree[node].right);
54 }
55 }
Preorder traversal: - + * 5 3 / 7 2 8
Inorder traversal: 5 * 3 + 7 / 2 - 8
Postorder traversal: 5 3 * 7 2 / + 8 - Same as in LL

11/30
Strengths and Weaknesses

• Strengths
• Easier to initialize tree
• Shorter code
• Weakness
• Limited size – if the size of the data set changes, might need to use a
dynamic array, and use standard function realloc when run out of space

12/30
Why Use this Implementation?

• Some languages do not support pointers


• Ease of initialization
• Easy to change node data if tree structure is static

13/30
Summarizing
Binary Trees with Array Index
Referencing
• A binary tree can be implemented using an array of records as a data
structure
• Each record (or node) contains
• the data
• the array index of the left child
• the array index of the right child
• It is useful for immutable data (not changing)

14/30
Binary Tree with Array Index
Calculation (1/4)
• Differences with the previous methods
• Pointers/indices not stored - instead, calculated
• Initialization laid out in nice tree fashion
• A better option if the tree is full
• If tree not full, space wasted (6 nodes, aside from root, wasted in the following
example)

15/30
Binary Tree with Array Index
Calculation (2/4)
• The key of this method
• Index of left child = index of parent * 2
• Index of right child = index of parent * 2 + 1
• A blank node in position 0 of the array (as 0 * 2 = 0)
• Specify an empty node by storing some special value which will never occur
(e.g. null character (‘\0’) since this won’t occur in the data)

16/30
Binary Tree with Array Index
Calculation (3/4) i Value
0 ‘\0’
• Example: Given the tree below 1 -
- 2 +
3 8
+ 8 4 *
5 /
6 ‘\0’
* /
7 ‘\0’
8 5
5 3 7 2
9 3
• Suppose we are at node 5 (‘/’) 10 7
• Left child = 5 * 2 = 10 (‘7’)
• Right child = 5 * 2 + 1 = 11 (‘2’)
11 2
• Parent = 5 / 2 = 2 (‘+’) 12 ‘\0’
13 ‘\0’
14 ‘\0’
17/30
15 ‘\0’
Binary Tree with Array Index
Calculation (4/4)
• How do we check if a tested node is valid?
• Returns “false” if the index is out of bound of the array or if the data is 0

int valid(int node){


return ( (node < MDEPTH*MDEPTH) && tree[node] );
}

18/30
Implementing a Binary Tree using
Array Index Calculation Method (1/5)

• The following program


• implements a binary tree using array index calculation style
• traverses the tree in
• preorder
• inorder
• postorder
• prints the contents of each node

19/30
Implementing a Binary Tree using
Array Index Calculation Method (2/5)
1 /* Implementing a binary tree with array index cal. */
2 #include <stdio.h>
3 #define MDEPTH 4 Depth of tree rather than number of nodes specified
4
5 char tree[MDEPTH*MDEPTH] = {
6 0,
7 '-',
8 '+', '8',
9 '*', '/', 0, 0,
10 '5','3', '7','2', 0, 0, 0, 0
11 };
12
13 void visit(char data);
14 int valid(int node);
15 int leftChild(int node);
16 int rightChild(int node); Array index passed
17 void preorder(int node);
18 void postorder(int node);
19 void inorder(int node);
20
20/30
Implementing a Binary Tree using
Array Index Calculation Method (3/5)
21 int main(void){
22 printf("\nPreorder traversal:\t"); preorder(1);
23 printf("\nInorder traversal:\t"); inorder(1);
24 printf("\nPostorder traversal:\t"); postorder(1);
25 return(0);
26 } Index of root passed; In this implementation, the root is at 1
27
28 void visit(char data){ printf("%c ", data); }
29
30 int valid(int node){ /* if there's something there */
31
32 return((node < MDEPTH*MDEPTH) && tree[node]);
33 }
34
35 int leftChild(int node) { find left child at node * 2
36 return(node * 2);
37 }
38
39 int rightChild(int node) { find right child at node * 2 + 1
40 return((node * 2) + 1);
} 21/30
Implementing a Binary Tree using
Array Index Calculation Method (4/5)
41 void preorder(int node){
42 if (valid(node)){ Checks for valid node
43 visit(tree[node]);
44 preorder(node*2);
45 preorder(node*2+1);
46 }
47 }
48 void postorder(int node){
49 if (valid(node)){
50 postorder(leftChild(node));
51 postorder(rightChild(node));
52 visit(tree[node]);
53 }
54 }
55 void inorder(int node){
56 if (valid(node)){
57 inorder(leftChild(node));
58 visit(tree[node]);
59 inorder(rightChild(node));
60 }
61 } 22/30
Implementing a Binary Tree using
Array Index Calculation Method (5/5)
Preorder traversal: - + * 5 3 / 7 2 8
Inorder traversal: 5 * 3 + 7 / 2 - 8
Postorder traversal: 5 3 * 7 2 / + 8 -

Output is the same with


the previous methods

23/30
Why Would We Use this Method?

• In a full tree, no wasted space – no need for pointers, indices


calculated
• Efficient calculation of indices – one machine instruction
• Left child: SHIFTLEFT
• Right child: SHIFTLEFT, INCREMENT
• Parent: SHIFTRIGHT

24/30
Aside: How SHIFTLEFT Works (1/3)

• SHIFTLEFT is a one-cycle (i.e. really fast) operation implemented on


all ordinary microprocessors
• It shifts the bits of the binary number left
• E.g. the number 5 is 00000101 in binary
• Shifting it left would give us 00001010, which is 10 (i.e. 5*2)

25/30
Aside: How SHIFTRIGHT Works
(2/3)

• SHIFTRIGHT is a one-cycle operation implemented on all ordinary


microprocessors
• It shifts the bits of the binary number right
• E.g. the number 5 is 00000101 in binary
• Shifting it right would give us 00000010, which is 2 (i.e. 5/2 (divide 5 by 2
and throw away the remainder))

26/30
Aside: How SHIFTRIGHT Works
(3/3)

• SHIFTLEFT and INCREMENT would take 2 machine cycles on almost


all microprocessors, still very fast
• E.g. the number 5 is 00000101 in binary
• Shifting it left would give us 00001010, which is 10 (i.e. 5*2)
• Then incrementing would give us 00001011, which is 11 (i.e. 5*2+1)

27/30
Summarizing Binary Trees with Index
Calculation

• Implementing binary trees by array index calculation is very efficient


• for memory allocation (for nearly full tree)
• for speed; Finding a child or parent is a single machine instruction
• It is suitable for trees that are
• full
• not growing or shrinking

28/30
Choosing a Tree Implementation
If you want ... And you do not mind ... You should use ...
full flexibility in the tree using more memory and Linked list implementation
structure and in insertion & things taking a bit longer
deletion
to use a language without having the tree size limited Array by index referencing
pointers, or if the tree is static by the array size
and sparse, and ease in
initialization
speed in accessing the nodes, having the tree size limited Array by index calculation
and ease in initialization by the array size, and having
a static structure, and
wasting space if the tree is
sparse

29/30
Summary

• There are three ways of traversing a tree, i.e.,


• preorder
• postorder
• inorder (for binary tree only)
• Three ways of implementing, in ANSI C, binary trees, i.e.,
• linked lists
• arrays with index referencing
• arrays with index calculation

30/30

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy