Module 1 DS Notes
Module 1 DS Notes
A data structure is a storage that is used to store and organize data. It is a way of arranging
data on a computer so that it can be accessed and updated efficiently. A data structure is not
only used for organizing the data. It is also used for processing, retrieving, and storing data.
sequentially or linearly, where each element is attached to its previous and next
adjacent elements, is called a linear data structure.
Example: Array, Stack, Queue, Linked List, etc.
2. Static Data Structure: Static data structure has a fixed memory size. It is easier
An Abstract Data Type (ADT) is a conceptual model that defines a set of operations and
behaviors for a data structure, without specifying how these operations are
implemented or how data is organized in memory. It is a type (or class) of objects whose
behaviour is defined by a set of values and a set of operations. The user interacts with the
interface, using the operations that have been specified by the abstract data type. It offers a
high level use of a concept independent of it's implementation. They package data structure
and operations on them hiding internal details.
A data type refers to the type of values that variables in a programming language hold.
Eg: Integer, real, character, and boolean are inherently provided in programming languages
are referred to as primitive data types.
The data objects which comprise the data structure, and their fundamental operations are
known as Abstract Data Type (ADT).
ADT is defined as a set of data objects D defined over a domain L and supporting a list of
operations O.
Examples -
Use a struct with public data and no functions to represent the record
Implementation of a simple
4 Implementation of a high level concept
concept
The efficiency or running time of an algorithm is stated as a function relating the input length
to the number of steps, known as time complexity, or volume of memory, known as space
complexity.
Algorithm
Algorthm/Program Developement:
Algorithm of Efficiency:-
Space Efficiency:- There are some circumstances where the space/memory used must be
analyzed. For example, for large quantities of data or for embedded systems programming.
1. instruction space : Affected by: the compiler, compiler options, target computer (cpu)
2. data space : Affected by: the data size/dynamically allocated memory, static program
variables,
3. run-time stack space : Affected by: the compiler, run-time function calls and recursion,
local variables, parameters
Clearly the more quickly a program/function accomplishes its task the better.
Algorithm Analysis:
Space Complexity
The space complexity of a program is the amount of memory that it needs to run to
completion. The space needed the program is the sum of the following components:
Eg:
𝐒𝐚𝐛𝐜(I) = 0
● Here, the summation is handled recursively. This means that the compiler must save
the parameters, local variables and the return address for each recursive call.
● The following table shows that the number of bytes required for one recursive call
under the assumption that an integer and the array each required 4 bytes.
Parameter 2 – integer n 4
return address 4
Total = 12
● The variable space is 12 for one time recursion. If ‘n’ is the size of an array,
then
● That is, in recursive function call, the space requirement is more compared
with the iteration space requirement.
Time Complexity
● Linear: O(n)
● Quadratic: O(n²)
● Cubic: O(n³)
● Exponential: O(2ⁿ)
To dive a bit deeper into the topic of algorithm complexity, let's take a closer look at some
common time complexity functions.
● Constant Time Complexity (O(1)): An algorithm that takes the same amount of time
to solve a problem, regardless of the size of the input data, has a constant time
complexity of O(1). An example of an O(1) algorithm is accessing an element in an
array by its index.
● Logarithmic Time Complexity (O(log n)): An algorithm that takes time proportional to
the logarithm of the size of the input data has a logarithmic time complexity. An
example of a logarithmic time complexity algorithm is binary search.
● Linear Time Complexity (O(n)): An algorithm that takes time proportional to the size
of the input data has a linear time complexity. An example of a linear time complexity
algorithm is linear search.
● Quadratic Time Complexity (O(n^2)): An algorithm that takes time proportional to the
square of the size of the input data has a quadratic time complexity. An example of a
quadratic time complexity algorithm is bubble sort.
● Cubic Time Complexity (O(n^3)): An algorithm that takes time proportional to the
cube of the size of the input data has a cubic time complexity. An example of a cubic
time complexity algorithm is matrix multiplication.
● The time T(P) taken by a program P is the sum of its compile time and its run time.
● Time complexity only consider execution(run) time. Type of time complexities are
• Worst case time complexity – The maximum value of f(n) for any possible
input.
• Average case time complexity – The expected value of f(n)
• Best case time complexity – minimum possible value of f(n).
Where f(n) is a function/ computing time of an algorithm.
Rules
● Comments & Declarations – Step count=0
● Return & Assignment – Step count= 1
● Ignore low order exponent when higher order exponents are present
Nested Loops
● The total running time of a statement inside a group of nested loop is the running
time of the statement multiplied by the product of the size of all the loops.
Eg: for (i=0;i<n;i++)
for (j=0;j<n;j++)
k++;
Consecutive Statements
These just add, which means that the maximum is the one that counts.
Eg:
for (i=0;i<n;i++) O(n)
a[i]=0;
for (i=0;i<n;i++)
for (j=0;j<n;j++) O(𝑛 )
a[i]+=a[j]+i+j;
This program fragment, which has O(n) works followed by O(n ) work, is also O(𝒏𝟐)
Best case scenario: The best case scenario describes the best-performing version of an
algorithm. This scenario occurs when the input data is particularly well-suited for the
algorithm, and the algorithm is able to solve the problem with minimal time and space
complexity.
Worst case scenario: The worst case scenario describes the worst-performing version of
an algorithm. This scenario occurs when the input data is particularly challenging for the
algorithm, and the algorithm takes a long time and requires a large amount of memory to
solve the problem.
Average case scenario: The average case scenario describes the average-performing
version of an algorithm. This scenario occurs when the input data is typical for the
algorithm, and the algorithm takes an average amount of time and requires an average
amount of memory to solve the problem.
Notations:
There are several notations used to express the time and space complexities of
algorithms. The most commonly used notations are:
● f(n) = O(g(n)) iff there exist 2 +ve constants c and n₀ such that |f(n)| ≤ c.|g(n)| for all
n≥ n₀
● When we say that the computing time of an algorithm is O(g(n)), we mean that its
execution takes no more than a constant time g(n).
|f(n)|≤ c. |g(n)|
f(n) ≤ n for n≥5
TC = O(𝒏𝟐)
2. Omega (Ω)
f(n) = Ω(g(n)) iff there exist +ve constants c and n₀ such that f(n)≥c.g(n) for all n, n≥n₀
TC = Ω (𝒏𝟐)
3. Theta (θ)
● f(n) = θ(g(n)) iff there exist +ve constants c₁ , c₂ and n₀ such that c₁.g(n)≤ f(n)≤c₂.g(n)
for all n, n≥n₀
Eg:3n +2
TC = θ (n)
Array
● An array is a consecutive set of memory locations. An array is a set of pairs, ie; index
& values.
● For each index which is defined, there is a value associated with the index. In
mathematical term we call this a correspondence or a mapping.
● Array can be defined as:
It is a linear data structure that allows efficient storage and retrieval of a fixed number of
data items.
Properties of Array:
Property Explanation
Homogeneous All elements in the array are of the same data type (e.g., all
Elements integers, all floats).
Efficient Element Accessing any element in an array takes constant time (O(1)),
Access (O(1)) due to direct indexing.
Static and Dynamic Arrays can be statically allocated (fixed at compile time) or
Allocation dynamically allocated (at runtime) in some languages.
Linear Data Structure Arrays are linear, meaning data is stored sequentially in
memory.
Memory Efficiency Arrays are memory efficient for storing similar data types
without additional overhead.
The addition (+) and subtraction (-) operators can be used between arrays if and only if the
two arrays have the same dimensions and order, and are defined using the same set of array
labels.
Eg: A[3:4]
Row = U₁-L₁+1
Column = U₂-L₂+1
Row Major
As its name implies, row major order stores multidimensional arrays by rows
A[L₁……..U₁ , L₂…….U₂]
U₂ = column representation
Eg:
𝟏𝟐𝟑
𝟒𝟓𝟔 A [3,3] in C, A[3][3]
𝟕𝟖𝟗
L₁ U₁ L₂ U₂
A[5:7,2:4]
m (row) = U₁-L₁+1 = 3
n (column) = U₂-L₂+1 = 3
A(6,3)
=Base address + (i-L₁) column + (j-L₂)
= 10+(6-5)3 + (3-2)
= 10+4 = 14
Column Major
As its name implies, Column major order stores multidimensional arrays by columns
Eg:
𝟏𝟐𝟑
𝟒𝟓𝟔
𝟕𝟖𝟗
Eg: A[6:9 , 3:6] find the address of A[8,5] , base address α=10.
L₁ U₁ L₂ U₂
A[6:9,3:6]
m (row) = U₁-L₁+1 = 9-6+1 = 4
n (column) = U₂-L₂+1 = 6-3+1= 4
A(8,5)
= 10+(8-6) + (5-3)х 4
= 10+2+8 = 20
SPARSE MATRIX
● A matrix is a two-dimensional data object made of ‘m’ rows and ‘n’ columns,
therefore having total m x n values. If most of the elements of the matrix have
0 values, then it is called a sparse matrix.
● Sparse matrix is a matrix which contains very few non-zero elements.
● When a sparse matrix is represented with a 2-dimensional array, we waste a
lot of space to represent that matrix.
Consider a matrix of size 100 X 100 containing only 10 non-zero elements. In this
matrix, only 10 spaces are filled with non-zero values and remaining spaces of the
matrix are filled with zero. Totally we allocate 100 X 100 X 2 = 20000 bytes of space
to store this integer matrix. To access these 10 non-zero elements we have to make
scanning for 10000 times.
Sparse Matrix Representations can be done in many ways following are two
common representations:
• Array representation
• Three tuple form
• Linked list representation
2D array is used to represent a sparse matrix in which there are three columns
named as:
Triplets
(0,2,3)
(0,4,4)
(1,2,5)
(1,3,7)
(3,1,2)
(3,2,6)
● Storage: There are lesser non-zero elements than zeros and thus lesser
memory can be used to store only those elements.
● Computing time: Computing time can be saved by logically designing a data
structure traversing only non-zero elements.
● Storage: We know that a sparse matrix contains lesser non-zero elements than zero,
so less memory can be used to store elements. It evaluates only the non-zero
elements.
● Computing time: In the case of searching in a sparse matrix, we need to traverse
only the non-zero elements rather than traversing all the sparse matrix elements. It
saves computing time by logically designing a data structure traversing non-zero
elements.
1ST METHOD
● One dimensional array is defined and coefficient is added to the array and
exponent is indicated by the index value
Eg : 2x +3x+1
● Here, array size is fixed. Usually it will be larger than the degree of
polynomial.
2ND METHOD
● Here a one dimensional array is defined and the coefficient is added to the
array and the exponent is represented by the array index.
● It differ from the first method in the size of array. Here size of the array is
defined as the largest degree of the polynomial.
Eg: 2x +1
3RD METHOD
● Here coefficient and exponent is stored in the array. Two pointers are used to
indicate the beginning and end of the polynomial.
● In this method , zero coefficient term is not used. There is no fixed size
allocation is needed.
el = ef+(n-1)
Where,
STACK
● It is a linear data structure in which elements are placed one above another.
● A stack is an ordered collection of homogeneous data elements where the insertion and
deletion operations take place only at one end called Top of the stack.
● LIFO - In stack elements are arranged in Last-In-First-Out manner (LIFO). So it is also
called LIFO lists.
● Anything added to the stack goes on the “top” of the stack.
● Anything removed from the stack is taken from the “top” of the stack.
● Things are removed in the reverse order from that in which they were inserted
Operations of Stack
Basic Operations
int peek() {
return stack[top];
}
bool isempty() {
if(top == -1)
return true;
else
return false;
}
Algorithm: PUSH()
Start
POP Operation
Algorithm: POP()
Start
● if top= -1 then
● print “UNDERFLOW”
● else
● set item=A[top]
● Set top=top-1
● exit
QUEUES
int peek()
{
return queue[front];
}
bool isfull()
{
If (rear == MAXSIZE - 1)
return true;
else
return false;
}
bool isempty()
{
if(front < 0 || front > rear)
return true;
else
return false;
}
Algorithm : Enqueue
Start
Algorithm : Dequeue
Start
Type of Queues
● Circular Queue
● Priority Queue
● Doubly ended Queue
5. CIRCULAR QUEUE
● It is a modification of simple queue in which the rear pointer is set to the initial
location, whenever it reaches the location max_size – 1.
else
Exit
Exit
7. PRIORITY QUEUE
● Regular queue follows a First In First Out (FIFO) order to insert and remove an item.
Whatever goes in first, comes out first.
● In a priority queue, an item with the highest priority comes out first.
● Therefore, the FIFO pattern is no longer valid.
● Every item in the priority queue is associated with a priority.
● It does not matter in which order we insert the items in the queue
● The item with higher priority must be removed before the item with the lower priority.
● If two elements have the same priority, they are served according to their order in the
queue.
● EnQueue: EnQueue operation inserts an item into the queue. The item can be inserted
at the end of the queue or at the front of the queue or at the middle. The item must
have a priority.
● DeQueue: DeQueue operation removes the item with the highest priority from the
queue.
● Peek: Peek operation reads the item with the highest priority.
● CPU Scheduling
● Graph algorithms like Dijkstra’s shortest path algorithm, Prim’s Minimum
Spanning Tree, etc
● All queue applications where priority is involved.
● For load balancing and interrupt handling in an operating system
A double-ended queue is a versatile data structure that allows for the insertion and deletion of
elements from both ends. A double-ended queue in the data structure is an extension of the
linear queue structure.
Deque provides greater flexibility in data handling. Unlike a standard queue, which follows
the First-In-First-Out (FIFO) principle, a deque can function in both FIFO and
Last-In-First-Out (LIFO) modes, making it suitable for various applications in programming
and algorithms.
Double-ended queues in the data structure are especially useful in scenarios where you need
to manage a collection of items with dynamic size and require efficient access to both ends.
They can be implemented using arrays or linked lists, each offering different performance
characteristics.
CONVERSION & EVALUATION OF EXPRESSIONS
● Prefix Expression (Polish notation): The operators occurs before the operand
● Postfix Expression (Reverse Polish notation): The operators occurs after the
operand
Given P is the postfix expression, the following algorithm uses a stack to hold operands. It
finds the value of the arithmetic expression P, Written in postfix notation.
Algorithm:
Step 1: Add “ ) “ at the end of P
Step 2: Scan P from left – right & repeat the steps 3 & 4
Step 3: If an operand occurs, PUSH it to stack.
Step 4: If an operator occurs, then
A: Remove the top elements of the stack.
When A is the top element and B is the next top element
B: Evaluate B A
C: Place the result of step B back to stack
Step 5: Set the value equals to TOP element of the stack.
Evaluate the expression 5 * ( 6 + 2 ) – 12 / 4
● Q = A + ( B * C - ( D / E ^ F ) * G ) * H
Symbol
Stack p
Scanned
(
A ( A
+ (+ A
( (+( A
B (+( AB
* (+(* AB
C (+(* ABC
- (+(- ABC*
( (+(-( ABC*
D (+(-( ABC*D
/ (+(-(/ ABC*D
E (+(-(/ ABC*DE
^ (+(-(/^ ABC*DE
F (+(-(/^ ABC*DEF
) (+(- ABC*DEF ^ /
* (+(- * ABC*DEF ^ /
G (+(- * ABC*DEF ^ /G
) (+ ABC*DEF ^ /G * -
* (+* ABC*DEF ^ /G * -
H (+* ABC*DEF ^ /G * - H
) ABC*DEF ^ /G * - H * +
Q=((A+B)*C–(D–E))^(F+G)
Ans:
Q=((A+B)*C–(D–E))^(F+G))
Symbol
Stack p
Scanned
0 (
( ((
( (((
A ((( A
+ (((+ A
B (((+ AB
) (( AB+
* ((* AB+
C ((* AB+C
- ((- AB+C*
( ((-( AB+C*
D ((-( AB+C*D
- ((-(- AB+C*D
E ((-(- AB+C*DE
) ((- AB+C*DE-
) ( AB+C*DE--
^ (^ AB+C*DE--
( (^( AB+C*DE--
F (^( AB+C*DE--F
+ (^(+ AB+C*DE--F
G (^(+ AB+C*DE--FG
) (^ AB+C*DE--FG+
) AB+C*DE—FG+^
Q=(A+B)*C/D+E^F/G
Ans :
Q=(A+B)*C/D+E^F/G)
Symbol
Stack p
Scanned
(
( ((
A (( A
+ ((+ A
B ((+ AB
) ( AB+
* (* AB+
C (* AB+C
/ (/ AB+C*
D (/ AB+C*D
+ (+ AB+C*D/
E (+ AB+C*D/E
^ (+^ AB+C*D/E
F (+^ AB+C*D/EF
/ (+/ AB+C*D/EF^
G (+/ AB+C*D/EF^G
) AB+C*D/EF^G/+