Data Structure Using C Notes
Data Structure Using C Notes
2
(preferably we use C/C++ programming because of their versatile features and modern
programming approaches).
1.4.1Algorithm Specification
The concept of algorithm is fundamental to computer science and plays a crucial role in developing
good and efficient programs. It is process or set of rules required to perform calculations or data
processing.
Definition: An algorithm is defined as step by step procedure to solve a given problem in finite
number of steps. It accepts a set of inputs and produces the desired output for the given problem.
Characteristics of an Algorithm
Input: It takes zero or more well-defined inputs.
Output: It should produce at least one or more well-defined outputs.
Definiteness: Each step must be clear, well-defined and precise.
Finiteness: The algorithm must terminate after finite number of steps.
Effectiveness: Each instruction must be simple enough to be carried out.
Independent: It should be independent of any programming language.
A good algorithm should be optimized in terms of time and space. The time and space it uses are
two major measures of the efficiency of an algorithm.
1.
Example: Fibonacci sequence of 10 terms: 0 1 1 2 3 5 8 13 21 34
/* C program to generate N Fibonacci numbers using recursive
function */
#include <stdio.h>
int fibo(int n)
{
if ( n = = 0)
return 0;
else if ( n = = 1)
return 1;
else
Fibonacci Numbers
The Fibonacci sequence is a set of numbers that is generated by adding previous two numbers.
First two numbers are 0 and 1 respectively.
return (fibo(n - 1) + fibo(n - 2));
}
main( )
{
int i, n ;
printf(“Enter the number of terms :”);
scanf(“%d”,&n);
printf(“Fibonacci series \n”);
for(i=1; i<=n; i++)
printf(”%d \n” fibo(i));
}
7
2. GCD of two Numbers
The GCD of two non-zero integers a and b is greatest positive integer is d, such that d is a divisor
of both a and b.
8
{
int i=1;
while(n!=0)
{
i= i*n;
n--;
}
Return i;
}
4. Tower of Hanoi
Tower of Hanoi is a mathematical puzzle where we have three rods and n disks. The objective of
the puzzle is to move the entire stack to another rod, obeying the following simple rules:
1. Only one disk can be moved at a time.
2. Each move consists of taking the upper disk from one of the stacks and placing it on top of
another stack i.e. a disk can only be moved if it is the uppermost disk on a stack.
3. No disk may be placed on top of a smaller disk.
4. Recursion terminates when a base case is 4. An iteration terminates when the loop
recognized condition fails
5. Used when code size needs to be small, and 5. Used when time complexity needs to be
time complexity is not an issue balanced against an expanded code size
6. Recursion is usually slower than
6. An iteration does not use the stack so it is
iteration due
faster than recursion
to the overhead of maintaining the stack
7. Recursion uses more memory than
7. Iteration consumes less memory
iteration
9. Recursion makes the program is very small 9. Iteration makes the program longer
10
UNIT – 2: Arrays
An array is defined as collection of homogeneous data item stored in consecutive memory locations.
Array is considered as linear data structure because it stores the elements of same data types.
Advantages of arrays are;
Arrays store multiple data of similar types with the same name.
It is helpful to store any type of data with a fixed size
Accessing an element is very easy by using the index number.
The search process can be applied to an array easily.
11
NUM[3] NUM[0] NUM[1] NUM[2] NUM[3] NUM[4] NUM[5]
NUM[4]
NUM[5]
2.2.2 Initialization of Linear arrays
Initialization is process of assigning values to the elements of an array during declaration. Syntax for
initialization of a linear array is as follows;
data type array_name[size] = { element1, element2, ………,element n};
Example: int NUM[6] = { 57, 38, 98, 75, 25, 97}; will initialize the elements as follows;
57
NUM[0] Will assign the values to elements of the array NUM as follows;
38
NUM[1] NUM[0] = 57 NUM[1] = 38 NUM[2] = 98
98
NUM[2] NUM[3] = 75 NUM[4] = 25 NUM[5] = 75
75
NUM[3] 25
NUM[4]
97
NUM[5]
12
An element is stored in a given index and they can be retrieved at a later time by specifying the same
index. The Array (ADT) have one property, they store and retrieve elements using an index.
Each ADT description consists of two parts:
Data: This part describes the structure of the data used in the ADT in an informal way.
Operations: This part describes valid operations for this ADT, hence, it describes its interface.
13
Accessing and processing each element of the array exactly once. Let A be collection of data stored
in the memory of the computer. Suppose we want to print the content of each element of A, or
suppose we want to count the number of elements of A with a given property. This can be done by
traversing A, that is, by accessing and processing each element of A exactly once.
Traversing Algorithm
The following algorithm traverses a linear array LA with lower bound LB, and upper bound UB. It
traverses LA applying an operation PROCESS to each element of LA.
14
downward to new locations to accommodate the new element and keep the order of the other
elements.
Similarly, deleting an element at the end of an array have no difficulties, but deleting and element
somewhere in the middle of the array would require that each subsequent element be moved one
location upward in order to fill up the array.
Insertion Algorithm
The following algorithm inserts a data element ITEM into the K th position in a linear array LA with
N elements.
Algorithm: INSERT(LA, N, K, ITEM)
Step 1: [Initialize the counter.] Set J = N.
Step 2: Repeat Steps 3 and 4 while J N.
Step 3: [Move Jth element downward.]
Set LA[J + 1] = LA[J].
Step 4: [Decrease counter.]
Set J = J – 1.
[End of Step 2 loop.]
Step 5: [Insert element.]
Set LA[K] = ITEM.
Step 6: [Reset N.] Set N = N + 1.
Step 7: Exit.
2.2.8 Sorting
Sorting refers to the operation of arranging data in some given order, such as increasing or
decreasing, with numerical data or alphabetically, with character data. Sorting is a fundamental
operation and is an important concept that is extremely used in the field of computer science.
Usually sorting is frequently applied to a file of records.
A sort can be classified as being internal if the records that it is sorting are in main memory, or
external if some the records that it is sorting are in auxiliary storage. Usually sorting methods used
for internal sort.
Various sorting methods are;
i. Bubble Sort
ii. Selection Sort
iii. Quick Sort
iv. Insertion Sort
i. Bubble Sort
Bubble sort is also called as exchange sort. It is the simplest and most widely used sorting technique.
One of the characteristics of bubble sort is that it is easy to understand and program, and also it is
probably least efficient sorting method.
Suppose the list of numbers A[1], A[2], ………, A[N] is in memory. The bubble sort algorithm
works as follows:
Step 1: Compare A[1] and A[2] and arrange them in the desired order, so that A[1] < A[2].
Then compare A[2] and A[3] and arrange them so that A[2] < A[3]. Then compare
A[3] and A[4] and arrange them so that A[3] < A[4]. Continue until we compare
A[N – 1] with A[N] and arrange them so that A[N – 1] < A[N].
Here we observe that Step 1 involves n –1comparisons. (During Step 1, the largest element is
“bubbled up” to the nth position or “sinks” to the nth position.) When Step 1 is completed, A[N] will
contain the largest element.
Step 2: Repeat Step 1 with less comparison; that is, now we stop after we compare and
possibly rearrange A[ N –2] and A[N –1]. ( Step 2 involves N –2 comparisons and,
when Step 2 is completed, the second largest element will occupy A[N –1].)
Step 3: Repeat Step 1 with two fewer comparisons; that is, now we stop after we compare
17
and possibly rearrange A[ N –3] and A[N –2].
. ……………………………………………………………………………………….
. ………………………………………………………………………………………
Step N – 1: Compare A[1] and A[2] and arrange them so that A[1] < A[2].
After n – 1 steps, the list be sorted in increasing order.
The process of sequentially traversing through all or part of a list is frequently called a “pass” so
each of the above steps is called a pass. Accordingly, the bubble sort algorithm requires n – 1
passes, where n is the number of input items.
Example: Consider an array with the following elements
32, 51, 27, 85, 66, 23, 13, 57
We apply the bubble sort to sort the array in an ascending order.
Pass 1: We have the following comparisons:
a) Compare 32 and 51: Since 32 < 51, the list is not altered.
18
At end of Pass 2, the second largest number, 66, has moved its way down to next-to-last position.
Pass 3: 27, 32, 23 , 51 , 13, 57 , 66 , 85
27, 32, 23, 13 , 51 , 57 , 66 , 85
Pass 4: 27, 23 , 32 , 13, 51, 57, 66 , 85
K=2, LOC=6 11 33 44 77 88 22 66 55
K=3, LOC=6 11 22 44 77 88 33 66 55
K=4, LOC=6 11 22 33 77 88 44 66 55
K=5, LOC=8 11 22 33 44 88 77 66 55
K=6, LOC=7 11 22 33 44 55 77 66 88
K=7, LOC=7 11 22 33 44 55 66 77 88
Sorted 11 22 33 44 55 66 77 88
The Selection sort algorithm is divided into parts. The first past gives a procedure called MIN,
which find the location of smallest element, and the second part uses the procedure SELECTION,
which sorts the array.
21
Beginning with 77, scan the list from right to left, seeking a number less than 44. We do not meet
such a number before meeting 44. This means all numbers have been scanned and compared with
44. All the numbers less than 44 on the left form one sublist, and all numbers greater than 44 on the
right side forms another sublist as shown below.
22, 33, 11, 40, 44 , 90, 77, 60, 99, 55 , 88, 66
Thus, 44 is correctly placed in its final position, and the task of sorting the original list A has now
been reduced to the task of sorting each of the above sublists.
The above reduction step is repeated with each sublist containing 2 or more elements. Since we can
process only one sublist at a time, we must be able to keep track of some sublists for future
processing. This is accomplished by using two tasks, called LOWER and UPPER, to temporarily
“hold” such sublists. This is, the addresses of the first and last elements of each sublist, called its
boundary values, are pushed onto the stacks LOWER and UPPER, respectively; and the reduction
step is applied to a sublist only after its boundary values are removed from the stacks.
Quick Sort Algorithm: The quicksort algorithm is divided into two parts. The first part gives a
procedure called QUICK, which executes the reduction step and the second part uses the procedure
sort the entire list.
Procedure: QUICK(A, N, BEG, END, LOC)
Step 1: [Initialize.] Set LEFT = BEG, RIGHT = END and LOC = BEG.
Step 2: [Scan from the right to left.]
a) Repeat while A[LOC] A[RIGHT] and LOC RIGHT:
RIGHT = RIGHT – 1.
23
Pass A[0] A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8]
K=1 -∞ 77 33 44 11 88 22 66 55
K=2 -∞ 77 33 44 11 88 22 66 55
K=3 -∞ 33 77 44 11 88 22 66 55
K=4 -∞ 33 44 77 11 88 22 66 55
K=5 -∞ 11 33 44 77 88 22 66 55
K=6 -∞ 11 33 44 77 88 22 66 55
K=7 -∞ 11 22 33 44 77 88 66 55
K= 8 -∞ 11 22 33 44 66 77 88 55
Sorted -∞ 11 22 33 44 55 66 77 88
To implement insertion sort algorithm, a sentinel element A[0] = -∞ (or very small number) used.
The insertion sort algorithm scans A from A[1] to A[N], inserting each element A[K] into its proper
position in previously sorted sub array A[1], A[2], ……, A[ K-1].
This sorting algorithm is frequently used when n is small. For example, this algorithm is very
popular with bridge players when they are first sorting their cards.
Algorithm: (Insertion Sort) INSERTION(A, N).
This algorithm sorts the array A with N elements
Step 1: Set A[0] = –. [Initializes sentinel element.]
Step 2: Repeat Steps 3 to 5 for K = 2, 3, ………., N
Step 3: Set TEMP = A[K] and PTR = K – 1.
Step 4: Repeat while TEMP < A[PTR]:
a) Set A[PTR + 1 ] = A[PTR]. [Moves element forward.]
b) Set PTR = PTR – 1.
[End of loop.]
Step 5: Set A[PTR + 1] = TEMP. [ Inserts element in proper place.]
[End of step 2 loop]
Step 6: Return.
2.2.9 Searching
24
Searching refers to finding the location of the record with a given value, or finding the locations of
all records which satisfy one or more conditions. It is one of the fundamental operations in
computer science and it frequently applied to a file of records.
Let DATA be a collection of data elements in memory, and suppose a specific ITEM of information
is given. Searching refers to the operation of finding the location of LOC of ITEM in DATA, or
printing some message that ITEM does not appear there. The search is said to be successful if ITEM
does appear in DATA and unsuccessful otherwise.
There are many different searching algorithms. The algorithm that one chooses generally depends
on the way the information in DATA is organized. Two important searching algorithms are linear
search, and binary search.
Binary Search
25
Suppose DATA is an array which is sorted in increasing numerical order or, equivalently,
alphabetically. Then there is an extremely efficient searching algorithm, called binary search, which
can be used find the location LOC of a given ITEM of information in DATA.
The binary search algorithm applied to the array DATA works as follows. During each stage of the
algorithm, the search for ITEM is reduced to a segment of elements of DATA:
DATA[BEG], DATA[BEG + 1], DATA[BEG + 2] …….. DATA[END]
The variables BEG and END denotes, respectively, the beginning and end location of the segment
under consideration. The algorithm compares ITEM with the middle element DATA[MID] of the
segment, where MID is obtained by
MID = INT ( ( BEG + END ) / 2 )
,
If DATA[MID] = ITEM, then the search is successful and we set LOC = MID. Otherwise a new
segment of DATA is obtained as follows:
i. If ITEM < DATA[MID], then ITEM can appear only in the left half of the segment:
2. It searches the given ITEM with each 2. It searches the given ITEM in the list, by
item of the list until a match occurs. reducing the elements of the list into segments.
4. It is one of the crudest search methods. 4. It is one the efficient search method.
27
2.3 Multi-Dimensional Arrays
Multi-dimensional arrays are classified into two-dimensional arrays, three-dimensional arrays and
so on N-dimensional arrays.
28
figure(a) figure(b)
29
3.1.1 Static Memory Allocation
The memory allocated during compile-time is called static memory allocation. The static memory is
allocated for the variables declared in a program by the compiler. This is done before program
execution. In static memory allocation, once the memory allocated, we cannot change its size.
1. The memory is allocated at the compile time The memory is allocated at the runtime
2. Static memory cannot be changed during Dynamic memory can be changed during
program execution program execution
3. In the static memory allocation, variables get In the Dynamic memory allocation,
allocated permanently, till the program variables get allocated only if your
executes or a function call finishes. program unit gets active
4. There is no memory re-usability in static There is memory re-usability and memory
memory allocation can be freed when not required
5. It saves running time as it is fast It is slower than static memory allocation
6. It is less efficient as compared to Dynamic It is more efficient as compared to the
memory allocation Static memory allocation
7. This memory allocation is simple This memory allocation is complicated
8. Static memory allocation allots memory from Dynamic memory allocation allots memory
the stack from the heap
9. Static memory allocation is preferred in an Dynamic memory allocation is preferred in
array the linked list
It allocates contiguous space in memory for 25 elements each with the size of the float.
31
This statement frees the space allocated in the memory pointed by ptr.
Information Link
Figure (1)
The first part contains the information of the element, and the second part, called the link field or
nextpointer field, contains the address of the next node in the list.
The figure(2), is a schematic diagram of a linked list, with 6 nodes. Each node is pictured with 2
parts. The left part represents the information part of the node, which may contain an entire record
of data items. The right part represents the next pointer field of the node. The pointer of the last
node contains, a special value, called the null pointer, which is any invalid address. The null pointer
is denoted by x in the diagram. The linked list also contains a list pointer variable called START to
point the first node in the list.
START
Example:
A hospital ward contains 12 beds, of which 9 are occupied as shown in the figure. Suppose we want
an alphabetical listing of the patients; this may be given by the pointer field, called Next in the
figure. We use the variable START to point to the first patient. Hence START contains 5, since the
first patient, AAA, occupies bed 5. Also AAA’s pointer is equal to 3, since DDD, the next patient,
32
occupies bed 3; DDD’s pointer is 11, since FFF, the next patient, occupies bed 11; and so on. The
entry for the last patient (SSS) contains the null pointer, denoted by 0.
START
33
It is the simplest type of linked list in which every node is divided into two parts called,
information field and next pointer field. The next pointer field means that the node stores the
address of the next node in the sequence. A single linked list allows the traversal of data only in
one way.
START
FIRST LAST
BACK pointer field of Node N
INFO field of Node N
FORW field of Node N
x x
Here, we observe that a NULL pointer appears in the FORW field in the last node, and for BACK
field it appears in the first field.
Advantages of Doubly Linked Lists
Using doubly linked list is we can traverse the list in both directions.
Insertion and deletion operations can be made very easily.
Doubly linked lists are used to represent binary trees.
Header node
Example: The following figure shows a linked list in memory where each node of the list contains a
single character
INFO LINK
START 1
9 2
3 O 6
4 T 0
5
6 K 11
7 X 10
8
9 N 3
10 I 4
11 E 7
12
36
traversing algorithm uses a pointer variable PTR which points to the node that currently being
processed.
Accordingly, LINK[PTR] points to the next node to be processed. Thus assignment
PTR = LINK[PTR]
moves the pointer to the next node in the list, as shown in the following figure.
PTR
ii. The following procedure finds the number NUM of elements in a linked list
Procedure: COUNT(INFO, LINK,START,NUM)
Step 1: NUM = 0 [Initializes counter]
Step 2: Set PTR = START [Initializes pointer]
Step 3: Repeat steps 4 and 5 while PTR NULL
Step 4: NUM = NUM + 1 [Increases NUM by 1]
Step 5: Set PTR = LINK[PTR] [Updates the pointer]
[End of step 3 loop] 37
Step 5: return
3.6.2 Searching in a Linked List
Searching refers to finding the location of the node in the linked list. There are two searching
methods;
i. Searching in unsorted linked list ii. Searching in sorted linked list.
i) LIST is unsorted
Let LIST be linked list in memory. If a specific ITEM of information is given. Searching refers to
find the location LOC of the node where ITEM first appears in LIST.
Suppose the data in LIST are not sorted. Then one searches for ITEM in LIST by traversing through
the list using a pointer variable PTR and comparing ITEM with the elements INFO[PTR] of each
node, one by one, of LIST. Before we update the pointer PTR by PTR = LINK[PTR] we require
two tests. First we have to check to see whether we have reached the end of the list. i.e. first we
check to see whether PTR = NULL. If not, then we check to see whether INFO[PTR] = ITEM.
Searching Algorithm (Unsorted)
The following algorithm find the location LOC of the node where the ITEM first appears in a linked
list called LIST or sets LOC = NULL.
Algorithm: SEARCH (INFO, LINK, START, ITEM, LOC)
Step 1: Set PTR = START
Step 2: Repeat step 3 while PTR NULL
Step 3: If ITEM = INFO[PTR] then:
Set LOC = PTR and Exit
Else: Set PTR = LINK[PTR]. [PTR now points to the next node.]
[End of step 2 loop]
Step 4: [Search is unsuccessful?] Set LOC = NULL
Step 5: Exit
Node A Node B
x
Node A Node B
x
Node N
Figure 2 (b) After insertion
The above figure does not take into account into that memory space for the new node N will come
from the AVAIL list. Specifically, for easier processing, the first node in the AVAIL list be used for
the new node N. Thus a more exact schematic diagram of such an insertion is that in figure 2.
Here we observe that three pointer fields are changed as follows:
1. The nextpointer field of node A now points to the new node N, to which AVAIL previously
pointed.
2. AVAIL now points to the second node in the free pool, to which node N previously pointed.
3. The nextpointer field of node N now points to node B, to which node A previously pointed.
START Data list
Node A Node B
x
AVAIL
39
Node N
x
Free-storage list
Insertion Algorithms
Algorithms which insert into linked lists come up in various situations. We can insert a node in two
different ways. The first one inserts a node at beginning of the list, and the second one inserts a node
the node with a given location. All the algorithms assume that the list is in memory in the form
LIST(INFO, LINK, START, AVAIL) and the variable ITEM contains the new information to be
added to the list.
START
AVAIL
41
x
Free-storage list
Deletion Algorithms
Algorithms which delete nodes from linked lists come up in various situations. We can delete a
node in two different ways. The first one deletes the node following a given node, and the second
one deletes the node with a given ITEM of information. The algorithms assume that the linked list
is in memory in the form LIST (INFO, LINK, START, AVAIL).
The garbage collector (GC) manages the allocation and release of memory. The garbage collector
serves as an automatic memory manager. That means the programmers do not need to know how to
allocate and release memory or manage the lifetime of the objects that use the memory.
GC implementation requires three primary approaches, as follows:
Mark-and-sweep: In process when memory runs out, the GC locates all accessible memory
and then reclaims available memory.
Reference counting: Allocated objects contain a reference count of the referencing number.
When the memory count is zero, the object is garbage and is then destroyed. The freed
memory returns to the memory heap.
Copy collection: There are two memory partitions. If the first partition is full, the GC locates
all accessible data structures and copies them to the second partition, compacting memory
after GC process and allowing continuous free memory.
43
Unit-4: Stacks and Queues
4.1 Stacks
Stack is one of the most useful concepts in computer science. Stacks are used whenever we want to
restrict insertions and deletions so that they can take place only from one end.
4.1.1 Definition: A stack is linear list of elements in which an element may be inserted or deleted
only at one end, called the top of the stack. This means, the elements are removed from a stack in
the reverse order of that in which they were inserted into the stack. Therefore, stacks are also called
LIFO (last-in-first-out) lists. Other names used for stacks are “Piles” and “Push-down lists”.
Examples of stacks are Stack of dishes, Stack of coins, Stack of folded towels etc.
Special terminology is used for two basic operations associated with stacks:
i. “Push” is the term used to insert an element into a stack.
ii. “Pop” is the term used to delete an element from a stack.
Note: These terms are used only with stacks, not with other data structures.
Example: Suppose the following 6 elements are pushed in order, onto an empty stack:
AAA, BBB, CCC, DDD, EEE, FFF
The following figure shows 3 ways of representing such a stack. For notational convenience, we
will frequently designate the stack by writing:
STACK: AAA, BBB, CCC, DDD, EEE, FFF
The right-most element is the top element and according to the property of stacks, insertions and
deletions can occur only at the top of the stack. This means EEE cannot be deleted before FFF is
deleted, DDD cannot be deleted before EEE and FFF are deleted, and so on. Consequently, the
elements may be popped (deleted) from the stack only in the reverse order of that in which they were
pushed (inserted) onto the stack.
1 AAA
2 BBB
TOP 3 CCC TOP
4 DDD
5 EEE
FFF
6 FFF
EEE 7
DDD 8
CCC
(a) (b)
BBB N-1
44
AAA N
AAA BBB CCC DDD EEE FFF
1 2 3 4 5 6 7 8 9 N-1 N
TOP
(c)
4.1.2 Representation and Primitive operations on Stack
Stacks may be represented in the computer in various ways, usually by means of one-way lists or a
linear array. More often a stack will be maintained by linear array.
Let STACK be a linear array, TOP be a pointer variable which contains the location of the top
element of the stack and MAXSTK is a variable, which gives the maximum number of elements that
can be held by the stack. The condition TOP = 0 or TOP = NULL will indicate that the stack is
empty.
An array representation of a stack is as shown in the following figure. Since TOP = 3, the stack has
3 elements, XXX, YYY, ZZZ and MAXSTK= 8, there is room for 5 more items in the stack.
The primitive operations PUSH (adding) and POP (removing) can be performed as follows:
The operation of adding (pushing) an item onto a stack and the operation of removing (popping) an
item from a stack may be implemented, respectively, by the following procedures, called PUSH and
POP. In executing the procedure PUSH, one must first test whether there is room in the stack for the
new item; if not, then we have the condition known as overflow. Analogously, in executing the
procedure POP, one must first test whether there is an element in the stack to be deleted; if not, then
we have the condition known as underflow.
An expression where an operator follows the two operands is called postfix expression. The
notation of postfix expression is
<operand> <operand> <operator>
Example: AB+, CD–, EF*, GH/, etc.
An expression where an operator precedes the two operands is called prefix expression. The
notation of prefix expression is
<operator> <operand> <operand>
Example: +AB, – CD, *EF, /GH, etc.
We can convert expressions from one form to other. While evaluating or converting an expression
into other forms, one should know the hierarchy of operators and whether they are left associative or
right associative. Consider the infix expression;
46
((A+(B–C)*D)^E+F)
Here, parenthesis is having higher precedence, next comes the exponentiation represented as ^, then
multiplication or division whichever comes first from left to right and finally the addition and
subtraction whichever comes first from left to right.
b. Add ⊗ to STACK. 47
[ End of If structure]
Step 6: If a right parenthesis is encountered then:
a. Repeatedly POP from STACK and add to P each operator (on TOP of STACK)
Example: Consider the following arithmetic infix expression
Q: A + ( B * C – ( D * E ^ F ) + G ) * H
We simulate the algorithm to transfer Q into its equivalent Postfix expression P.
First we PUSH ‘(‘ onto the STACK then we add ‘)’ at the end of Q to obtain equivalent Postfix
expression P.
Sl. No. Symbol Scanned STACK Expression P
1. A ( A
2. + (+ A
3. ( (+( A
4. B (+( AB
5. * (+(* AB
6. C (+(* ABC
7. – (+(– ABC*
8. ( (+(–( ABC*
9. D (+(–( ABC*D
10. / (+(–(/ ABC*D
11. E (+(–(/ ABC*DE
12. ^ (+(–(/^ ABC*DE
13. F (+(–(/^ ABC*DEF
14. ) (+(– ABC*DEF^/
15. * (+(–* ABC*DEF^/
16. G (+(–* ABC*DEF^/G
17. ) (+ ABC*DEF^/G*–
18. * (+* ABC*DEF^/G*–
19. H (+* ABC*DEF^/G*–H
20. ) -- ABC*DEF^/G*–H*+
b. Evaluate B ⊗ A.
next-to-top element.
50
4.2.3 Applications of Queues
Queues have the following applications
1. Queues are used in computer simulation of a real world situation.
2. They are also used in many ways by the operating system. The program that schedules and
allocates the resource of computer systems uses the concept of queues.
3. In a computer system network messages from one computer to another can be sent by using
queues by sorting them in queues.
4. Queues are used on time sharing system in which programs form a queue while waiting for
execution.
5. In a multi user system, the programs of higher priority are processed first and programs of lower
priority are processed next by forming a queue.
4.2.4 Representation of Queues
Queues may be represented in the computer in various ways, usually by means of one-way lists or
linear arrays. Usually a queue is maintained in a linear array. Let QUEUE be a linear array and
pointer variables FRONT and REAR, respectively, containing the location of the front element, and
the location of the rear element of the queue. The FRONT = NULL will indicate that the queue is
empty.
The following figure shows the way the array QUEUE with N elements will be stored in memory. It
also indicates the way elements will be deleted from the queue and the way new elements will be
added to the queue. Whenever an element is deleted from the queue, the value of FRONT is
increased by 1; this can be implemented by the assignment
FRONT = FRONT + 1
Similarly, whenever an element is added to the queue, the value of REAR is increased by 1; this can
be implemented by the assignment
REAR = REAR +1
This means that after N insertions, the rear element of the queue will occupy QUEUE[N] or, in other
words, eventually the queue will occupy the last past of the array. This occurs even though the
queue itself may not contain many elements.
QUEUE
FRONT: 1
REAR: 4
AAA BBB CCC DDD …..
1 2 3 4 5 6 7 ….. N
(a)
QUEUE
FRONT: 2
BBB CCC DDD …..
REAR: 4
1 2 3 4 5 6 7 ….. N
(b)
QUEUE
FRONT: 2
BBB CCC DDD EEE FFF …..
REAR: 6
1 2 3 4 5 6 7 ….. N
(c)
QUEUE
51
FRONT: 3
CCC DDD EEE FFF …..
REAR: 6
1 2 3 4 5 6 7 ….. N
(d)
Suppose we want to insert an element ITEM into a queue at the time the queue does occupy the last
part of the array, i.e., when REAR = N. One way to do this is to simply move the entire queue to the
beginning of the array, changing FRONT and REAR accordingly, and then inserting ITEM as
above. This procedure may be very expensive. The procedure we adopt is to assume that the array
QUEUE is circular, that is, that QUEUE[1] come after QUEUE[N] in the array. With this
assumption, we insert ITEM into the queue by assigning ITEM to QUEUE[1]. Specifically, instead
of increasing REAR to N +1, we reset REAR = 1 and then assign
QUEUE[REAR] = ITEM
53
3. Priority Queues
A priority queue is a collection of elements such that each element has been assigned a priority and
such that the order in which elements are deleted and processed comes from the following rules:
1. An element of higher priority is processed before any element of lower priority.
2. Two elements with the same priority are processed according to the order in which they
were added to the queue.
In other words, the priority queue is a special type of data structure in which items can be inserted or
deleted based on the priority. The different type of priority queues are
i. Ascending priority queue
ii. Descending priority queue
In an ascending priority queue elements can be inserted in any order. But, while deleting an element
from the queue, remove only the smallest element first. In descending priority queue, also the
elements can be inserted in any order. But, while deleting an element from the queue, only the
largest element is deleted.
Unit 5: Trees
5.1 Basic Terminology of Trees
Arrays, Stacks, Queues and Linked Lists are called linear data structure, because the elements are
arranged in a linear fashion. These data structures and their relationships are invariably expressed
using single dimension. Another very useful data structure is tree, where elements appear in a non-
linear fashion, which require two-dimensional representation. A tree is called a nonlinear data
structure. This structure is mainly used to represent data containing a hierarchical relationship
between elements, for example, records, family trees, and tables of contents.
5.2 Definition: A Tree T is a set of nodes such that,
i) there is a specifically designated node called root, and
ii) remaining nodes are partitioned into disjoint set of nodes
Example:
A
B C D
G H I E F
This is a tree because, it has a set of nodes {A, B, C, D, E, F, G, H, I} with node A as root and three
disjoint sets {B, G, H, I}, {C, E, F}, and {D}. Each of these sets is a tree individually because, they
satisfy above properties.
5. 3 Degree of a node of a tree
Degree of a node of a tree is the number of subtrees having that node as a root, or it is a number of
decedents of nodes. If degree is zero then it is called a terminating node of a tree.
54
5.4 Uses of Tree
Following are the common uses of tree.
1. Tress can be used to store and manipulate the hierarchical data.
2. They are used to organize data for efficient insertion, deletion and searching.
2. Using trees we can easily search and sort with the standard traversal algorithms.
3. To manipulate stored lists of data.
4. Used as a workflow for composing digital images for visual effects.
5. A special tree called Trie is used to store the dictionary. It is a fast and efficient way for dynamic
spell checking.
6. Using Heap trees we can implement priority queues.
7. The B-tree and B+ tree structures are used to implement indexing in datatbases.
8. The tree data structures is also used to store the data in routing tables in the routers.
5.5 Binary Trees
5.5.1 Definition: A binary tree is a finite set of elements that is either empty or is partitioned into
three disjoint subsets. The first subset contains a single element called the root of the tree. The
other two subsets are themselves binary trees, called the left and right subtrees of the original tree.
A left or right subtree can be empty. Each element of a binary tree is called node of the tree.
In general, a binary tree T is defined as finite set element, called nodes, such that:
a) T is empty (called the null tree or empty tree), or
b) T contains a distinguished node R, called the root of T, and remaining nodes of T form an
ordered pair of disjoint binary trees T1 and T2.
Example: If T does contain a root R, then the two trees T 1 and T2 are called, respectively, the left
and right subtrees of R. If T1 is nonempty, then its root is called the left successor of R; similarly, if
T2 is nonempty, then its root is called the right successor of R.
A binary tree T is frequently presented by means of a diagram. Specifically, the diagram in the
following figure represents a binary tree T as follows.
i. T consists of 11 nodes, represented by the letters A through L, excluding I.
ii. The root of T is the node A at the top of the diagram.
iii. A left-downward slanted line from N indicates a right successor of N
Here we observe that:
a) B is a left successor and C is right successor of the node A.
55
b) The left subtree of the root A consists of the nodes B, D, E and F, and the right subtree of A
consists of the nodes C, G, H, J, K and L.
Any node N in a binary tree T has 0, 1 or 2 successor. The nodes A, B, C and H have two
successors, the nodes E and J have only one successor, and the nodes D, F, G, L and K have no
successors. The nodes with no successors are called terminal nodes.
A
B C
D E G H
F J K
L
5.5.2 Terminology
Terminology describing family relationships is frequently used to describe relationships between the
nodes of a tree T. Specifically, suppose N is a node in T with left successor S1 and right successor
S2. Then N is called the parent (or father) of S1and S2. Analogously, S1 is called the left child (or
son) of N, and S2 is called the right child (or son) of N. Furthermore, S1and S2 are said to be siblings
(or brothers). Every node N in a binary tree T, except the root, has a unique parent, called
predecessor of N.
Root: Root is a special node in a tree. The entire tree is referenced through it. It does not have a
parent.
Parent Node: Parent node is an immediate predecessor of a node.
56
Child Node: All immediate successors of a node are its children.
Siblings: Children of same parents, or nodes with the same parent are called Siblings
Edge: The line drawn from a node N of T to a successor is called an edge.
Path: A sequence of consecutive edges is called a path or it is a number of successive edges from
source node to destination node
Leaf and Branch: A terminal node is called a leaf, and path ending a leaf is called a branch.
Level Number: Each node in a binary tree T is assigned a level number, as follows:
The root R of the tree T is assigned the level number 0 and every other node is assigned a level
number which is 1 more than the level of number of its parent. Furthermore, those nodes with the
same level number are said to belong to the same generation.
Height of a tree: The depth (or height) of a tree T is the maximum number of nodes in a branch of
T. This turns out to be 1 more than the largest level number of T. The tree in the above figure has
depth 5.
Degree of a node: Degree of a node represents a number of children of a node.
B F B F
C D G H C D G H
(a) (b) (c) (d)
In the above figure, the trees (a) and (c) and (d) are similar. In particular, (a) and (c) are copies of
each other, since they have same data at corresponding nodes.
The tree (b) is neither similar nor copy of tree (d) because, in a binary tree we distinguish between
left and right successor even when there is only one successor.
57
5.5.5 Extended Binary trees or 2-tree
A binary tree T is said to be an extended binary tree or a 2-tree, if each node N has 0 or 2 children.
The nodes with 2 children are called internal nodes
The nodes with 0 children are called external nodes.
The internal nodes are represented by circles and the external nodes are represented by squares.
Example: Consider, a binary tree T as shown figure (a), the tree T may be converted into a 2-tree by
replacing each empty subtree by a new node as shown in figure (b).
fig (a)
fig(b)
5.5.6
58
A binary tree T can be represented in memory in two different ways. The first and usual way is
called the link representation of T, and the second way, which uses a single array, called the
sequential representation of T. The main requirement of any representation of T is that one should
have direct access to the root R of T and, given node N of T, one should have direct access to the
children of N.
5.5.7 Linked Representation of Binary Trees
Consider a binary tree T. T will be maintained in memory by means of a linked representation
which uses three parallel arrays; INFO, LEFT and RIGHT, and a pointer variable ROOT as follows.
First of all, each node N of T will correspond to a location K such that:
1. INFO[K] contains the data at the node N.
2. LEFT[K] contains the location of the left child of node N.
3. RIGHT[K] contains the location of the right child of node N.
Furthermore, ROOT will contain the location of the root R of T. If any subtree is empty, then the
corresponding pointer will contain the null value; if the tree T itself is empty, then ROOT will
contain the null value.
Example: Consider a binary tree T consists of 11 nodes, represented by the letters A through L,
excluding I.
B C
D E G H
F J K
ROOT
B C
x D x E x x G x H
x F x J x x K x
x L x
59
INFO LEFT RIGHT
ROOT 1 K 0 0
5 2 C 3 6
3 G 0 0
AVAIL 4 14
8 5 A 10 2
6 H 17 1
7 L 0 0
8 9
9 4
10 B 18 13
11 19
12 F 0 0
13 E 12 0
14 15
15 16
16 11
17 J 7 0
18 D 0 0
19 20
20 0
We observe that each traversal operation contains the same three steps, and that the left subtree of R
is always traversed before the right subtree. The difference between these traversals is the time at
which the root R is processed. Specifically, in the “pre” traversal, the root R is processed before the
subtrees are traversed; in the “in” traversal, the root R is processed between the traversals of the
subtrees; and in the “post” traversal, the root R is processed after the subtrees are traversed.
These traversals are sometimes called, respectively, the node-left-right (NLR) traversal, the left-
node-right (LNR) traversal and the left-right-node (LNR) traversal.
60
Example: Consider the binary tree T as shown in the following figure. Here we observe that A is
the root, that its left subtree L T consists of nodes B, D and E and that its right subtree R T consists of
nodes C and F.
B C
LT RT
D E F
i. Preorder traversing
The preorder traversal of T process A, traverses LT and traverses RT. However, the preorder
traversal of LT processes the root B and then D and E, and the preorder traversal of R T processes the
root C and then F. Hence ABDECF is the preorder traversal of T.
61
Sometimes it is required construct a binary tree its traversals are known. From a single traversal, it
is not possible to construct a unique binary tree. However, if two traversals are known then the
corresponding tree be drawn uniquely. The basic principle for constructing a binary tree are stated
as follows;
If the preorder traversal is given, then the first node is the root node. If the postorder
traversal is given, then the last node is the root node.
Once the root node is identified, all the nodes in the left sub-trees and the right sub-trees of
the root node can be identified
The same technique can be applied repeatedly to form sub-trees.
Note: To construct a binary tree it is essential to have two traversals, out of which one should be
inorder traversal and another may be preorder or postorder.
a3, a4, a5
a1 a4 a7
a3 a5 a8
(In) n1 n2 n3 n4 n5 n7 n8 n9 (In)
(Post) n1 n3 n5 n4 n2 n8 n7 n9 (Post)
n1 (In) n3 n4 n5 n7 n8 (In)
(Post) n3 n5 n4 n8 n7 (Post)
n3 n5 n8
n2 n9
63
n1 n4 n7
n3 n5 n8
5, 1, 3, 9 8, 4, 2, 7
1 4
64
3, 9 2, 7
5 9 8 7
3 2
Example 5: Construct a binary tree from the following traversal
Inorder : E A C K F H D B G
Preorder: F A E K C D H G B
To construct the binary tree, following steps need to be followed.
1. From the preorder traversal, it is clear that F is the node.
2. In inorder traversal, the nodes are on the left side of F belongs to left sub-tree and the nodes on right
side of F belongs to the right sub-tree.
3. Now the same problem reduces to form sub-trees and the same procedure can be applied repeatedly.
Following figure illustrate this procedure.
E A C K F H D B G (In)
F A E K C D H G B (Pre)
(In) E A C K H D B G (In)
(Pre) A E K C D H G B (Pre)
E (In) C K H B G (In)
(Pre) K C G B (Pre)
C B
A D
E K H G
C B
(b) Final binary tree
5.6 Expression tree
An expression tree is a binary tree which stores an arithmetic expression. The leaves of an expression are
operands, such as constants or variable names, and all internal nodes are the operators.
65
5.7 Binary Search Trees (BST)
A binary tree T is called a binary search tree or binary sorted tree, if each node N of T has the following
property;
The value at N is greater than every value in the left subtree of N and is less than every value in the right
subtree of N.
66