0% found this document useful (0 votes)
13 views130 pages

Data Structures Notes

Uploaded by

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

Data Structures Notes

Uploaded by

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

DATA STRUCTURE

DATA STRUCTURE AND ALGORITHMS


UNIT 1
CHAPTER 1: ALGORITHM
Algorithm
 Algorithm is a step by step procedure to solve a given problem. The word algorithm is
derived from the name of 9thcentury Arab mathematician Abu Jafar Mohammed Ibn
Musa Al Khowarizmi.
 It is a finite, clearly specified sequence of instructions to be followed to solve a problem.

Classification of Algorithm
 Sequential construct: in sequential construct program statements are execution of
statements one after another in a sequence.
Ex: 1. Input statement: input a, b, c
2. Assignment: c <- a + b
3. Output statement: output a, b, c

 Selection construct: it is also known as conditional construct. It is used to indicate


decision in a program. They are different kinds of selection constructs and execution of
statements is on the basis of the condition.
Ex: 1. If
2. If then else
3. If then else if
4. Nested if
5. Multiple selection switch

 Iteration construct: if some of the statements have to be executed repeatedly we can use
repetitive constructs to perform much iteration. There are two types of looping
constructs:

1
DATA STRUCTURE

Ex: 1. Conditional looping: many programs require that a group of consecutive


instructions be executed repeatedly until some logical condition has been satisfied. The required
number of repetitions will not be known in advance. The two conditional looping constructs are:
 While do
 Do while

2. Unconditional looping: here the execution of group of consecutive instructions is repeated


some specified number of times.
 For loop

Example:
Algorithm: Area of the circle
step 1: read radius
step 2: [compute the area]
Area=3.14*radius*radius
step 3: [print the area]
Print “Area of a circle = area”
step 4: [end of algorithm]
Stop

Characteristics of an Algorithm
 Finiteness: each step in algorithm terminates after a finite number of steps.
 Definiteness: each step in algorithm is unambiguous. This means that the action
specified by the step cannot be interpreted in multiple ways and can be performed
without any confusion.
 Input: an algorithm accepts zero or more inputs.
 Output: it produces at least on output
 Effectiveness: it consists of basic instructions that are realizable. This means that the
instructions can be performed by using the given inputs in a finite amount of time.

2
DATA STRUCTURE

 Efficiency: algorithm efficiency is a measure of the average execution time necessary for
an algorithm to complete work on a set of data.

3
DATA STRUCTURE

Algorithmic notations
 Name of the algorithm
 Step number
 Explanatory comment
 Termination

Efficiency of an Algorithm
Algorithm efficiency is measured by the complexity function ‘T(n)’ and ‘n’ the size of the
algorithm’s input.

Time complexity: Time complexity of an algorithm is the amount of computer time needed to
complete the execution. “Time” can mean the number of memory accessing is performed, the
number of comparisons between integers, the numbers of times the inner loop is executed, or
some other natural unit related to the amount of computer of real time the algorithm will take.

Space complexity: Space complexity is function describing the amount of memory (space) an
algorithm takes in terms of the amount of input to the algorithm.

Worst case: It gives the maximum value of T(n) for any possible input. The worst case occurs
when element is found at last position / not found at any position.
Tworst(n) = n

Best case: It gives the minimum of T(n) for any possible input. The best case occurs when the
element to be searched is found at first location.
Tbest(n) = 1

Average case: it gives the expected value of T(n). The following assumptions are made to find
the average case.
 The probility of successful search is P(where 0<=P<=1)
 The probility of first match occurs in ith position of the array is the same of every i

4
DATA STRUCTURE

 In case of successful search, the probility of first match occurs in i th position of the array
is P/n for every i
 In case of successful search, the number of comparisons is ‘n’ with probility of such a
search being (1-P).
Taverage(n) = (p(n+1)/2)+(n(1-p))
Where P=1, search successful and Taverage(n) = (n+1)/2
P=0, search successful and Taverage(n) = n

Asymptotic notation
The Asymptotic efficiency of algorithms are concerned with how the running program
increases with the size of the input ‘m’ the input limit as the size of the input increases without
bound.

Several asymptotic notations


 Big-Oh notation(O)
 Omega notation(Ω)
 Theta notation(Ɵ)

Big-Oh notation (O): it is upper bound of function. The function f(n) will be considered for
worst case that it does not consume more than this computing time.
The names of common Big-Oh expression are,
EXPRESSION NAME
O(1) Constant
O(log n) Logarithmic
O(log2n) Log squared
O(n) Linear
O(n log n) N log n
O(n2) Quadratic
O(n3) Cubic
n
O(2 ) Exponential
Omega notation (Ω): it is used to find the lower bound behavior of f(n). The lower bound
implies that below the given time the algorithm cannot perform better. The function f(n) will be
considered for average case.

5
DATA STRUCTURE

Theta notation (Ɵ): it can be used when function f(n) is bounded both from above and below,
where upper and lower bound are same. In finding maximum and minimum element in an array,
the computing time is O(n) and Ω(n). There exists a notation Ɵ. The function f(n) will be
considered for best case.

6
DATA STRUCTURE

CHAPTER 2: DATA STRUCTURE

Definition of Data Structure


 Data Structure is an organized collection of related data items that are treated one by the
system.
 It is a systematic way of organizing and accessing data.
 Data Structure, d = (D, K, A)
It’s a triple comprising set of domain/data objects D, a set of functions/operations K, and
a set of axioms/postulates A.
 Data Structure is a representation of logical relationship between individual elements
of data. In other words, it is a way of organizing all data items and specifying their
relationship to each other.

Need for Data Structures


The computers are electronic data processing machines. In order to solve a particular problem we
need to know
 How to representation the data (efficiently stored and organized in the memory) in
computer?
 How to access (efficiently data can be retrieved and manipulated) them?
 The possible ways in which different data items are logically related.
 What are the steps to be performed to get the needed output?
These tasks can be achieved with the knowledge of data structures and algorithms.

7
DATA STRUCTURE

Classification of Data Structures

Goals of data Structures


 Correctness: a data structure designed using a high level language should work correctly
for all possible inputs.
 Efficiency: accessing of data. The designed data structure should be fast and should not
use more computer resources like memory space. i.e., minimum use of computers time
and space.

8
DATA STRUCTURE

 Robustness: program developed using the specific data structure should produce correct
outputs for all inputs when executed on all hardware platforms.
 Adaptability: modern software should also be able to adapt the data structure designed.
 Re-usability: software developed using data structure can be reusable in future software
applications thus reducing cost and time of software development.

9
DATA STRUCTURE

Primitive Data Structure and its types


Primitive data structures, which are readily available in a programming language i.e., they can be
operated upon by programming language or directly manipulated (operated) upon by machine
level instructions.

 Integer: it is a simple type data which when created is used to store integer values. When
this type is used we can store only numeric value at a time. But values can be varied at
any point of time.
a) Sign and magnitude method
b) Radix complement representation
c) Diminished complement representation Storage structure
d) Pure BCD representation
Note: Storage Structure is the representation of a particular structure in the memory of a
computer. It is also known as memory representation.

 Real/Floating-point numbers: it is also a simple type data like integer, but here
fractional or real values are stored.
a) Fixed decimal point representation
b) Floating point representation

 Character: it is a non-numerical data type which can store only one character at a time.
a) ASCII(American Standard Code for information Interchange)
b) EBCDIC(Extended Binary Coded Decimal Interchange Code)

 Logical data/ Boolean number: it is a data type which can store only two possible
values such as true/false, 0/1, high/low.

 Pointer data/Links: it is a reference to a data structure, also a data type which stores the
address of the other data element.

10
DATA STRUCTURE

Operations on Primitive Data Structure


 Creation operation: it is used to create a storage representation for a particular data
structure. This operation is normally performed with the help of a declaration statement
in the programming language.
Ex: In ‘C’ using declaration statement.
int k = 45; 1010 45 k
address value name

 Destroy operation: complementary effect of creation is one which destroys or


disassociate the created data structure from its storage representation. In some languages
this operation is not supported or it is automatically performed.
Ex: In ‘C’ one can destroy (de-allocation) by using the function called free(). This aids in
efficient use of memory.

 Selection operation: it is used to access data within a data structure. For complex
structures method of access is one of the important properties of a structure. In case of
files the access can be sequential or random depending on the nature of files.
Ex: scanf(“%d”, &a);

 Updation operation: this operation is used to change or modify data value of the
element in the structure. An Assignment operator is a good example of an update
operation.
Ex: y = 5; //modifies the value of y to store the new value 5 in it.

Non-Primitive Data Structure and its types


Data Structure which are not readily available in a programming language i.e., they cannot be
manipulated (operated) directly by machine instructions (programming language) but which are
not primitive in nature. They are created by using primitive data structure. The storage
representation and possible operations for these types are not predefined and user has to define
them. The different non-primitive data structures are array, stacks, queue, files and linked list. It
is classified into Linear and Non-linear data structure.

11
DATA STRUCTURE

Classification of non-primitive data structure


 Linear Data Structure: in which every data elements can exhibits adjacent between
elements. The concept adjacency may indicate either a linear or sequential relationship.
Ex: arrays, string, stacks, queues and linked lists.
 Non-linear Data Structure: in which every data elements can exhibit adjacent between
two elements. It is possible to derive any relationship other than adjacency. It can exhibit
a either a hierarchical relationship or parent child relationship. Ex: trees, graphs and
tables.

Linear Data structures


In linear data structure, the elements are stored in sequential order. They are,
 Array: it is a collection of data of same data type stored in consecutive memory location
and is referred by common name.
 Linked list: it is a collection of data of same data type but the data items need not be
stored in consecutive memory locations.
 Stack: it is a Last-In-First-Out linear data structure in which insertion (called as push)
and deletion (called as pop) takes place at only one end called the top of the stack.
 Queue: it is a First-In-First-Out linear data structure in which insertions takes place at one
end called the rear and the deletions takes place at one end called the front.

Non-Linear Data Structure


In non-linear data structure, elements are stored based on the hierarchical relationship among the
data. They are:
 Trees: it is used to represent data that has some hierarchical relationship among the data
elements.
 Graph: it is used to represent data that has relationship between pair of elements not
necessarily hierarchical in nature.

Operations on Non-Primitive Data Structure

12
DATA STRUCTURE

 Traversing: it is the process of visiting each element in the data structure exactly to
perform certain operation on it.
 Sorting: it is the process of arranging the elements of a particular data structure in some
logical order. The order may be either ascending or alphabetic order depending on the
data item present.
 Merging: it is the process of combing the elements in two different structures into a
single structure.
 Searching: it is the process of finding the location of the element with given key value in
a particular data structure or finding the location of an element, which satisfies the given
condition.
 Insertion: it is the process of adding a new element to the structure. Most of the times
this operation is performed by identifying the position where the new element is to be
inserted
 Deletion: it is the process of removing an item from the structure

Difference b/w Linear & Non-Linear Data Structure


 In Linear Data Structure only one link connects two nodes, the two nodes being the
predecessor node and successor node as shown below:

Where as in the case of Non-Linear data structure, a node be connected to more than one
successor and one predecessor as shown below:

For node 2, we have one predecessor and two successors i.e., node4 and node5.
 The Linear Data Structure exhibits adjacency relationship where as non - linear data
structure exhibits hierarchical/parent- child relationship.

13
DATA STRUCTURE

CHAPTER 3: ARRAYS
Definition of Arrays
 An array is a type of linear data structure consisting of finite number of
similar/homogeneous objects. Here we can derive linear relationship between the
elements because elements are arranged one after the other.
 It is an ordered list of homogeneous data elements.
 It is defined as a set a set of homogeneous data items, in which variable holds multiple
values of the same data types.

Classification of Arrays
 One-Dimensional / Single / Linear Array
 Multi-Dimensional Array
o Two-Dimensional Array
o Three-Dimensional Array
o n-Dimensional Array

Operations on an Array
 Traversal: processing each element in an array exactly once.
 Search: find the location of element with a given value in an array
 Insertion: inserting an element into an array (Note: size of the array does not change).
 Deletion: deleting an element from an array (Note: size of the array does not change).
 Sorting: arranging the elements in some type or particular order (ascending / descending)
 Merging: combine one or more arrays to form a single array.

Linear array [one-dimensional]


It s a finite set of homogenous data elements of size N
 The elements are referenced by index or subscript consisting of N consecutive
numbers.
 Elements are stored in successive memory locations called the length of the array.

14
DATA STRUCTURE

 All elements have same array name.


Or
An array that can have only one subscript which can be used as a linear set of values is called
one dimensional array.

Declaration of an one-dimensional array (Linear)


Syntax: data_type array_name[size];
For ex: int list [10];
In the above example, int specifies the type of the variable, list specifies the name of the variable
and the value in bracket [10] is the size of the array. The bracket ( [ ] ) tells the complier that it is
an array and number mentioned in the bracket specifies that how many elements it can store.
This number is called dimension of array.

Initialization and assignment of an array


Initializing and assigning values to the arrays is the same way as it is done with other
variable. We can assign value to an array at the time of declaration or during runtime.
Syntax: data_type array_name[size] = {ele 1, ele 2,… ele n};
For ex: int num [5] = {2, 4, 6, 8, 10};
int arr [ ] = {1, 2, 3, 4};
We can see memory arrangement of above declared array as follows:

1 2 3 4
arr

arr[0] arr[1] arr[2] arr[3]


In the above example, we declare an integer array and named it “num” which holds 5
elements, also initialized with array elements.
Both the above example are valid method to declare and initialize single dimensional
array. In first example, we mention the size (5) of an array and assigned it values in curly braces
({}), separating element’s value by comma (,). But the second example, size field is left blank
but we provided its element’s value. When we only give element values without providing size
then C compiler automatically assumes its size from the given element values.

15
DATA STRUCTURE

16
DATA STRUCTURE

Processing of an array
Single operation involving entire array are not permissible in C. But, it allows the programmer to
perform certain operations (comparison, assignment) on an element – by – element basis.

The length of the array is obtained by the formula


LENGTH = UB – LB + 1
Where UB is the upper bound and LB is the lower bound.

Ex: Let num[4], here UB=3 and LB=0, hence the LENGTH = 3 – 0 + 1 = 4. Here index set is an
integer. The elements of array are num[0], num[1], num[2], num[3].

Memory representation of linear array


Let A be an array of size N as shown below
a[i] 50 55 60 65 70

a[1] a[2] a[3] a[4] a[5]


It can be represented in memory by N sequential memory locations. Since the memory locations
are sequential, it computes the address of each memory location by the following formula:
Syntax: Loc [a(k)] = base (a) + w (K - LB)
Where Location of a(k) = base address of the array ‘a’ + No of words per memory location(K -
lower bound)

Ex: Consider an array A of size 10. Suppose this is stored at the storage address 200 with two
words per memory. Find the address of A[4].

Sol: By applying the formula


Loc [A(k)] = base (A) + w (K - LB)
Lower bound = 0 and Base(A) = 200
Loc(A[4]) = 200 + 2(4 - 0)
= 200 + 8
= 208.

17
DATA STRUCTURE

Memory representation is shown below:

Traversing one dimensional array


Traversing operation is nothing but visiting each element exactly once and performing some
processing. Here we have to access all elements of the array. For example, printing all the
elements of an array is the traversing operation.

Algorithm for traversing


Let A be a linear array with LB (lower bound) and UB (upper bound). This algorithm traverses
an array A by applying an operation PROCESS to each element of A.
1. for i LB to UB do
2. Apply PROCESS to a[i]
end for
3. end

18
DATA STRUCTURE

Algorithm for printing elements of an array of size N


1. if n==0 then
write “Empty Array”
else
write “The Array is”
for i 0 to n do
write “a[i]”
end for
end if
2. end

Insertion
An element can be inserted into the array provided the memory space allocated for the array is
large enough to accommodate the additional element. Inserting an element at the end of the array
does not require any movement of data. On the other hand, if an element is inserted in the middle
of the array, then on the average half of the element must be moved one location downward to
new locations to accommodate the new element and keep the order of the other elements.

Ex: Consider an array of 6 elements. To add an element 35 into location 4, all elements from
A[4] have to be moved downwards. For this consider an array A which can store maximum 10
elements. Let the length of the array be 6. i.e., N=6. i.e., out of 10 memory locations we are using
only 8 of it as shown below:

19
DATA STRUCTURE

An algorithm to insert an element into the Kth position in A


1. read ele, pos
2. if pos-1<=n then
for i n down to pos do // for(i=n-1;i>=pos-1;i--)
a[i+1] a[i] //moving element downward
end for
a[pos-1] ele //insert element at kth position
n++ //increment number of elements by 1
write “Element Inserted”
else
write “Invalid Position”
end if
3. end

Deletion
As in insertion, deleting an element at the end of an array is easy but deleting an element
somewhere in the middle of an array will require subsequent elements to be moved one location
upwards as shown below:
Ex: Consider an array of 7 elements. To remove an element 19 from location 3, all elements
from A[4] have to be moved upwards. For this consider an array A which can store maximum 10
elements. Let the length of the array be 7. i.e., N=7. i.e., out of 10 memory locations we are using
only 7 of it as shown below:

20
DATA STRUCTURE

An algorithm to delete an element from the Kth position in A


1. read pos // position of the element to be deleted
2. if pos-1<=n then
item a[pos-1]
for i pos-1 to n-1 do // for(i=pos-1;i<n-1;i++)
a[i] a[i+1] //moving the elements upward
end for
n-- //decrement the length of the array by 1
write “Element Deleted”
else
write “Invalid Position”
end if
3. end

Multi-dimensional array
Multi-dimensional array uses more than one subscript to refer a particular element then it is
called multi-dimensional array.
Ex: A[i,j] - two dimensional array
A[i,j,k] - three dimensional array multi-dimensional array

Two dimensional array


A two dimensional m*n array A is a collection of m*n data elements such that each element is
referenced by a pair of indices i.e., I, J called the subscripts with a property that 1<=I<=M and
1<=J<=N

It is also called as an ordered table of homogeneous elements in business application. It is


generally, referred to as a matrix of same rows and some columns in mathematics. It is also
called as a two-subscripted variable.

21
DATA STRUCTURE

Declaration of a two-dimensional array


Syntax: data_type array_name[rows][columns];
Ex: int marks[2][3];
The above example declares a 2D array of integer type. This integer array has been named marks
and it can hold up to 6 elements.

Initialization of 2-D arrays


Syntax: data_type array_namesize 1][size 2]={e1,e2,..en};
Ex: int matrix[3][3]={1,2,3,4,5,6,7,8,9};
So in the above example, we declared a 2D array named matrix which can hold 3*3 elements,
which is also initialized the array with values, which contains 3 rows (0 to 2). Elements for
column have been differentiated by a comma (,). When compiler finds comma in array elements
then it assumes comma as beginning of next element value.

Processing of 2-D arrays


 A 2-D array is generally called a matrix. The operation that can be perform on matrix using
2-D array
 Reading & printing elements of a matrix
 Insertion into & deletion of an element of a matrix
 Arithmetic operation that perform on two matrices(addition, subtraction & multiplication)
 Searching & sorting of elements in a given matrix
 Comparisons of elements of two matrices

22
DATA STRUCTURE

Memory representation of 2-D array


The elements of two dimensional array is always stored sequentially in computer memory. Let A
be an array of size m*n, which is sequentially allocated and stored. 2-D array elements can be
represented in two ways:
 Row by row method [row major ordering]
 Column by column method [column major ordering]

Row Major Ordering Method


Let ‘a’ be two dimensional array of size m*n. In this method first row elements are stored first
and then second row elements, the third row and so on.

For ex: Consider an array ‘a’ of size 3*3, the matrix representation of array elements are given
by,

The fact that computer does not keeps track of the address of all the elements of a[i,j] instead it
keeps track of base address of a[i,j] i.e., base(a). Thus the address of the first element a[1,1] of
‘a’ computes the address of loc(a[i,j]) of a[i,j] using the following formula,
Row major order: Loc(a[i,j]) = base(a)+w[n(i-1)+(j-1)]
Where base(a) is base address of the array, ‘w’ is the number of words per memory location, ‘n’
is the total number of rows, ‘i’ no. of rows and ‘j’ no. of columns.

23
DATA STRUCTURE

Column Major Ordering Method


Let ‘a’ be a two dimensional array of size m*n. in this method first column elements are stored
first and the second column elements, then the third column and so on.

For ex: Consider an array ‘a’ of size 3*3, the matrix representation of array elements are given
by,

The formula to compute the address of memory location of an array of size m*n is given by,
Column major order: Loc(a[i,j]) = base(a) + w [(i-1) + m(j-1)]
Where base(a) is base address of the array, w is the number of words per memory location, m is
the total number of rows, ‘i’ no. of rows and ‘j’ no. of columns.

Limitations of two dimensional arrays


 We cannot delete any element from the array.
 If we don’t know that how many elements have to be stored in a memory in advance, then
there will be memory wastage if large array size is specified.

Characteristics of an array
 Zero-based indexing: We refer first element a[0], the second element a[1] and so forth. Its
more natural we start with index a[1], but starting the indexing with0 has some advantage
and has emerged as the convention used in most modern programming languages.

24
DATA STRUCTURE

 Array length: Once we create an array, its size is fixed. Code for referring the length of an
array a.length
 Bounds checking: when programming with arrays, it our responsibility to use legal indices
when accessing an array element.
 Setting array values at compile time: when we small number of literal values, which can be
initialized by listing it between curly braces, separated by a comma.
Ex: char suits[ ] = {“clubs”, “diamonds”, “hearts”, “spades”}

Features
 Array size should be positive number only
 String array terminates with null character (\0)
 Array elements are counted from 0 to n-1
 Useful for multiple reading of elements.

Advantages of using arrays


 Array elements are of same data type.
 Performance will be better while store and retrieve of data elements.
 Run time errors and type mismatches can be prevented.
 It is easy to compute the address of an element in an array.
 Linear relationship is reflected by the physical relationship of the data in memory.
 Implementing Searching and Sorting technique is very easy.

Disadvantages of using arrays


 No easy method to initialize large number of array elements.
 Array is fixed in size and cannot grow.
 Arrays are zero index based and little difficult. The way to store and retrieve elements from
arrays is to use integral index.
 Addition and deletion are not easy.
 It cannot be used in application where the is unpredictable storage requirements.

25
DATA STRUCTURE

26
DATA STRUCTURE

Applications of an array
 Used in matrix manipulation (addition, subtraction and multiplication).
 Used to represent records, stacks and queues in memory.
 Used in the representation of polynomials.

27
DATA STRUCTURE

CHAPTER 4: STACKS

Definition of Stacks
 Stack is a linear list (ordered collection of elements) in which insertion and deletion done at
one end, called the top of the stack.
 Data is stored and retrieved in the Last-In-First-Out order (LIFO).
 As mentioned earlier, elements are added into or removed from end, indicated by Top of the
stack.
 PUSH is the term used to insert an element into a stack.
 POP is the term used to delete an element from a stack.
 Stack is restricted variant of the list in which elements are inserted and deleted from only one
end. While this make stack both efficient and easy to implement.

Ex: stack of bangles, stack of coins and stack plates


The different ways of representing stack elements are shown below:

Memory representation of stacks


 Stacks are represented using a linear data structure called arrays.
 Let the name of the array be stack having ‘n’ elements i.e., maximum size of the stack or the
number of elements that can be stored in the stack be ‘n’.

28
DATA STRUCTURE

 Let ‘top’ be variable which points to the top element of the stack
 If top=0, then there is no element in the stack, which is called ‘stack underflow’ i.e., no more
elements can be poped from the stack.
 If top=n, then the stack is full, which is called as ‘stack overflow’ i.e., no more elements can
be pushed into the stack.

Here n = 7 and top = 3, that means there are


three elements in the stack, 24, 56 and 89
and n = 7, it can accommodate still four
more elements.

Operations on Stacks
Stack performs the following functions and operations:
 PUSH: inserts an element to the top of stack. It takes an integer element as argument. If the
stack is full then error is returned.
 POP: removes top element from the stack. If the stack is empty then error is returned. The
element is deleted from the top of the stack.
 DISPLAY: traverse each element and displays stack contents.
 Search: this function takes an integer element as an argument and returns the location on the
element. If number is not found then 0 is returned.
 REPLACE: this function takes two integers as arguments, first is to find and second is to
replace. It first performs search operation then replaces the integers.

Algorithm for PUSH operation


This algorithm inserts an item to the top of the stack, representated by an array stack containing
‘n’ elements with a stack pointer ‘top’ which denotes the top elements on the stack.

29
DATA STRUCTURE

1. [Check for stack overflow] s[top] item


if top>=max-1 then end if
write "stack overflow" 2. [Finish] end
return
else
write "enter the element to be
inserted"
read " item "
[Increment top]
top top+1
[Insert the element item in new top position]

Here on this case attempt to insert one more item ‘fff’ to the array stack will result in
OVERFLOW, because TOP has got the value 4 and the maximum SIZE of the stack which is
constructed using array is also 4

Algorithm for POP operation


This algorithm deletes an item to the top of the stack, representated by an array stack containing
‘n’ elements with a stack pointer ‘top’ which denotes the top elements on the stack

1. [Check for stack underflow] end if


if top = = -1 then 2. [Finish] end
write "stack underflow"
return;
else
[Assign top element to item]
item_del s[top]
[Decrement stack pointer(top)]
top top-1
write "element deleted is item_del "

30
DATA STRUCTURE

Here in this case attempt to delete item from the TOP of stack will result in UNDERFLOW
condition as there are no elements in the stack i.e., top = 0

Algorithm for DISPLAY operation


1. [Check for stack underflow]
if top = = -1 then
write "stack is underflow"
return
else
write "elements of the stack are"
for i 0 to top do
write “s[i]”
end for
end if
2. [Finish] end

Limitation of array implementation


 The stack cannot grow and shrink dynamically as per requirement.
 The only problem with array implementation is array size must be specified initially.

Linked list implementation of stack


The operation of adding an element to the front of a linked list is quite similar to that of pushing
an element on a stack. In both cases, a new item is added as the only immediate link accessible
item in a collection. A stack can be accessed only through is top elements, an a list can be
accessed only from the pointer to its first elements. Similarly, the operation of removing the first
element from the linked list is analogous to poping a stack. In both the cases the only
immediately accessible item for collection is removed from that collection and the next items
become immediately accessible.

31
DATA STRUCTURE

Thus we discovered another way of implementing a stack. A stack may be represented by a


linear linked list. The first node of the list is the top of the stack. It is easy to remove a node from
the linked stack.

Algorithm to implement stack operations using singly linked list


//function to push an item onto a stack
NODE insert_front(int item, NODE first)
{
NODE temp //declare temp
temp getnode() //allocate space for the new node
temp->info = item //insert a data into newnode
temp->link = first //insert a newnode at the beginning of the list
return temp
}

//function to pop an item from a stack


NODE delete_front(NODE first)
{
NODE temp //declare temp
if(first==NULL) //check for stack underflow

write "List Empty"


return first
end if
temp=first //check top element
first=first->link //disconnecting top element from list
write "Poped element is temp->info”

32
DATA STRUCTURE

freenode(temp) //deleted the top element


return first;
}

//function to display the content of a stack


display(NODE first)
{
NODE temp //declare temp
if(first==NULL) //check for empty list
write "List is Empty"
end if
write "Contents of the singly linked list are"
temp=first //initialize to beginning node of the list
while(temp!=NULL)
write “temp->info” //print the data of the node
temp = temp->link
end while
}

The advantage of the linked list implementation of stack is that all stacks being used by the
program can share the same available list. Then in the stack needs a node, it can be obtained it
from the single available list. Then any stack no longer needed a node, it return the node to that
available list. As long as the total amount of space needed by the entire stack at any one time is
less than the amount space initially available to them all, is stack is able to grow a shrink to any
size. No spaces have been preallocated to the single stack and no stack is using space that it does
not need.

33
DATA STRUCTURE

Drawback of linked list implementation


 All the operations take constant time.
 Call to malloc and free are expensive especially in comparison to the pointer manipulation
routines.

Recursion
 Calling a function itself again and again until some specified condition is satisfied is called
recursive function. This method / programming technique is called recursion.
 Function that calls itself directly or indirectly again and again. Such function is called
recursive functions and the process is termed as recursion. When a function calls itself, it is
making a recursive call.
Syntax:
data_type function_name(a)
{
base case; //recursive function terminating condition
else
function_name(x); //recursive part
}

Features
 There should be at least one if statement used to terminate recursion.
 It should not contain any looping statement.

Examples of using recursive function


Many problems can be solved easily using recursive function. Some of them are finding XN,
GCD, factorial of a number, generation of ‘n’ fibonacci numbers, Tower of Hanoi an so on.

Recursive algorithm to find factorial of a number


int fact(int n) // recursive factorial function
if n == 1 then

34
DATA STRUCTURE

return 1
else
return n*fact(n-1)
end if
end

Recursive algorithm to find GCD of 2 numbers


int gcd(int m , int n) // recursive gcd function
if m = = n then
return m;
else if m < n then
return gcd(m,n-m)
else
return gcd(m-n,n)
end if
end

Recursive algorithm of Tower-Of-Hanoi problem


T_H(int n, char S, char D, char T) // recursive T_H function
if ( n <= 0 ) then
write “Invalid input”
else if (n==1) then
write “move disk from S to D”
else
T_H(n-1,S,T,D) //move disks from src to temp
write “move disk from S to D”
T_H(n-1,T,D,S) //move all disks from temp to dest
end if
end

35
DATA STRUCTURE

Recursive algorithm to find Xn


int power (int x, nt n)
if(x= =0) tehn
return 0;
if(n= =0) then
return 1;
else if(n > 0) then
return x*power(x, n -1)
else
return (1/x)*power(x, n + 1)
end if
end

Recursive algorithm to generate Fibonacci number


int fibo(int n)
if(n= =1)
return 0;
else if (n= = 2)
return 1;
else
return fibo(n -1) + fibo (n – 2)
end if
end

Advantages of recursion
 It is easy to use and implement.
 Used to represent compact programming structures.
 Used in the divide and conquer method of problem solving
 Used for postponing the decisions.
 On machine with hardware stack instructions, in fact, the non-recursive function may
actually required more running time than equivalent recursive function.

36
DATA STRUCTURE

 If solution to the problem is defined in terms of itself. In such situation one can make use of
recursive version.

Disadvantage of recursion
 It is slower than that of looping statement because each time function is called.

Expression conversion and evaluation


Arithmetic expression
An expression is a string of symbols. We are going to consider the expressions with variables (a -
z), digits (0 - 9), binary operators (+ , - , * , /) and brackets [(- left & )- right]

Example for some arithmetic expression


1) a+b+c*d
2) (a+b)*(c-d)

Types of expression
An expression can be in 3 forms
 Infix expression
 Prefix expression
 Postfix expression

NOTE: The process of writing the operators of an expression either before their operands or
after them is called ‘notation’.

PRECEDENCE OPERATOR
1. (, ), ^
2. *, /, %
3. +,-

37
DATA STRUCTURE

Infix notation
 Operators are written in between their operands.
 The operations(order of evaluation) are performed from left to right and obeys precedence
rules
 Brackets can be used to change the order of evaluation
Ex: 1) A+B 2) X*(Y+Z)

Prefix notation
 Operators are written before their operands.
 Order of evaluation from right to left.
 Brackets cannot be used to change the order of evaluation.

Ex: 1) +AB 2) *X+YZ


SL
INFIX PREFIX
NO
1 (A + B) * C = [+AB] * C = * + ABC
2 A+B-C = [+AB] - C = - + ABC
3 (A + B) / (X - Y) = [+AB] / [-XY] = / + AB – X Y
4 A ^ B * C – D = [^AB] * C - D = [* ^ ABC] - D = - * ^ ABCD
((A + B) * C - (D - E)) ^ (X + Y) = ([+AB]*C-[DE])^[+XY])
= ^ - * + ABC – DE +
5 = ([*+ABC]-[-DE])^[+XY]
XY
= ([-*+ABC-DE]^[+XY])
Note: The process of writing the operators of an expression before their operands is called
‘Polish Notation’.

Postfix notation
 Operators are written after their operands
 The order of evaluation of operators is always from left to right.
 Brackets cannot be used to change the order of evaluation.
 This notation is also known as Suffix Notation.
Ex: 1) AB+ 2) XYZ+*

38
DATA STRUCTURE

SL NO INFIX POSTFIX
1 (A + B) * C = [AB + ] * C = AB + C *
2 A+B-C = [AB + ] - C = AB + C -
3 (A+B) / (X-Y) = [AB + ] / [XY - ] = AB + XY - /
4 A^B*C–D = [AB ^ ] *C – D = AB ^ C * ] - D = AB ^ C * D -
((A + B) * C - (D - E)) ^ (X + Y) = ([AB + ] * C - [DE - ]) ^ [XY + ])
= AB + C * DE -
5 = ([AB + C * ] - [DE - ]) ^ [XY + ]
XY + ^
= ([AB + C * DE - - ] ^ [XY + ])
Note: The process of writing the operators of an expression after their operands is called
‘Reverse Polish Notation’.

Conversion from infix to postfix


1. Push the symbol ‘#’ on to stack.
2. Scan INFIX from left to right and repeat steps 3 to 6 for each element of INFIX until ‘#’ is
found.
3. If an operand is encountered add it to POSTFIX.
4. If a left parenthesis ‘(’ is encountered push it on to stack.
5. If an operator is encountered then push it on to stack.
a. If the new operator has same precedence or lower precedence than operator in stack, then
repeatedly pop operators from stack and add to POSTFIX.
b. Add operator to stack.
c. [end if of step 5]
6. if right parenthesis ‘)’ is encountered then,
a. Repeatedly pop each operator from stack and add to POSTFIX until a left parenthesis ‘(’
is encountered.
b. Remove the left parenthesis ‘(’
i. [end if of step 6]
ii. [end if of step 2 loop]
7. Exit.

Ex: ((A – (B + C)) * D) ^ (E + F)

39
DATA STRUCTURE

INFIX STACK POSTFIX


#
( #(
( #((
A #(( A
- #((- A
( #((-( A
B #((-( AB
+ #((-(+ AB
C #((-(+ ABC
) #((- ABC+
) #( ABC+-
* #(* ABC+-
D #(* ABC+-D
) # ABC+-D*
^ #^ ABC+-D*
( #^( ABC+-D*
E #^( ABC+-D*E
+ #^(+ ABC+-D*E
F #^(+ ABC+-D*EF
) #^ ABC+-D*EF+
# ABC+-D*EF+^

Evaluating a postfix expression


 Push the symbol ‘#’ on to stack.
 Scan the expression from left to right, repeat steps 3 and 4 for each element of postfix
expression.
 If an operand is encountered push it on to stack.
 If an operator is encountered then:
o Remove the two top elements of stack. Consider n1, n2 are two top elements.
o Evaluate n2 {operator} n1.
o Place the result back on to stack.
 Take top element of the stack as value of expression.
 Exit

Example: 5 3 7 * + 2 -
SCANNED SYMBOL STACK VALUE

40
DATA STRUCTURE

#
5 #5
3 #53
7 #537
* # 5 21 3 * 7 = 21
+ # 26 5 + 21 = 26
2 # 26 2
- # 26 26 – 2 = 24
# 24

Applications of stacks
 Used to implement recursion function (factorial, fibonacci, GCD of a given number).
 Expression conversion (infix to postfix) and evaluation(postfix expression)
 Reversing a string (to check given number is palindrome or not)
 Stack usage in four function calculator. Most the calculator today accept standard format of
an infix notation (operand-operator-operand). In contrast mainly calculators still today made
today using postfix notation (operand-operand-operator).
 Used to indicate the order of processing data when certain steps of the processing must be
postponed until some other conditions are fulfilled.
 Direct applications
o page visited history in a web browser
o undo sequence in a text editor

41
DATA STRUCTURE

CHAPTER 5: QUEUE

Definition of Queue
 Linear (ordinary) queue is a special type of data structure where elements are inserted
from one end and deleted from the other end.
 Queue defines as sequence-oriented object container where element are access and
deletion is restricted to the first element in the sequence, which is called front of the
queue and the insertion is restricted to the end of the sequence, which is called the rear of
the queue.
 The end from where elements are inserted is called rear end.
 The end from where elements are deleted is called front end.
 Since the first element inserted is the first item to be deleted from queue, so it is also
called First In First Out (FIFO) data structure.

Memory representation of queue


Queue is represented by an linear array. Let queue be a linear array. Two pointers variable
FRONT and REAR is used to keep track of insertion and deletion. Front pointer contains the
location of front element of the queue (element to be deleted) and rear pointer contains the
location of the rear element of the queue (recently added element). The condition front = 0
indicates the queue is empty. To add the element, the value of the rear is incremented by one. If
rear = N then queue is full.

For insertion rear = rear + 1, Q[rear] = item

42
DATA STRUCTURE

For deletion, item = Q[front], front = front + 1

The above figure shows the way the array Q will be stored in memory with elements. It also
shows how the elements are inserted or deleted from the queue.

Operations on queue
 Insertion: Inserts an element to the rear end of the queue. If the queue is full then error is
returned.
 Deletion: Removes the element from the front end of the queue. If the queue is empty then
error is returned.
 Traversal: Display the contents of queue.

Algorithm to insert at rear end


Insert_rear( )
Step1: [check for overflow]
if r = n-1 then
write “Queue is full”
exit
end if
Step 2: [check for empty queue]
if f = -1 then
f=0
else

43
DATA STRUCTURE

[Insert item and increment rear pointer]


r=r+1
end if
Step 3: q[r] = item
Step 4: end

Algorithm to delete at front end


Delete_front ( )
Step 1: [check for underflow]
if f = -1 then //if(f > r)
write “Queue is empty”
exit
end if
Step 2: [delete front element]
item = q[f]
Step 3: [check for empty queue]
if f = = r then
[Queue has only one element]
f = r = -1
else
[Increment front pointer]
f=f+1
write “element deleted is item”
end if
Step 4: end

Algorithm to display the content


Display ( )
Step 1: [check for underflow]
if f = -1 then //if(f > r)
write “Queue is empty”

44
DATA STRUCTURE

exit
end if
Step 2: [print the content of queue]
for i = f to r do
write “q[i]”
end for
Step 3: end

Disadvantage of ordinary queue


 Even if free memory was available,
those memory spaces cannot be
accessed.
 This disadvantage can be overcome by
 For the above example, if we try using “Circular queue”
inserting element it is encountered with
the condition “Queue overflow”

Linked list implementation of queues


Let us now examine how to represent a queue as a linked list. Recall that items are deleted from
the front and inserted at the rear. Let a pointer to the first element of a list represent the front of
the queue. Another pointer to the last element of the list represents the rear of the queue. Another
pointer to the last element of the list represents the rear of the queue, as shown in fig 1. Fig 2
illustrates the same queue after a new item has been inserted. Fig 3 illustrates the same queue
after a node has been deleted.

Fig1: Queue as a linked list

45
DATA STRUCTURE

Fig 2: Queue after insertion

Fig 3: Queue after deletion

Algorithm to insert at rear end using linked list


insert_front(int item)
Step 1: [declaration]
struct node *newnode
Step 2: [allocate memory for new element]
newnode=(struct node *) malloc (sizeof (struct node))
Step 3: [insert data and address into newnode]
newnode -> data=item
newnode->link=HEAD
HEAD=newnode
Step 4: end

Algorithm to delete at front end using linked list


int delete_begin()
Step 1: [delaration]
int ele
NODE *curptr
Step 2: [check for empty queue]
if(HEAD==NULL)

46
DATA STRUCTURE

write "Queue Empty"


return 0
else
[Delete element at front]
curptr=HEAD
ele=curptr->info
HEAD=curptr->link
end if
Step 3: [deallocate element removed from queue]
free(curptr)
Step 4: return ele
Step 5: end

Algorithm to display contents of queue using linked list


display(NODE *temp)
Step 1: [check for empty queue]
if(HEAD==NULL)
write " Queue is Empty"
else
[Display the queue contents]
write "The elements of list are"
while(temp!=NULL)
write “temp->data”
temp = temp->link;
end while
end if
Step 2: end

Different types of queue


 Queue (ordinary queue)
 Circular queue

47
DATA STRUCTURE

 Double ended queue (dequeue)


 Priority queue

Circular queue
 Queue of having logic terminate when the limit of the array used to store the queue is
reached, both REAR and FRONT loop back to the array. In this way any number of elements
could be placed on the queue, so long elements were also taken off. This implementation of a
queue is called circular queue.
 It is essence, the queue is full when the REAR is one less than FRONT; otherwise there is a
room in the queue for another event.
 In a circular queue, the elements can be stored efficiently in an array so as to “wrap around”
so the end of the queue is followed by front of the queue.
 It representation allows the entire array to store the elements without shifting data within
queue.

Algorithm to insert at rear end using circular queue


void cir_insert(int Q[MAX],int *front,int *rear,int *count)
Step 1: [declare]
int item
Step 2: [check for empty queue]
if((*front==0 && *rear==MAX-1)||(*front==*rear+1)) then
write "Queue is full"
else
write "Enter the element"

48
DATA STRUCTURE

read “item”
end if
Step 3: if(*front= = -1)
[Insert item as first element of the queue]
*front=0
*rear=0
else if(*rear==MAX-1)
[Reset the rear pointer]
*rear=0
else
[Increment rear pointer]
*rear=*rear+1
end if
Step 4: Q[*rear]=item
Step 5: end

Algorithm to delete at front end using circular queue


void cir_delete(int Q[MAX], int *front, int *rear, int *count)
step 1: [declare]
int item
step 2: [check for empty queue]
if(*front==-1)
write "Queue is Empty"
else
[delete front element]
item=Q[*front]
write “The deleted item is item”
end if
step 3: if(*front==*rear)
[Queue has only one element]
*front=-1

49
DATA STRUCTURE

*rear=-1
else if(*front==MAX-1)
[Reset the front pointer]
*front=0
else
[Increment front pointer]
*front=*front+1
*count=*count-1
end if
step 4: end

Algorithm to display contents of circular queue


void cir_dis(int Q[MAX], int *front, int *count, int *rear)
Step 1: [declare]
int i,c
Step 2: [check for empty queue]
if(*count==0) then
write "Queue is Empty!"
else if(*front>*rear) then
[display queue element from front to rear]
for(i=*front;i<MAX;i++) do
write “Q[i]”
end for
for(i=0;i<=*rear;i++) do
write “Q[i]”
end for
else
for(c=*count,i=*front;c!=0;c--) do
write “Element: Q[i++]”
end for
end if

50
DATA STRUCTURE

Step 3: end
Advantages of circular queue over ordinary queue
 In circular queue we utilize memory efficiently
 Rear insertion is denied in ordinary queue even if free memory is available; we cannot access
the memory locations. This is the major disadvantage of ordinary queue.
 In circular queue, the elements of a given queue can be stored efficiently in an array so as to
“wrap around” so that end of queue is followed by the front queue.
 Circular representation allows the entire array to store the elements without shifting any data
within the queue.

Double ended queue (Deque)


Queue like data structure that supports insertion and deletion at both the front and rear ends of
the queue. Such an extension of queue is called a Double ended queue or Deque.

Fig: Deque

Operations performed on deque


 Insert an item from front end (refer insertion of linear queue)
 Insert an item from rear end
 Delete an item from front end (refer deletion of linear queue)
 Delete an item from rear end
 Display the contents of queue (refer display of linear queue)

Two variations of deque


 Input-restricted deque: it is a deque which allows insertion at only one end (rear) of the list
but allows deletion at both ends of the list.
 Output-restricted deque: it is a deque which allows insertion at both ends of the list but
allows deletion at only one end (front) of the list.

51
DATA STRUCTURE

52
DATA STRUCTURE

Algorithm to insert at front end


Insert_front( )
Step1: [insert when Q empty]
if f = = 0 && r = = -1 then
r=r+1
q[r] = item
exit
end if
Step 2: [insert when items are present]
if f ! = 0 then
f=f-1
q[f] = item
exit
else
write “Insertion at front end is not possible”
end if
Step 3: end

Algorithm to delete at rear end


Delete_rear( )
Step 1: [check for underflow]
if f = -1 then //if(f > r)
write “Queue is empty”
exit
end if
Step 2: item = q[r]
Step 3: if f = = r then
f = r = -1
else
f=f+1
write “item deleted is q[r]”

53
DATA STRUCTURE

end if
Step 4: end

Priority queue
 A queue in which we are able to insert items or remove items from any position depending
on some property is called priority queue.
 If an element of higher priority is processed before any element of lower priority.
 If two elements with same priority are processed according to the order in which they are
added to the queue (FIFO).
 The difference between priority queue and other queues is that the strict ordering on the
queue is not purely FIFO. Instead ordering is a combination of FIFO and the priority
assigned to the elements.

Ex: Refer fig1 that represents a priority queue of jobs of supervisors(S), teachers (T) and
students (ST) respectively. Therefore, if a job is initialed with priority P, it is inserted
immediately at the end of the queue of other jobs with priority P, P = 1, 2, 3. Here the jobs are
always removed from the front of the queue.

Fig1: Priority Queue


In priority queue is a series of queues representing situations in which it is known as priori what
priorities are associated with queue elements. Fig2 represents how the single priority queue can
be visualized as three separate queues; each follow FIFO principle. The elements in the second
queue are removed only when the first queue is empty and so on. This separation of a single
priority queue into a series of queues also suggested an efficient storage representation of a
priority queen. When the elements are added, they are always added at the end of one of the
queues as determined by priority. If one uses a single sequential storage structure for the priority

54
DATA STRUCTURE

queen then insertion may mean that the new element must be placed in the middle of the queue.
This can require the movement of several elements. Thus, we can say that it is better to split a
priority queen into several queues, each having its own storage structure.

Applications of queue
Queues are used in various operations. Some of them are:
 Queues are useful in time sharing systems where many users’ jobs will be waiting in the
system queue for processing. These jobs may request the service of the cpu, main memory or
external device such as printer etc. all these jobs will be given a fixed time for processing and
are allowed to use one after the other. This is the case of an ordinary queen where priority is
the same for all the jobs and whichever job is submitted first, that job will be processed.
 Perhaps the most common use of circular queues is in operating system where the circular
queue holds the information read from and returns to disk files or the console.
 In a computer network, message from one computer to another are generally created
synchronously.
 Priority queues are used in designing CPU schedulers where jobs are dispatched to the CPU
based on priority of the job.
 Operating systems often use a priority queue for the ready queue of processes to run on the
CPU. Important programs, like those that the user is interacting with, receive a high priority;
lower priority is accorded to less urgent tasks like checking periodically for new e-mail or
rearranging files on disk for more efficient access. As a result, the operating system works on
the background tasks only when the user is not interacting with the computer.

55
DATA STRUCTURE

UNIT 2
CHAPTER 6: POINTERS
Pointers
 Pointer is a special data type which is derived from basic data types (int, float, char,
double,.). So pointer is called derived data type.
 Definition: pointer variable is a variable used to hold the information of the other variable.
 The pointer takes the values from 0 to 65535, if the size of the RAM is 64K.

Any variable, which is declared and initialized, has three things associated with it
 Y, a memory location which hold the value of the variable.
 The initialized value, which is stored in the location
 The address of that memory location.

Pointer variable
A variable which holds address of the variable is called a pointer variable.
Declare a data variable
Steps to be followed while using pointer Declare a pointer variable
Initialize a pointer variable
Access data using pointer variable

To show the creation of a pointer variable


#include<stdio.h>
void main( )
{
int *p int i; // Declaration
i=500; // Initialization

56
DATA STRUCTURE

p = &i; // Assignment
printf(“%d”, *p); //500 (value of the data variable)
printf(“%p”,p); //1055 (address of the data variable)
}

Observing the program closely highlights the following points


 The address of a variable is accessed with the help of the “&” operator.
 Using the name of the variable we can accesses the value of the variable.
 A pointer variable is created by including the operator “*” when the variable is declared.
 A pointer variable can hold the address of another variable and not the value of another
variable.

Pointer declaration
A pointer is a variable that contains the address of the memory location of another
variable. To create a pointer variable we use the syntax in the figure

Pointer operator
A pointer operator is used to classify a variable as a pointer and not as a normal variable
For ex: int *prt;

Address operator
Once pointer variable is declared, it must be pointed to something. It can be achieved by
assigning to the pointer the address of the variable which is needed.
ptr = &num;

57
DATA STRUCTURE

Fig: allocation of address to pointer variable

Pointer constants
 Computer store information in memory, where it is divided into number of locations called
storage cells.
 All 65536 locations arranged sequentially, but physically divided into even bank (address)
and odd bank (address). These addresses are called pointer constants.

Pointer values
Memory is divided into number of storage cells called locations. 0 to 65536 addresses are
sequentially arranged. Out of these memory addresses assigned to variables by the system are
called pointer values.

Dangling pointer
int *p;
 This indicates p is a pointer variable and corresponding memory location contain address of
an integer variable, but declaration will not initialize the memory location and memory
contains garbage value.
 A pointer variable should contain a valid address, which does not contain a valid address is
called dangling pointer.

NULL pointer
int *p = NULL;
A NULL pointer is defined as a special pointer value that points to nowhere in the memory. If it
is early to assign value to the pointer then it is better to assign NULL (i.e., \0 or 0) to the pointer.

58
DATA STRUCTURE

Garbage Collection
Computers do not have an infinite amount of storage and cannot manufacture more storage for
immediate utilization. Therefore there are finite numbers of nodes available and it is impossible
to use more than that number at any given instant. If it desired more memory over a period of
time, some nodes must be reused. Suppose memory space becomes reusable because a node is
deleted from a list or an entire list is deleted. One way to bring this free space, immediately
reinsert the space in free-storage list. But this is time consuming. So operating system
periodically collects all deleted space onto the free-storage list, this technique of collection is
called garbage collection.

Garbage collection usually takes place in two steps. First the computer run through all lists,
tagging those cells which are currently in use, and second then the computer runs through the
memory, collecting all untagged space onto the free-storage list. Garbage collection takes place
only when there is minimum amount of space or no space at all left in free storage list or when
CPU is idle (free) and has time to do the collection. However garbage collection is invisible to
the programmer. The free( ) function returns a node to the free pool, I.e., availability list. This
function makes a node that is no longer being used in the linked list available for reuse.

Note: When a node is deleted from a list or an entire list is deleted then that memory cells can be
reused. Thus the process of collecting all reusable cells into the free storage list is called
garbage collection.

Operations on pointers
A pointer variable which holds address of the other variable. This address can be incremented or
decremented. The pointer variables cannot be multiplied and divided because those operations
are performed on the addresses.

Assignment operator
 int *ptr, var;
 ptr = &var;

59
DATA STRUCTURE

Addition and subtraction operator


int *x;
x = (x + 2);
x = (x – 1);

Comparison / Relational operator


if two pointer variables are pointing to the objects of the same data type, then they can be
compared with one another.
Ex: int *m, *n;
then,
 (m = = n)
 (m ! = n)
 (m < = n) (m < n)
 (m > = n) (m > n) etc, can be performed using decision making statements.

Logical operator
Ex: int *r, *s, *t;
then,
 (*r > *s && *s > *t && *r > *t)
 printf(“%d is greatest\n”, *r);
 (*r < *s || *r < *t || *s < *t)
 printf(“%d is smallest\n”, *t); etc, can be performed using decision making statements and
relational operators.

Pointers and functions


Pointers are used very much with functions. Complexity of function can be easily represented
and accessed only with pointer arguments can be passed to one of the following methods.
 Passing values of the arguments [Call by value]
 Passing the addresses of the arguments [Call by reference]

60
DATA STRUCTURE

Call-by-value
When a function is invoked a correspondence is established between actual and formal
parameter, where a temporary storage is created were the value of the actual parameter is stored.
The formal parameter picks up its value from this storage area. This mechanism of data transfer,
between actual and formal parameter which allows the actual parameter to be an expression,
function arrays and etc. such parameter is value parameter and mechanism of data transfer is
referred to as call-by-value.

Function to exchange two value using call by value


void swap(int x, inty)
{
int temp;
temp= x;
x=y;
y=temp;
printf(“swapped values are a=%d and b=%d”, x, y);
}

Call-by-reference
Whenever the function call is made if we pass the address of the variable to function, the
parameters receive the address to the pointers. The process of calling function using pointers to
pass the address of variable is called call-by-reference

Function to exchange two value using call by reference


void swap(int *x, int *y)
{
Int temp:
temp = *x;
*x = *y;
*y = temp;
printf(“swapped values are a=%d and b=%d”, *x, *y);
}

61
DATA STRUCTURE

Pointers to Pointers
 It makes a pointer to point to another pointer variable. The variable which contains
address of a pointer variable is called pointer to a pointer.

Program to show the configuration of all variables and the output


#include<stdio.h>
void main()
{
int a; int *x; int **y; //local definitions
a = 100; x = &a; y = &x; //statements
printf(“%d\n”,a); //100
printf(“%d\n”,*x); //100
printf(“%d\n”,**y); //100
printf(“%p\n”,x); //1006
printf(“%p\n”,y); //1004
}

Pointers and structures


 A structure is a collection of one or more variables, possibly of different types, grouped
together under a single name for convenient handling.
 Structure Member can be an ordinary data type such as int, float, char and even a structure
also.
 It is permitted to declare a pointer as a member to a structure.

A sample structure program using pointers


#include<stdio.h>
struct complex
{

62
DATA STRUCTURE

int x;
float y;
}struct complex *p; //to declare p as a pointer of type struct complex

void main( )
{
*p.x = 8; //to access the first member of the struct
p -> y = 10.5; //another way to access the first member of the struct
printf(“value of X = %d\n”, (*p).x);
printf(“Value of Y = %f\n”, p -> y);
getch();
}

Advantages of pointers
 Memory allocation to a variable More than one value can be returned using pointer
concept(pass by reference)
 Very compact code can be written using pointers.
 Data accessing is much faster when compared to arrays.
 Using pointers, we can access byte or word locations and the cpu registers directly. The
pointers in c are mainly useful in processing of non-primitive data structure such as arrays,
linked lists etc.

Disadvantages
 Un-initialized pointers or pointers containing invalid address can came system crash.
 It is very easy to use pointers incorrectly, causing bugs that are very difficult to identify and
correct.
 They are confusing and difficult to understand in the beginning and if they are misused the
result is not predictable.

63
DATA STRUCTURE

Memory allocation to a variable


There are two kinds of memory allocation through a variable:
 Static memory allocation
 Dynamic memory allocation

Static memory allocation


 It refers to the process of allocating memory at compile time before the associated program is
executed.
 Each static or global variable defines one block of space, of a fixed size.
 The space is allocated once, is never freed.
Ex: int a[10][10];

Dynamic memory allocation


 It refers to a process of allocating memory as required at run – time.
 Dynamic variables have the space allocated to them during the execution.
 The amount of memory needed is not known before execution of a program.
 We can allocate memory dynamically by using functions
malloc( )
calloc( )
realloc( )
 We can release the allocated memory by using function:
free( )
 These above functions are defined in stdlib.h header file.

Malloc ( )
It allocates the specified number of bytes.
Syntax: (type_cast) malloc (no. of element * size of each element);
Example: int *ptr;
ptr = (int*) malloc (10 * sizeof(int));

64
DATA STRUCTURE

Calloc ( )
It allocates the specified number of bytes and initailizes them to zero.
Syntax: (type_cast) calloc ( no. of blocks, size of each block);
Example: int ptr = (int*) calloc (10, sizeof(int));

Realloc ( )
It increases / decreases the size of the specified block of memory.
Syntax: (type_cast) realloc (pointer, new size);
Example: int ptr = (int*) realloc (number, count * sizeof(int));

Free ( )
It releases the specified block of memory back to the system.
Syntax: free (pointer_variable);
Example: free(ptr);

Difference between malloc and calloc function


Malloc
 The syntax of malloc() is: ptr =(data_type*) malloc (size);
 The required number of bytes to be allocated is specifies as argument i.e., size in bytes
 Allocates a block of memory of size bytes
 Allocated space will not be initialized
 Since no initialization takes place, time efficiency is higher than calloc().
 This function can allocate the required size of memory even if the memory is not available
contiguously but available at different locations.
 Allocation and initialization of allocation memory with()’s can be done using the following
statement: p=malloc(sizeof(int)*n); memset(p,0,sizeof(int*n));

65
DATA STRUCTURE

Calloc
 The syntax of calloc is: ptr = (data_type*) calloc(n, size); takes two arguments number of
blocks to be allocated size is number of bytes to be allocated for each block.
 Allocates multiple blocks of memory, each with the same size.
 Each byte of allocated space is initialized to zero
 Calloc() is slightly more computationally expensive because of zero filling but, occasionally,
more convenient than malloc()
 This function can allocate the required number of blocks contiguously. If required memory
can not be allocated contiguously, it returns null.
 Allocation and initialization of allocated memory with 0’s can be done using the following
statement: p = calloc(sizeof(int)*n);

66
DATA STRUCTURE

CHAPTER 7: LINKED LIST

Linked List
 Linked list is a type of data structure for storing information as a list, which consisting of a
group of nodes together represents a sequence.
 A linked list is a list with each data item containing a link to the location of the next data item
in the list.
 A linked list represents a linear collection of items, called nodes. Nodes of a linked list can
be scattered about in the memory. They need not necessarily represent a set of consecutive
memory locations. Each node in a list has two parts: information part and link part.

Fig: Linked list with three nodes

Node: It is a structure of a linked list consists of two fields INFO and LINK as member of the
structure.

Info: It is an information field in a node that accommodates the actual data element value.
These data elements can be int, float, char, string or even another structure.

Link: It is next address field containing a pointer value to locate next node in sequence.

Null list: A list with empty node, without any information of next node (Null, /0)

Empty node: It a node with requisite amount of memory location to it, where info field
contains a 0, link field contains arbitrary pointer value.

67
DATA STRUCTURE

Header node: It is preferred to keep an additional blank node at the front portion of the list
which never contains data element in its info field.

Advantages of Linked List


 In case of linked list, contiguous memory space is not required. Each element will contain
pointer that will give address of the next free location. So linked list uses memory more
wisely.
 Array size is fixed and cannot change at run time, but in linked list we can create memory
according to requirement. Therefore there is no wastage of memory space.
 Inserting or deleting nodes from a linked list is very easy at any place of the linked list.
 Data storage in the linked list can be of any type. All the nodes need not have the same type
of data.

Disadvantages of Linked List


 Random access is not allowed in linked in list. We have to access elements sequentially
starting from the first node. So we cannot do binary search with linked lists.
 Extra memory space for a pointer is required with each element of the list.
 Arrays have better cache locality that can make a pretty big difference in performance.

Types of Linked List


 Singly linked list
 Doubly linked list
 Circular linked list

Singly Linked List (SLL)


 It is a data structure that consists of a sequence of nodes such that each node contains a link
to the next node in the list. The last node’s pointer is null. This type of list can be traversed in
only one direction.

68
DATA STRUCTURE

 A linked list in its simplest form is a collection of nodes that together form a linear sequence.
The ordering determined as “Follow the leader”, in each node usually consists of a structure
that includes information fields and a link pointer.

The above figure shows a list of numbers, which is represented, in the form of a linked list.
HEAD is a pointer, which gives the address of the first node in the linked list. Link field of the
last node contains the NULL, which indicates it does not contain any address.

We have seen that a linked list is a collection of nodes of the same type and hence it can be
defined as follows:
The structure representation of singly linked list is,
struct node
{
int data; //information field
struct node*link; //a pointer which points to next node
};
typedef struct node *NODE; //structure to create a node in SLL
NODE *HEAD;

Different operations on linked list


 Creating a linked list
 Traversing a linked list
 Inserting an item into a linked list
 Deleting an item from the linked list
 Searching an item in a linked list
 Merging two or more lists to from a single list.

69
DATA STRUCTURE

Creating the Singly Linked List


To create the linked list, the following three things should be done.
 Allocating memory for the node
 Assigning the data
 Adjusting the pointers

Algorithm to create a Linked List


create_ll (int item)
Step 1: Start
Step 2: Declare NODE *newnode, *temp
Step 3: [Create a new node and store its address in the pointer newnode]
newnode (NODE*)malloc(sizeof(NODE))
Step 4: [Increment]
count++
Step 5: [Copy the information for the new node to the information part]
newnode -> data item
Step 6: [Set the contents of the link part as NULL]
newnode -> link NULL
Step 7: [Is the new node the first node?]
if(HEAD==NULL) then
[if yes connect the new node to the head]
HEAD newnode
else
temp HEAD
while(temp->link!=NULL)
[take the temp to the last node of the linked list]
temp temp->link

70
DATA STRUCTURE

[connect the new node to the link of the last node]


temp -> link newnode
end while
end if
Step 8: end

In the above algorithm, we used three pointers


1. HEAD is used to hold the address of the first node of the linked list.
2. NEWNODE is used to hold the address of the new node.
3. TEMP, which is updated to always point to the last node in the linked list.

Algorithm to display the contents of a linked list


display(NODE *temp)
Step 1: start
Step 2: [check for empty list]
if(HEAD==NULL) then
write "The List is Empty"
else
write "The elements of list are:"
[Perform the traversing operation]
while(temp!=NULL) do
[Print data of temp]
write "temp->data"
[Move pointer to the next node]
temp temp -> link
end while
end if
Step 3: end

71
DATA STRUCTURE

Memory allocation
The maintenance of the linked list in memory assumes the possibility of inserting new node into
the lists and hence requires some mechanism, which provides memory space for the new nodes.
This is achieved by the memory space of deleted nodes becomes available for future use.
Together with linked list in memory, a special list is maintained which consists of unused
memory cells. This list, which has its own pointer, is called the list of available space
(AVAILABILITY LIST) or free-storage list or free pool. The AVAIL pointer points to the first
node in the availability list.

Whenever a node is to be inserted into a linked list, it is necessary to have a function (GetNode)
that supplies an unused node from the availability list. If there is a free node, then the address of
the available free node in which the new data can be placed is also to be determined. The
following will allocate a free node and makes it available to the program.

Function to create a node from the available list


NODE GetNode ()
{
NODE newnode;
newnode = (NODE)malloc(sizeof(struct node));
if(newnode = = NULL)
{
printf("Out of Memory\n"); //free node is not available
return 0;
}
return newnode; //return newnode address to program
}

72
DATA STRUCTURE

Inserting an item into a Singly Linked List


There are many applications where it is desired to maintain an order linear list. The ordering may
be in increasing or decreasing order of information field. Such an ordering often results more
efficient processes in many cases. Before inserting a new node, first we have to take the free
node from the available list. If no free nodes are available then we cannot insert the node.

There are different types of insertions.


 Insert a node at the beginning of the linked list
 Insert the node at the end of the linked list
 Insert a node at a specified position in the linked list

Inserting a node at the beginning of the linked list


Consider the following linked list
 Create memory for the new node
 Assign the value to the data field of the new node
 Make the link field of the new node to point to the starting node of the linked list
 Set the head pointer (which was pointing to the first node) to point to the new node

Algorithm to insert an item into linked list at front end


insert_front(int item)
Step 1: start
Step 2: declare struct node *newnode
Step 3: [create a new node and store its address in the pointer newnode]
newnode (struct node *)malloc(sizeof(struct node))
Step 4: increment count++
Step 5: [copy the information for new node to the information part]
newnode->data item
Step 6: [set the contents of the link part to contain the address of the first node]
newnode->link HEAD
Step 7: [make the new node as the first node of the linked list]

73
DATA STRUCTURE

HEAD newnode
Step 8: end

The schematic diagram

74
DATA STRUCTURE

Inserting a node at the end of the linked list


Consider the following linked list
 Create memory for the new node
 Assign the value to the data field of the new node
 Make the link field NULL
 Go to the last node with the help of another pointer called temp
 Insert the new node after the last node

The schematic diagram

75
DATA STRUCTURE

Algorithm to insert an item into linked list at rear end


insert_rear (int item)
Step 1: start
Step 2: declare struct node *newnode, *temp
Step3: [Create a new node and store its address in the pointer newnode]
newnode (struct node *) malloc (sizeof (struct node))
Step 4: Increment count++
Step 5: [Copy the information for new node to the information part]
newnode -> data item
Step 6: [Set the contents of the link part to NULL]
newnode -> link NULL
Step 7: [Initialize HEAD value to temp]
temp HEAD
Step 8: [Find the last node of the list]
while(temp->link! NULL) do
[Move temp to next node]
temp temp->link
Step 9: [Connect the new node to the link of the last node]
temp -> link newnode
Step 10: end

76
DATA STRUCTURE

Inserting a node at a specified position of the linked list


 Create memory for the new node
 Assign the value to the data field of the new node
 Search the nodeA with the help of the pointer temp
 If there is no nodeA in the list, then the position entered is out of range
 Make the link field of the new node to point to nodeB
 Make the link field of nodeA to point to the new node

77
DATA STRUCTURE

Algorithm to insert an item into linked list at specified position


insert_pos(int item, int pos)
Step 1: Start
Step 2: Declare struct node *newnode,*temp
Step 3: Declare i
Step 4: [Create a new node and store its address in the pointer newnode]
newnode (struct node *) mallow (sizeof(struct node))
Step 5: Increment count++
Step 6: [Copy the information for new node to the information part]
newnode->data item
Step 7: [Initialize HEAD value to temp]
temp HEAD
Step 8: [Check for given position is in range or not]
if(pos > count) then
write "Out of Range!!"
[Check for given position is the first position]
else if(pos==1) then
newnode -> link HEAD
HEAD newnode
else
temp HEAD
[move to the required position]
for i 1 to pos-1 && temp!=NULL do
[move temp to next node]
temp temp->link
[Insert the new node at the required position]
newnode->link temp->link
temp->link newnode
end for
end if
Step 9: end

78
DATA STRUCTURE

The schematic diagram

79
DATA STRUCTURE

Deleting an item from the linked list


To delete an existing node from a linked list, we have to loop through the nodes until we find the
node we want to delete. We should follow the steps below to delete a node from a linked list:
 If the linked list is empty, then deletions not possible and this condition called as underflow
condition.
 To delete a particular node, we have to loop through the nodes until we find the node we
want to delete.
 If the end of the list has been reached, “position out of range” message can be displayed.
 Insert deleted node into the free area.
The deletion operation is classified into following types:
 Deletion of first node
 Deletion of last node
 Deleting the node at a specified position

Deletion of first node


 Check whether the list is empty or not
 Make HEAD to point to the second node
 Free the first node

The schematic diagram

80
DATA STRUCTURE

Algorithm to delete an item from a linked list at front end


int delete_begin( )
Step 1: Start
Step 2: Declare ele
Step 3: Declare NODE *curptr
Step 4: [Check for empty list]
if(HEAD= =NULL) then
write "List Empty"
return 0
else
[Initialize pointer variable curptr]
curptr HEAD
[copy the information of curptr to variable element]
ele curptr->info
[delete first node]
HEAD curptr->link
end if
Step 5: [Return deleted node to the AVAIL list]
free(curptr)
Step 6: Decrement count- -

81
DATA STRUCTURE

Step 7: return ele


Step 8: end

Deletion of last node


 Check whether the list is empty or not
 Go to traversing the list till the last but one node
 Set the link field of the last bur one node to NULL
 Free the last node

82
DATA STRUCTURE

The schematic diagram

83
DATA STRUCTURE

Algorithm to delete an item from a linked list at rear end


int delete_end( )
Step 1: Start
Step 2: Declare ele
Step 3: Declare NODE *curptr,*prevptr
Step 4: [Check for empty list]
if(HEAD= =NULL) then
write "List Empty"
return 0
else
[Initialize pointer variable curptr]
curptr HEAD
[Traverse linked list and take the pointer to next node]
while(curptr->link!=NULL)
prevptr curptr
curptr curptr->link
end while
ele curptr->info
prevptr->link NULL
end if
Step 5: [Return deleted node to the AVAIL list]
free(curptr)
Step 6: Decrement count- -
Step 7: return ele
Step 8: end

Deleting a node at a specified position


 Check whether the list is empty or not
 Search the desired node
 Check whether the specified node is present in the first
 Make the link field of nodeA to point to nodeB

84
DATA STRUCTURE

 Free the node between nodeA and nodeB

The schematic diagram

85
DATA STRUCTURE

Algorithm to delete an item from a linked list at a specified position


int delete_pos(int pos)
Step 1: Start
Step 2: Declare ele, i
Step 3: Declare NODE *curptr,*prevptr
Step 4: [Check for given position is in range or not]
if(pos>count) then
write "Out of Range!!"
return
[Check for empty list]
else if(HEAD = = NULL) then
write "List Empty"
return 0
else
[initialize pointer variable cuptr]
curptr HEAD
[traverse linked list and take the pointer to next node]
for i 1 to pos && curptr->link!=NULL do
prevptr curptr
curptr curptr->link
end for
ele curptr->info
prevptr->link curptr->link
[return daleted node to the AVAIL list]
free(curptr)
count- -
end if
Step 5: return ele
Step 6: end

86
DATA STRUCTURE

An algorithm to Searching for an item in a linked list


search (int key, node first)
Step 1: [declare]
node cur
Step 2: [check for empty list]
if (first=null)
write “list is empty”
end if
[compare one after the other]
cur=first
while(cur!=null)
if (key=cur->info)
break;
cur=cur->link;
end while
if(cur = = null)
Write “search is unsuccessful”
else
write “search is successful”
end if
Step 3: end

Advantages of Singly Linked List


 Accessing of a node in the forward direction is easier
 Insertion and deletion of nodes are easier.

Disadvantages of Singly Linked List


 Accessing of the preceding node of a current node is not possible as there is no backward
traversal.
 Accessing a node is time consuming

87
DATA STRUCTURE

Doubly Linked List


 In singly list, traversing is possible only in one direction, because each list elements contains
a pointer to next element. Sometimes it is required to traverse a list in forward or backward
direction. A doubly linked list is designed to allow convenient access from a list node to the
last node and also to the preceding node on the list, it also used to traverse the list in both the
directions, so it is also called as two-way list.
 A doubly-linked list is a linked data structure that consists of a set of data nodes, each having
two special link fields that contain reference to the previous and to the next node of the list.
The left link points to the predecessor (prior) node and the right link points to the successor
(next) node.

 The data field contains the value, the llink field has the address of the previous node in the
list and rlink field has the address of the next node in the list.
 The llink field of the first node and rlink field of the last node is NULL, indicating the end of
the list for each direction.
 The address of the first node is stored in the special pointer called HEAD and the address of
the second node is stored in the special pointer called TAIL.

Implementation of Doubly Linked List


The structure representation of doubly linked list is,
struct node
{
int data; //information field
struct node *llink; //a pointer which is pointing right node
struct node *rlink; //a pointer which is pointing left node
};

88
DATA STRUCTURE

Advantages of Doubly Linked List


 From the given node in the list, one can navigate easily in both directions.
 Insertion and deletion of nodes are easy to perform.
 It is very useful in representing the tree data structure.

Disadvantages of Doubly Linked List


 Each node requires an extra pointer, to store right and left pointers for each node.
 The insertion/deletion of a node takes a bit longer space (due to more pointer operations).

Circular Linked List


 Some applications do not require that there be a particular first or last list element. In such
cases, it may be convenient to allow from the last element to the first. In normal linked list,
the link field of the last element stores the value NULL.
 In a circular linked list, all nodes are linked in a continuous circle, without using null.
 It is exactly the same as a singly linked list, but instead of setting the next pointer in the last
node of the list to null, will be set to point to the first node. Hence it is called circular linked
list.
 With this implementation, a HEAD pointer is no longer needed. The primary danger with
such implementations is that list-processing operations may go into infinite loop since there
is no obvious end to the list. However, in circular linked list instead of HEAD, TAIL pointer
is used as a marker to determine when list processing has worked full circle through the list.
 It can be classified in two ways:
 Circular singly linked list
 Circular doubly linked list

89
DATA STRUCTURE

Advantages of Circular Linked List


 In a circular linked list every node is accessible from a given node.
 Traversing this list is time consuming.
 Concatenation and splitting operation on it are more efficient.

Disadvantages of Circular Linked List


 In processing, it is possible to get into an infinite loop.

Merits of an array over linked list


 It is easy to compute the address of an element in an array.
 Linear relationship is reflected by the physical relationship of the data in memory.
 Extra memory space is not required to store link fields.
 Binary search is applicable
 Sorting an array is easier.
 Once can directly access any element of the array.

Demerits over linked list


 Additions and deletions are not easy.
 It cannot be used in application where there is an unpredictable storage requirement.

90
DATA STRUCTURE

Application of the linked list


This section will be concerned with a number of applications of linear linked lists. Many
examples could be given, but only first two applications will be described in this section.
 It is useful for representing polynomials. In addition, subtraction, multiplication of the two
polynomial, linked lists is useful.
 They are used in dynamic memory management to allocate and release memory at runtime.
 It is used to find the sum of two long integers.
 It is used to represent queues, stacks in memory resulting in efficient use of storage and
computer time.
 It is used in symbol table construction to balance the parenthesis.
 It is used in representing sparse matrix
 It is used in memory management of operating systems.

91
DATA STRUCTURE

CHAPTER 8: TREES

Non-linear data structures: Trees


 A tree is a data structure which is collection of zero or more nodes and finite set of directed
lines called branches that connect to nodes.
 The first node in the tree is called root node and remaining nodes are partitioned into various
sub tress.
 Data structures using linear ordering was maintained using arrays and linked lists, for some
of the problems it is not possible to maintain linear ordering.
 Using non-linear data structures such as trees, graphs, multi-linked structures etc., and more
complex relations can be expressed.
 A tree which is also a doubly linked list, but field like llink does not point to predecessor and
field rlink does not point to successor, instead they point to some other trees.

Trees can be classified into two groups


 General tress
 Binary tress

Trees
 Tree is a non-linear data structure. It is an abstract data type that stores elements
hierarchically. It is a collection of nodes. With the exception of the top element, each element
in a tree has a parent element and zero or more children elements.
 The top most node/element is called as root and the other nodes are called sub trees / child
node.

92
DATA STRUCTURE

Properties of tree
 There is precisely one root node.
 All nodes except the root have precisely one parent.
 There are no cycles. That is, starting at any given node, there is no path that can take back to
the starting node.
 The first two properties – that there exists one root and that all nodes save the root have one
parent – guarantee that no cycles exist.

Binary tree
 Binary tree is a tree which is collection of zero or more nodes and finite set of directed lines
called branches that connect the nodes.
 A binary tree is an ordered tree in which each internal node can have a maximum of two
child nodes connected to it. In a binary tree, the first child of an internal node is called the
left child, and the second child is called the right child. The sub-tree rooted to at the left and
right of a child is called the left sub-tree and the right sub-tree.
 The number of branches associated with each node is called degree of a node.

93
DATA STRUCTURE

 When a branch is directed towards node, it is called has indegree branch.


 When a branch is directed away from the node, it is called has outdegree branch.
 A tree can be empty or partitioned into three groups:
o Root: if tree is not empty, the first node is called root.

o Left subtree: it is a tree connected to the left of root. Since it comes under root, it is
called left subtree.
o Right subtree: it is a tree connected to the right of root. Since it comes under root, it is
called right subtree.

Various Terminologies

Root node: The first node in the tree and with the indegree zero is called root node. It does not
have any parent node.

94
DATA STRUCTURE

Child node: The node, which can be reachable from a node x, using only one edge are called
children of node x and node x is the parent for all those children.

Parent node: A node that has at most one child is called parent node of that child. A node
having left or right or both subtree is said to be parent node.

Siblings: Two or more nodes having the same parent.

Ancestors: The nodes in the path from root to the specified node x.

Descendents: The nodes in the path below the parent, the node that are all reachable from
node x are all called descendent.

Left Descendents: The node that lie towards left subtree of node x.

Right Descendents: The node that lie towards right subtree of node x.

Subtree: A node having at most one child node and all the nodes that are descendents of a
node x is called subtrees.

Left Subtree: A node having at most one left child and all the nodes that are left descendents
of a node x is called left subtrees.

Right Subtree: A node having at most one right child and all the nodes that are right
descendents of a node x is called right subtrees.

Leaf: a node in a tree that has an outdegree of zero. A node with an empty left and right child is
called leaf node.

95
DATA STRUCTURE

Internal nodes: the nodes expect leaf nodes in a tree are called internal nodes. A node is a
internal node if it has one more children.

External nodes: the leaf nodes in a tree are called external or terminal node. A node is a
terminal node if it has no children.

Level: the distance of a node from the root is called level of the node. In a tree, the root has a
level 0 and other node is one more than the parent.

Height/depth: the height of the tree is defined as the maximum level of any leaf in the tree or
maximum number of nodes in a branch of tree. It also called as depth.

Degree of a node: The number of subtrees connected to a node.

Degree of a tree: The maximum height of the tree or the maximum degree of nodes in the
tree.

96
DATA STRUCTURE

Properties of a binary tree


Binary tree have several interesting properties, which includes the following:
 In a binary tree T, the number of external nodes is one more than the number of internal
nodes.
 The maximum number of nodes in a particular level I of a binary tree is given by the
expression
2 I-1
 The maximum number of nodes upto a particular level I of the binary tree is given by the
expression
2I - 1
The binary tree of depth K that has exactly 2K-1 nodes is a called FULL BINARY TREE of the
depth K i.e., all internal nodes in the binary tree has exactly two child nodes and all the terminal
nodes are at the same level.

Left skewed and right skewed tree


 Left skewed tree: a binary tree with only left subtree is called left skewed tree.
 Right skewed tree: a binary tree with only right subtree is called right skewed tree.

97
DATA STRUCTURE

Types of Binary Tree

Strictly binary tree: if the outdegree of


every node in a tree is either 0 or 2, then it is
said to be strictly binary tree each node
having maximum two child or empty.

Complete binary tree: a strictly binary


tree in which the number of node at any
level i is 2i, is said to be a complete binary
tree.

Binary search tree: It is a binary tree in


which for each node say x in the tree,
elements in the left-subtree are less than
info(x) and the elements in the right-subtree
are greater or equal to info(x). Every node in
the tree should satisfy this condition, if there
exists a left or right subtree.

Expression tree: It is a binary tree that


satisfy the following properties

98
DATA STRUCTURE

 Any leaf is an operand


 The root and internal nodes are operators
 The subtrees represent sub expressions
with root of the subtree as an operator

Almost complete binary tree: It


should satisfy the following properties
 If the tree is complete up to the level d-
1, then total no of nodes at level d-1
should be 2d-1.
 The total no of nodes at level d may be
equal to 2d. If the total no of nodes at
level d < 2d, then the no of nodes at level
d-1 should be 2d-1 and in level d the
nodes should be present only from left to
right.

Storage Representation of a Binary Tree


It can be classified as shown below:
 Sequential allocation technique (using arrays)
 Linked allocation technique (using dynamic allocation)

Linked allocation technique


A node in a tree has three fields
 info – which contains the actual information
 llink – which contains address of the left subtree
 rlink - which contains address of the right subtree

99
DATA STRUCTURE

A node can be represented using structure:


struct node
{
int info;
struct node *llink;
struct node *rlink;
};
typedef struct node* NODE;
A pointer variable root is used to point root node. If tree is empty, root points to NULL. The root
pointer variable can be declared and initialized as shown below:
NODE root = NULL;

Note: Memory can be allocated or de-allocated using malloc( ) and free( ) function.

Sequential/Static allocation technique


A tree can also be represented using array, which is sequential in nature:
 The node is numbered sequentially from 0.
 The node with position 0 is considered as the root node.
 If an index i=0, it gives the position of the root node.
 The given position of any node is i, 2i+1 gives the position of left child and 2i+2 given the
position of the right child.
 If i = position of the left child, i+1 = position of the right child.
 If i = position of the right child, i-1 = position of the left child.
 If i = given position of any node, the parent position = (i-1)/2. if i is odd, it points to the left
child otherwise, it points to the right child.

Method1: In representation some of the locations may be used and some may not be used. To
indicate memory location are used or not flag field namely, link is used. If link=0, the
corresponding location is not used and indicates the absence of the node at that position.
 So each node contains two fields:

100
DATA STRUCTURE

 Info - storing information


 Link - indicates the presence and absence of a node

A structure declaration
#define max 20
struct node
{
int info;
int link;
};
typedef struct node NODE;
An array a of type NODE can be used to store different items and declared as shown below:
NODE a[max];

Method 2: Instead of using separate flag field link to check the presence of a node, one can
initialize each location in the array to 0 indicating the node is not used. Non-zero value in
location indicates the presence of the node.

Various operations binary tree


 Creation: to create a tree which consist of root, subtrees and child nodes
 Insertion: To insert a given item into a tree
 Deletion: To delete a from node the tree
 Search: To search for the specified item
 Traversal: To visiting the nodes of the tree one by one
 Copying: To obtain exact copy of the given tree

Creating a tree
It is process of creating a tree which consist of root, subtrees and child nodes

101
DATA STRUCTURE

Algorithm to create a tree


create_tree(int ele)
Step 1: declare NODE *curptr,*ptr,*temp
Step 2: assign temp (NODE*)malloc(sizeof(NODE))
Step 3: assign temp -> info ele
Step 4: assign temp -> llink NULL
Step 5: assign temp -> rlink NULL
Step 6: if(root==NULL) then
root temp
else
curptr root
while(curptr!=NULL) do
ptr curptr
curptr (ele > curptr->info) ? curptr->rlink : curptr->llink
end while
end if
if(ptr->info < ele) then
ptr->rlink temp
else
ptr->llink temp
end if

Inserting a node into tree


It is process of inserting a given item into a tree

Function to insert an item into a binary tree based on direction


NODE insert(int item, NODE root)
{
NODE temp; //node to be inserted
NODE cur; //child node
NODE prev; //parent node

102
DATA STRUCTURE

char direction[10]; //directions where the node has to be inserted


int i; //max depth where a node can be inserted
temp = getnode(); //obtain a node from the availability list
temp -> info=item; //copy the necessary information
temp -> llink = temp -> rlink = NULL;
if (root = = NULL) //node is inserted for the first time
return temp;
printf(“give the directions where you want to insert\n”);
scan(“%s”,direction);
toupper(direction); //convert the direction to upper case
prev = NULL;
cur = root;
for(i=0; i < strlen(direction); i++)
{
if(cur = = NULL)
break;
prev = cur; //parent
if( direction[i] = = ‘L’) //if the direction is L move towards left
cur = cur -> llink;
else //otherwise move towards right
cur = cur -> rlink;
}
if(cur != NULL || i != strlen(direction))
{
printf(“insertion not possible\n”);
free(temp);
return root;
}
if (direction[i-l] = = ‘L’) //insert the node at the leaf level
prev -> llink = temp; //attach the node to the left of the parent
else

103
DATA STRUCTURE

prev -> rlink = temp; //attach the node to the right of the parent
return root;
}

Traversals
Traversing is a method of visiting each node of a tree exactly once in a systematic order based on
the order. During traversing, info field of each node is visited and printed.

Different Traversal Technique of a Binary Tree


Preorder Traversal
The preorder traversal of a binary tree can
be recursively defined as follows:
1. Process the root Node [N]
2. Traverse the Left subtree in preorder [L]
3. Traverse the Right subtree in preorder
[R]

The C function to traverse the tree in Preorder


void preorder(NODE *root)
{
if(root!=NULL)
{
printf("%d\t", root >info); //visit the root node
preorder(root ->llink); //visit left subtree
preorder(root ->rlink); //visit right subtree
}
}

104
DATA STRUCTURE

Inorder Traversal
The inorder traversal of a binary tree can be
recursively defined as follows:
1. Traverse the Left subtree in inorder [L]
2. Process the root Node [N]
3. Traverse the Right subtree in inorder [R]

The C function to traverse the tree in Inorder


void inorder(NODE *root)
{
if(root!=NULL)
{
inorder(root ->llink); //visit left subtree
printf("%d\t", root >info); //visit the root node
inorder(root ->rlink); //visit right subtree
}
}

Postorder Traversal
The postorder traversal of a binary tree can
be recursively defined as follows:
1. Traverse the Left subtree in postorder
[L]
2. Traverse the Right subtree in postorder
[R]
3. Process the root Node [N]

105
DATA STRUCTURE

The C function to traverse the tree in Postorder


void postorder(NODE *root)
{
if(root!=NULL)
{
postorder(root ->llink); //visit left subtree
postorder(root ->rlink); // visit right subtree
printf("%d\t", root >info); // visit the root node
}
}

Searching
By traversing the tree in any of the order one can visit each node. As we visit the node we can
compare the info field of each node with the key to be searched. If found, display successful
search, otherwise display unsuccessful search.

The C program to search for an item


#include<stdlib.h>
void main( )
{
if(root = = NULL)
printf(“Tree is empty\n”);
else
{
printf(“Enter item to be search\t”);
scanf(“%d”, &item);
flag=0;
search(item, root,&flag);
if(flag = = 1)
printf(“Search successful\n”);
else

106
DATA STRUCTURE

printf(“Search unsuccessful\n”);
}
break;
}

Function to search for an item using Inorder Traversal


void search(int item, NODE root, int *flag)
{
if(root = = NULL)
return;
search(item, root -> llink, flag); //traverse left subtree
if(item = = root -> info) //visit the node
{
*flag = 1;
return;
}
search(item, root -> rlink, flag); //traverse right subtree
}

Function to search for an item using Preorder Traversal


void search(int item, NODE root, int *flag)
{
if(root = = NULL)
return;
if(item = = root -> info) //visit the node
{
*flag = 1;
return;
}
search(item, root -> llink, flag); //traverse left subtree
search(item, root -> rlink, flag); //traverse right subtree
}

107
DATA STRUCTURE

Function to search for an item using Postorder Traversal


void search(int item, NODE root, int *flag)
{
if(root = = NULL)
return;
search(item, root -> llink, flag); //traverse left subtree
search(item, root -> rlink, flag); //traverse right subtree
if(item = = root -> info) //visit the node
{
*flag = 1;
return;
}
}

Copying a tree
Here address of the root node is given and after copying, it returns address of the root node of the
new tree.

The C function to get the exact copy of a tree


NODE copy(NODE root)
{
NODE temp;
if(root = = NULL) //tree does not exist
return NULL;
temp = (NODE)malloc(sizeof(struct node)); //create a new node
temp -> lptr = copy(root->lptr); //copy the information field into the new tree
temp -> rptr = copy(root->rptr);
return temp; //return address of the new root node
}

108
DATA STRUCTURE

Binary search tree (BST)


It is a binary tree in which for each node say x in the tree, elements in the left-subtree are less
than info(x) and the elements in the right-subtree are greater or equal to info(x). Every node in
the tree should satisfy this condition, if there exists a left or right subtree.

Operations performed on binary search tree


 Creation – create a tree which is consist of root, subtrees and child nodes.
 Insertion – an item is inserted into the tree.
 Searching – search for a specific item in the tree (same as of binary tree).
 Deletion – deleting a node from a given tree (same as of binary tree).
 Traversing - visiting the nodes of the tree one by one (same as of binary tree).

Insertion
It is process of inserting an item into tree.

Function to insert an item into binary search tree


NODE insert (int item, NODE root)
{
NODE temp, cur, prev;
temp = getnode(); //obtain new node from availability list
temp->info = item; //copy appropriate data
temp->llink = NULL;
temp->rlink = NULL;
if(root = = NULL)
return temp; //insert a node for the first time
prev = NULL; //find the position to insert
cur = root;
while(cur != NULL)
{
prev = cur; //obtain parent position

109
DATA STRUCTURE

if(item =cur->info) //do not insert duplicate item


{
printf(“Duplicate items not allowed\n”);
free(temp);
return root;
}
if(item < cur->info)
cur = cur->llink; //obtain left child position
else
cur = cur->rlink //obtain right child position
}
if(item < prev->info) //if node to be inserted < parent
prev->llink = temp; //insert towards left of the parent
else
prev->rlink = temp; //insert towards right of the parent
return root;
}

Deletion
It is a process of deleting a node from a given tree.

Function to delete an item from the tree


NODE delete_item (int item, NODE root)
{
NODE cur, parent,suc,q;
if(root= =NULL)
{
printf(“tree is empty! Item not found\n”);
return root;
}
parent=NULL, cur=root; //obtain node to be deleted, its parent

110
DATA STRUCTURE

while(cur!=null)
{
if( item=cur->info)
break;
parent =cur;
cur= (item<cur->info) ? cur->llink : cur->rlink;
}
if(cur==NULL)
{
printf(“item not found\n”);
return root;
}

/ * item found and delete it * / //case 1


if (cur->llink= =null) //if left subtree is empty
q=cur->llink; //obtain non empty right subtree
else if (cur-> rlink= null) //if right subtree is empty
q=cur -> llink; //obtain non empty left subtree
else
{ //case 2
suc =cur->rlink; //obtain the inorder successor
while(suc->llink!=null)
suc=suc->llink;
suc->llink =cur->llink; //attach left of node to be deleted to left of
successor of node to be deleted
q=cur ->rlink; //right subtree obtained
}

if( parent =null )


return q; //if parent does not exist return q as root

111
DATA STRUCTURE

/ * connecting parent of the node to be deleted to q * /


if (cur=parent-> llink)
parent->llink=q;
else
parent->rlink=q;
free(cur);
return root;
}

Application of trees
 It is used to represent hierarchical relationship.
 It is used in the construction of symbol table.

112
DATA STRUCTURE

UNIT 3: SEARCHING AND SORTING

CHAPTER 9: SEARCHING
 Searching is an operation refers to finding a particular element and its location in a given list
of elements. There are some different searching techniques, which are fast and efficient but
some are slow in finding the desired element.
 The techniques involve searching large amounts of data to find a particular piece of
information. Certain methods of organizing data make the search process more efficient.

Two important searching techniques


 Linear search
 Binary search

LINEAR SEARCH: This method is simple and straight forward. It is also called as
‘Sequential search’. It is applicable when the array elements which are unsorted.
Logic:
 The ‘search key’ is compared with first element, if both the values are equal, the search
process stop.
 Otherwise same procedure is continued with next element, until the end of array.
 Search is successful is the element is found, else unsuccessful.

Algorithm for linear search


main( )
Step 1: start
Step 2: initialize loc 0, flag 0
Step 3: read “n”
Step 4: for i 1 to n do
read “a[i]”
end for
Step 5: read “item”

113
DATA STRUCTURE

Step 6: for i 1 to n do
if a[i] item then
loc i
flag 1
end if
end for
Step 7: if flag 1 then
write “Search is successful, item is found in the location”
else
write “Search is unsuccessful, element not found”
Step 8: end

Efficiency of Linear search


 In best case, if the element is in first position of the array, only one comparison is to be
performed, O(1).
 In Average case, if the element is present in last position of the array, then N comparison, the
number of comparison is O(n).
 If element appear in any given array position, a successful search will take (n + 1)/2
comparison and an unsuccessful search will take n comparisons (worst case), O(n).

Advantages of linear search


 Simple approach
 Works well for small arrays
 Used to search the elements in sorted/unsorted list

Disadvantages of linear search


 Less efficient if the array size is large
 If the elements are already sorted, this search method is not efficient.

114
DATA STRUCTURE

Binary search: This method can increase the efficiency of the search operation
Logic
 First find the middle element of the array
 Compare the mid element with an item, where item is the search element.

There are three cases


 If the desired element is same as item.
 If it is less than the desired item then search only the first half of the array.
 If it is greater than the desired item then search the second half of the array.
Repeat the same steps until an element is found or the search area is exhausted.

Algorithm for binary search


main( )
Step 1: start
Step 2: read “n”
Step 3: initialize loc 0
Step 4: for i 0 to n do
read “a[i]”
end for
Step 5: for i 0 to n do // loop for sorting a given array
for j 0 to n-1 do
if a[j]>a[j+1] then
temp a[j];
a[j] a[j+1];
a[j+1] temp;
end for(j)
end for(i)
Step 6: write “Sorted array elements”
for i 0 to n do
write “a[i]”
end for

115
DATA STRUCTURE

Step 7: read “key”


Step 8: initialize low 0, high n
Step 9: mid ((low + high)/2)
Step 10: while ((low <= high) && (a[mid] =! key)) do
if item < a[mid] then
high mid-1
else
low mid+1
end if
mid ((low + high)/2)
end while
Step 11: if a[mid] key then
loc mid
else
loc 0
end if
Step 12: if loc 0 then
write “search is unsuccessful, element not found”
else
write “search is successful, element found in the location”
end if
Step 13: end

Advantages of binary search


 Simple technique
 Very efficient

Disadvantages of binary search


 The list of elements were searching takes place should be sorted.
 To obtain the middle element this is possible only if the elements are stored in an array.
 If the elements are stored in linked list, this approach is not applicable.

116
DATA STRUCTURE

Efficiency of binary search


 In best case, if the element is equal to mid in the first comparison.
 In Average case, if the element is present in the left side or the right side of mid element of
the array, then comparison takes place by factor of 2, the maximum number of comparison is
log2n i.e., O(log n).
 In worst case, If element appear in any given array position, a successful search will take by
factor of 2 comparison and an unsuccessful search will take n comparisons, O(log n).

117
DATA STRUCTURE

CHAPTER 10: SORTING

Sorting is a process of arranging data in a particular order.


For instance: names arranged in an alphabetical order in telephone directory and numbers
arranged in a descending/descending order.

Sorting of the data elements involved rearranging, in movement of data from one place to
another within the given array list which reduces the cost of reorganization operation.

Some Sorting techniques


 Selection Sort
 Bubble Sort
 Insertion Sort
 Merge Sort
 Quick Sort
 Radix Sort

Selection Sort
This method is based on comparing and exchanging the top most element with the least
value, until all the elements in an array is sorted in particular order.

Algorithm for Selection Sort


Selection_sort (a, temp, n)
Step 1: Read n
Step 2: for i = 1 to n do
read a[i]
Step 3: for i = 1 to n-1 do
for j = i+1 to n do
if a[i] > a[j]
temp a[j]

118
DATA STRUCTURE

a[j] a[i]
a[i] temp
end if
end for (j)
end for (i)
Step 4: for i = 1 to n do
write “a[i]”
Step 5: end

Advantages of Selection Sort


 Simple and easy
 Straight forward approach

Disadvantages of Selection Sort


 Execution is slow and not efficient
 The iteration of the algorithm is n-1 times even if the elements are sorted.

Efficiency of Selection Sort


Comparisons required are (n-i)
 During 1st pass n-1 comparisons and the given array is sorted is said to be best case.
 During 2nd pass n-2 comparisons and so on.
f(n) = (n-1)+(n-2)+….+2+1
= (n(n-1))/2
= O(n2)
 Average case, (n(n-1))/2 = O(n2)
 Worst case, (n(n-1))/2 = O(n2)

119
DATA STRUCTURE

Bubble Sort
 Bubble sort is the simplest and easiest sorting technique. In this technique, the two successive
elements are swapped.
 Bubble sort differs from selection sort, in that, instead of finding the smallest record value
and then perform an interchange. The two values are interchanged immediately after
discovering that the elements are out of order.

Algorithm for Bubble Sort


Bubble_sort (a, temp, n)
Step 1: Read n
Step 2: for i 1 to n do
read a[i]
Step 3: for i 1 to n – 1 do
for j 1 to n – i do
if a[j] > a[j+1]
temp a[j]
a[j] a[j+1]
a[j+1] temp
end if
end for (j)
end for (i)
Step 4: for i 1 to n do
write “a[i]”
Step 5: end

Advantages of Bubble Sort


 Simple approach
 Straight forward technique

120
DATA STRUCTURE

Disadvantages of Bubble Sort


 It is less efficient when compared to selection sort
 The iteration of the algorithm is n-1 times even if the elements are sorted.

Efficiency of Bubble Sort


Comparisons required are (n-i)
 During 1st pass n-1 comparisons and the given array is sorted is said to be best case.
 During 2nd pass n-2 comparisons and so on.
f(n) = (n-1)+(n-2)+….+2+1
= (n(n-1))/2
= O(n2)
 Average case, (n(n-1))/2 = O(n2)
 Worst case, (n(n-1))/2 = O(n2)

Merge Sort
The technique is as follows
 Divide the sequence of elements into two parts.
 Recursively sort the elements on left part of the division.
 Recursively sort the elements on right part of the division.
 The process of merging of two sorted left and right parts of the array into a single sorted
array is called simple merge.
 To solve the problem of merge sort technique is that both arrays should be sorted either in
ascending or descending order.

Algorithm for Merge Sort


main( )
Step 1: start
Step 2: read “n”
Step 3: for i 0 to n do
read “a[i]”

121
DATA STRUCTURE

end for
Step 4: merge_sort(a,0,n-1) // calling function merge_sort
Step 5: write “Array after sorting”
for i 0 to n do
write “a[i]”
end for
Step 6: end

simple_merge(a, low, mid, high) //simple_merge function called to merge two


Step 1: start sorted array into single
Step 2: initialize the value for
i low, j mid+1, k low
Step 3: while (i<=mid && j<=high) do
if a[i] < a[j] then
c[k] a[i] //copy lowest element from 1st part of A to C
i i+1 //point to next element in the left part of A
k k+1 //point to next element in C
else
c[k] a[j] //copy lowest element from 2nd part of A to C
j j+1 //point to next element in the right part of A
k k+1 //point to next element in C
end if
end while
Step 4: while i<=mid do //copy the remaining elements from left part of array A to
C
c[k++] a[i++]
end while
Step 5: while j<=high do //copy the remaining elements from left part of array A to
C
c[k++] a[j++]
end while

122
DATA STRUCTURE

Step 6: for i low to high do //copy the elements from array C to A


a[i] c[i]
end for
return
Step 7: end

merge_sort(a, low, high) //merge_sort function called to divide a given array


Step 1: start
Step 2: if low < high then
mid (low+high)/2 //divide the array into equal parts
merge_sort(a,low,mid) //called function merge_sort to sort
the left part of array
merge_sort(a,mid+1,high) //called function merge_sort to sort
the right part of the array
simple_merge(a,low,mid,high) //called function simple_merge to
merge the left & right parts
end if
step 3: end

Efficiency of Merge Sort


In that case there will be approximately be n comparisons in the first pass, after which the array
is split into two sub arrays each approximately of the size n/2. For each of the sub arrays there
are approximately about n/2 comparisons and a total of four sub arrays each of size n/4 are
formed. Each of the sub arrays then requires n/4 comparisons and yielding n/8 sub arrays. After
repeating the process “m” times then there will be “n” sub arrays each of size 1.

Thus the total number of comparisons is approximately equal to


f(n) = n+2*(n/2)+4*(n/4)+…………+n*(n/n)
= n+n+n+…………….+n ( m times)
=O(n*m)
= O(n log n)

123
DATA STRUCTURE

 The best case occurs, when the array is divided into two exactly equal parts is O(n log n).
 The average case is O(n log n)
 he worst case is O(n2).
Quick Sort
 Quick sorting technique works well on large set of data.
 The first step
 Is to partition the given table into two sub-tables
 The elements towards left of the key element are less than the key element and elements
towards right of the key element are greater than key element
 After this step, the array is partitioned into two sub tables.
36 37 11 10 42 72 65 98 88 78
< 42 > 42

Algorithm for Quick Sort


main( )
Step 1: start
Step 2: read “n”
Step3: for i 0 to n do
read “a[i]”
end for
Step 4: write “Array before sorting”
for i 0 to n do
write “a[i]”
end for
Step 5: quick_sort(a,0,n-1) //quick_sort function calling
Step 6: write “Array after sorting”
for i 0 to n do
write “a[i]”
end for
Step 7: end

124
DATA STRUCTURE

int partition(int a[ ],int low, int high) //partition function called


Step 1: start
Step 2: initialize for values
i low, key a[low], j high
Step 3: while i<j do
while( i < high && key >= a[i]) do
i++
end while
while key < a[j] do
j- -
end while
if i < j then
temp a[i]
a[i] a[j]
a[j] temp
else
temp a[low]
a[low] a[j]
a[j] temp
return j
end if
end while
Step 4: end

quick_sort(int a[ ], int low, int high) //quick_sort function called


Step 1: start
Step 2: if low < high then
j partition(a,low,high) //partition function calling
quick_sort(a,low,j-1) //quick_sort function calling
quick_sort(a,j+1,high) //quick_sort function calling

125
DATA STRUCTURE

end if
Step 3: end

126
DATA STRUCTURE

Efficiency of Quick Sort


In that case there will be approximately be n comparisons in the first pass, after which the array
is split into two sub arrays each approximately of the size n/2. For each of the sub arrays there
are approximately about n/2 comparisons and a total of four sub arrays each of size n/4 are
formed. Each of the sub arrays then requires n/4 comparisons and yielding n/8 sub arrays. After
repeating the process “m” times then there will be “n” sub arrays each of size 1.

Thus the total number of comparisons is approximately equal to


f(n) = n+2*(n/2)+4*(n/4)+…………+n*(n/n)
= n+n+n+…………….+n ( m times)
= O(n*m)
= O(n log n)
 The best case occurs, when key is happens to divide the array into two exactly equal parts is
O(n log n).
 The average case is O(n log n)
 The worst case, when the key picked turns out to be the least element of the arrayto be sorted,
in every step and it is denoted as O(n2).

Insertion Sort
 Insertion sort was invented in 1959 by D. L. Shell and hence named as shell sort.
 This technique is similar to bubble sort, instead of comparing the adjacent elements one after
the other, far apart elements are compared.
 The given array is divided into sub-arrays through gap and then sort those sub-array. Once
the gap data is one, the elements will be sorted.
 It works very well when the array elements are partially ordered and the elements to be
sorted are very less.

127
DATA STRUCTURE

Instance of unsorted array by using Insertion Sort technique

Algorithm for Insertion Sort


main( )
Step 1: start
Step 2: read “n”
Step 3: for i 0 to n do
read “a[i]”
end for
Step 4: write “Array before sorting”
for i 0 to n do
write “a[i]”
end for
Step 5: insertion_sort (a, n) //calling function insertion_sort
Step 6: write “Array after sorting”
for i 0 to n do
write “a[i]”
end for
Step 7: end

128
DATA STRUCTURE

insertion_sort (int a[], int n) //insertion_sort function called


Step 1: start
Step 2: read i, j, item
Step 3: for i 0 to n do
item a[i]
j i-1
while (j>=0 && item<a[j]) do
a[j+1] a[j]
j j-1
end while
a[j+1] item
end for
Step 4: end

Efficiency of Bubble Sort


It is better than bubble sort; Comparisons required are (n-i)
 During 1st pass n-1 comparisons and the given array is sorted is said to be best case.
 During 2nd pass n-2 comparisons and so on.
f(n) = (1+2+….+(n-1))/2
= (n(n-1))/2
= O(n2)
 Average case, on the average there will be approximate (n-1)/2 comparisons in the inner
loop.
f(n) = (1/2)+(2/2)+….+(n-1)/2
= (n(n-1))/4 = O(n2)
 Worst case, when the array I sin reverse aorder and the inner loop must use maximum no of
i-1 comparisons
f(n) = (1+2+….+(n-1))/2
= (n(n-1))/2 = O(n2)

129
DATA STRUCTURE

Radix sort
 Radix sort technique is used by a mechanical card sorter.
 In radix sort they should be more than one digit. This method is based on the values of
individual digits in the positional weight representation of the decimal numbers to be sorted.
 For instance a three digit decimal number 275 consist of its most significant digit (MSD) 2 in
hundreds position, digit 7 in tens position and its least significant digit (LSD) 5 in the units
position.
 One can compare such numbers of equal lengths. Each digit is sorted in turn, starting with
LSD is compared with adjacent number and move if it’s greater into the respective pocket
and hence continue the process through the other digits in the given list from right-to-left
including MSD.
Ex: Consider 8 integer of 3-digit length, sort by Radix Sort Method
890, 456, 224, 122, 102, 275, 321, 765

130

You might also like