1.
1introduction Unit 1: Introduction to data Structure[4hrs][5marks]
1.1.1 Need of data structure
1.1.2 Types of data structure and its characteristics
1.2Abstract Data Type(ADT)
1.3 Basic algorithm design techniques (brute force, divide and conquer,
greedy algorithm, branch and bound , backtracking , randomized recursive
, dynamics programming)
1.4 Algorithm analysis
1.4.1 Time complexity and Space complexity
1.4.2 Best ,worst and average case analysis
1.4.3 Rate growth
1.4.4.Asymptotic notation :big Oh big Omaga and big theta
Data Structure
• Data Structure can be defined as the group of data elements which provides an
efficient way of storing and organizing data in the computer so that it can be
used efficiently.
• Example arrays, Linked List, Stack, Queue, etc
• Data Structures are the main part of many computer science algorithms as they
enable the programmers to handle the data in an efficient way.
• It plays a vital role in enhancing the performance of a software or a program as
the main function of the software is to store and retrieve the user’s data as fast
as possible
Need of data structure
• Efficient Data Storage
• Data Retrieval
• Processing Speed
• Reusability
• Abstraction
• Better Organization
• Optimization
Data Structure mainly specifies the following four things
• Organization of Data
• Accessing methods
• Degree of associatively
• Processing alternatives for information
Algorithm + Data Structure = Program
Data structure study covers the following points
• Amount of memory require to store.
• Amount of time require to process.
• Representation of data in memory.
• Operations performed on that data.
Classification of Data Structure
Primitive Data Structure
• Primitive data structures are basic structures and are directly operated upon
by machine instructions.
• Primitive data structures have different representations on different
computers. Integers, floats, character and pointers are examples of primitive
data structures.
• These data types are available in most programming languages as built in
type.
Integer: It is a data type which allows all values without fraction part. We
can use it for whole numbers.
Float: It is a data type which use for storing fractional numbers.
Character: It is a data type which is used for character values. X=
Pointer: A variable that holds memory address of another variable are
called pointer.
Characteristics of Primitive Data Structures .
• Basic Building Blocks
• Directly Operated by Machine Instructions
• Efficient Processing
• Fixed Memory Requirements
• Predefined in Programming Languages
.
Non primitive Data Type
• These are more sophisticated data structures.
• These are derived from primitive data structures.
• The non-primitive data structures emphasize on structuring of a group of
homogeneous or heterogeneous data items.
• Examples of Non-primitive data type are Array, List, and File etc.
• A Non-primitive data type is further divided into Linear and Non-Linear data
structure
Array: An array is a fixed-size sequenced collection of elements of the same
data type.
List: An ordered set containing variable number of elements is called as Lists.
File: A file is a collection of logically related information. It can be viewed as a
large list of records consisting of various fields.
Characteristics of Non-Primitive Data Types
• User-Defined
• Can Store Multiple Values
• More Complex
• Variable Memory Size
• Not Directly Supported by Machine Instructions
Linear data structures
A data structure is said to be Linear, if its elements are connected in linear fashion by means of
logically or in sequence memory locations.
There are two ways to represent a linear data structure in memory,
Static memory allocation
Dynamic memory allocation
The possible operations on the linear data structure are: Traversal, Insertion, Deletion, Searching,
Sorting and Merging.Examples of Linear Data Structure are Stack and Queue
Stack: Stack is a data structure in which insertion and deletion operations are performed at one
end only.
The insertion operation is referred to as ‘PUSH’ and deletion operation is referred to as
‘POP’ operation.
Stack is also called as Last in First out (LIFO) data structure.
Queue: The data structure which permits the insertion at one end and Deletion at another end,
known as Queue.
End at which deletion is occurs is known as FRONT end and another end at which insertion
occurs is known as REAR end.
Queue is also called as First in First out (FIFO) data structure.
Characteristics of Linear Data Structures
• Sequential Arrangement
• Single Level Traversal
• Each Element Has a Unique Predecessor and Successor
• Memory Utilization
• Easier Implementation
• Efficient for Storing and Accessing Ordered Data
Nonlinear data structures
Nonlinear data structures are those data structure in which data items are not arranged in a
sequence.
Examples of Non-linear Data Structure are Tree and Graph.
Tree: A tree can be defined as finite set of data items (nodes) in which data items are arranged in
branches and sub branches according to requirement.
Trees represent the hierarchical relationship between various elements.
Tree consist of nodes connected by edge, the node represented by circle and edge lives
connecting to circle.
Graph: Graph is a collection of nodes (Information) and connecting edges (Logical relation)
between nodes. A tree can be viewed as restricted graph.Graphs have many types:
• Un-directed Graph
• Directed Graph
• Mixed Graph
• Multi Graph
• Simple Graph
• Null Graph
Characteristics of Non-Linear Data Structures
• Hierarchical Relationships
• Multiple Paths of Traversal
• Each Element May Have Multiple Connections
• Complex Implementation
• Efficient for Certain Operations
• Dynamic Memory Usage.
Difference between Linear and Non Linear Data Structure
Linear Data Structure Non-Linear Data Structure
Every item is related to its previous and next Every item is attached with many other items.
time.
Data is arranged in linear sequence. Data is not arranged in sequence.
Data items can be traversed in a single run. Data cannot be traversed in a single run.
Eg. Array, Stacks, linked list, queue. Eg. tree, graph.
Implementation is easy. Implementation is difficult.
PCM@ DSA
Operation on Data Structures
Design of efficient data structure must take operations to be performed on the
data structures into account. The most commonly used operations on data
structure are broadly categorized into following types
Create
The create operation results in reserving memory for program elements. This
can be done by declaration statement. Creation of data structure may take place
either during compile-time or run-time. malloc() function of C language is used
for creation.
Destroy
Destroy operation destroys memory space allocated for specified data structure.
free() function of C language is used to destroy data structure.
Selection
Updation: It updates or modifies the data in the data structure.
Searching: It finds the presence of desired data item in the list of data items, it
may also find the locations of all elements that satisfy certain conditions.
Sorting: Sorting is a process of arranging all data items in a data structure in a
particular order, say for example, either in ascending order or in descending
order.
Merging: Merging is a process of combining the data items of two different
sorted list into a single sorted list.
Splitting: Splitting is a process of partitioning single list to multiple list.
Traversal: Traversal is a process of visiting each and every node of a list in
systematic manner.
ABSTRACT DATA TYPES (ADTS):
An abstract Data type (ADT) is defined as a mathematical model with a
collection of operations defined on that model.
Set of integers, together with the operations of union, intersection and set
difference form a example of an ADT.
An ADT consists of data together with functions that operate on that data.
Advantages/Benefits of ADT
Modularity
Reuse
Code is easier to understand
Implementation of ADTs can be changed without requiring changes to the
program that uses the ADTs.
THE LIST ADT
List is an ordered set of elements.
The general form of the list is A1 ,A2 , ……,AN
If the element at position i is Ai, then its successor is Ai+1 and its predecessor is
Ai-1
Various operations performed on List
Insert (X, 5)- Insert the element X after the position 5.
Delete (X) - The element X is deleted
Find (X) - Returns the position of X.
Next (i) - Returns the position of its successor element i+1.
Previous (i) Returns the position of its predecessor i-1.
Print list - Contents of the list is displayed.
Make-empty- Makes the list empty.
Implementation of list ADT:
Array based Implementation
Linked List based implementation
Comparison between Data structure and ADT,
Algorithm
An algorithm is defined as a step-by-step procedure or method for solving a
problem by a computer in a finite number of steps.
Steps of an algorithm definition may include branching or repetition depending
upon what problem the algorithm is being developed for.
While defining an algorithm steps are written in human understandable
language and independent of any programming language.
We can Implement it in any programming language of our choice.
Features:
Finiteness. An algorithm must always terminate after a finite number of steps.
Definiteness. Each step of an algorithm must be precisely defined; the actions
to be carried out must be rigorously and unambiguously specified for each case.
Input. An algorithm has zero or more inputs, i.e, quantities which are given to
it initially before the algorithm begins
Output. An algorithm has one or more outputs i.e, quantities which have a
specified relation to the inputs.
Effectiveness. An algorithm is also generally expected to be effective. This means
that all of the operations to be performed in the algorithm must be sufficiently
basic that they can in principle be done exactly and in a finite length of time.
Characteristics of an Algorithm
An algorithm must follow the mentioned below characteristics
Input: An algorithm must have 0 or well defined inputs.
Output: An algorithm must have 1 or well defined outputs, and should match with
the desired output.
Feasibility: An algorithm must be terminated after the finite number of steps.
Independent: An algorithm must have step-by-step directions which is
independent of any programming code.
Unambiguous: An algorithm must be unambiguous and clear. Each of their steps
and input/outputs must be clear and lead to only one meaning
Qualities of a good algorithm
• Input and output should be defined precisely.
• Each steps in algorithm should be clear and unambiguous.
• Algorithm should be most effective among many different ways to solve a
problem.
• An algorithm shouldn't have computer code. Instead, the algorithm should
be written in such a way that, it can be used in similar programming
languages.
Advantages of Algorithms:
It is a step-wise representation of a solution to a given problem, which makes
it easy to understand.
An algorithm uses a definite procedure.
It is not dependent on any programming language, so it is easy to understand
for anyone even without programming knowledge.
Every step in an algorithm has its own logical sequence so it is easy to debug.
By using algorithm, the problem is broken down into smaller pieces or steps
hence, it is easier for programmer to convert it into an actual program
Disadvantages of Algorithms:
Algorithms is Time consuming.
Difficult to show Branching and Looping in Algorithms.
Big tasks are difficult to put in Algorithms
Basic Algorithm Design Techniques
An algorithm design is a process that involves creating a step-by-step procedure or set of
instructions for a computer to follow while performing a task or solving a problem.
This process involves a series of steps, including problem analysis, requirements
gathering, algorithm design, and implementation.
The goal of these steps is to create an algorithm that is reliable, efficient, and correct.
Some of the most common types of algorithm design include
Brute Force Divide and Conquer
Greedy Dynamic Programming
Backtracking Branch and Bound
Recursion Randomized
Brute Force
Try all possible solutions to find the correct one.
Small inputs; exhaustive search.
Example: Linear search, generating all permutations.
Divide and Conquer
Divide the problem into smaller subproblems, solve them recursively, then
combine the results.
Problems that can be broken into independent parts.
Example: Merge Sort, Quick Sort, Binary Search.
Greedy Algorithm
Make the best local choice at each step, hoping for the global optimum.
Optimization problems where local decisions lead to optimal solutions.
Example: Dijkstra’s algorithm, Kruskal’s algorithm, Activity selection.
Dynamic Programming (DP)
Solve overlapping subproblems and store results to avoid recomputation.
Optimization problems with overlapping subproblems and optimal substructure.
Example: Fibonacci (with memoization), 0/1 Knapsack, Longest Common
Subsequence.
Backtracking
Build a solution step-by-step and backtrack when a constraint is violated.
Constraint satisfaction problems.
Example: N-Queens, Sudoku solver, Maze solving.
Branch and Bound
Explore solution space and prune paths that can’t lead to better solutions.
Optimization problems with constraints.
Example: Travelling Salesman Problem, 0/1 Knapsack (exact solution).
Recursive Algorithms
Solve a problem by solving smaller instances of the same problem.
Naturally recursive structures (trees, math functions).
Example: Factorial, Tree traversals, Fibonacci (basic version)
Randomized Algorithms
Use random choices in logic to simplify or speed up computation.
Problems where deterministic approaches are slow or complex.
Example: Randomized Quick Sort, Monte Carlo algorithms, Randomized
primality testing.
Analysis algorithm
The term analysis of algorithms is used to describe approaches to the study
of the performance of algorithms. In this course we will perform the
following types of analysis:
the worst-case runtime complexity of the algorithm is the function
defined by the maximum number of steps taken on any instance of size a.
the best-case runtime complexity of the algorithm is the function defined
by the minimum number of steps taken on any instance of size a.
the average case runtime complexity of the algorithm is the function
defined by an average number of steps taken on any instance of size a.
Algorithm Complexity are two types
Time complexity
Time complexity of an algorithm signifies the total time required by the
program to run till its completion.
The time complexity of algorithms is most commonly expressed using the
big O notation. It's an asymptotic notation to represent the time
complexity.
Time Complexity is most commonly estimated by counting the number of
elementary steps performed by any algorithm to finish execution.
To calculate the time complexity of an algorithm:
Identify the basic operations(Assignment, comparisons,arithemetic
Operation and fun calls)
Count how many times those operations run relative to the input size n
Use Big O notation
Three cases while calculating Time complexity
• Worst case: An algorithm takes more time to execution is called the
worst case, it is mostly in cases of loops where execution time is
depends upon the number of input size.
• Average case: An algorithm takes time between the best and worst
case to execution is called the Average case.
• Best case: An algorithm takes expected to execution is called the best
case
Space Complexity of Algorithms
Whenever a solution to a problem is written some memory is required to complete.
For any algorithm memory may be used for the following: Variables (This include
the constant values, temporary values)
Program Instruction
Execution
Space complexity is the amount of memory used by the algorithm (including the
input values to the algorithm) to execute and produce the result.
Sometime Auxiliary Space is confused with Space Complexity. But Auxiliary
Space is the extra space or the temporary space used by the algorithm during it's
execution.
Space Complexity = Auxiliary Space + Input space
Memory Usage while Execution
While executing, algorithm uses memory space for three reasons:
Instruction Space It's the amount of memory used to save the compiled
version of instructions.
Environmental Stack Sometimes an algorithm(function) may be called
inside another algorithm(function). In system stack, where they wait for
further execution and then the call to the inside algorithm(function) is
made.
For example, If a function A() calls function B() inside it, then all the
variables of the function A() will get stored on the system stack
temporarily, while the function B() is called and executed inside the
function A().such a situation, the current variables are pushed onto the
system stack, where they wait for further execution and then the call to the
inside algorithm(function) is made.
Calculating the Space Complexity
Space complexity refers to the total amount of memory an algorithm
needs to run to completion, including:
• Input storage
• Auxiliary (temporary) space used during computation
• Space for function calls, recursion stack, etc
Although the size of each data type may vary across operating systems
or architectures, the approach to calculating space complexity is
consistent
Example
int sum(int arr[], int n) { int arr[]:input array of size n =O(n)
int total = 0; total ,I,n:scalar variables=O(1)
for (int i = 0; i < n; i++) { Total Space Complexity=O(n)
total += arr[i];
}
return total;
}
Rate of Growth in Time Complexity
The rate of growth describes how the running time of an algorithm increases as the input
size n increases. It helps us compare the efficiency of algorithms.
Time Complexity Name Growth Rate Example Algorithm
O(1) Constant Time Doesn't grow with input size Accessing array element
O(log n) Logarithmic Time Grows slowly even with large Binary Search
inputs
O(n) Linear Time Grows directly with input size Simple loop over array
O(n log n) Linearithmic Time Slightly faster than quadratic Merge Sort, Quick Sort (avg)
Slower; grows quickly with
O(n²) Quadratic Time input Nested loops, Bubble Sort
O(n³) Cubic Time Very slow for large inputs 3 nested loops
O(2ⁿ) Exponential Time Grows extremely fast Recursive Fibonacci
Brute-force permutations (like
O(n!) Factorial Time Grows faster than exponential in TSP)
Asymptotic Notations
Asymptotic notations are mathematical tools used to describe the time or space complexity of
algorithms as input size n becomes large. They help us analyze performance independent of
hardware and implementation.
There are three main asymptotic notations
Big O Notation – O(n)
• Represents the worst-case time complexity.
• It gives an upper bound on the time.
• Useful for knowing the maximum time an algorithm may take.
It defines an upper bound on order of growth of time taken by an
algorithm or code with input size.
Mathematically, if f(n) describes the running time of an algorithm;
f(n) is O(g(n)) if there exist positive constant C and n0 such that, 0 <=
f(n) <= Cg(n) for all n >= n0
n = used to give upper bound a function.
If a function is O(n), it is automatically O(n-square) as well.
Omega Notation – Ω(n)
• Represents the best-case time complexity.
• It gives a lower bound on the time.
• Tells the minimum time the algorithm will take.
It defines a lower bound on order of growth of time taken by
an algorithm or code with input size.
Let f(n) define running time of an algorithm;
f(n) is said to be Ω(g (n)) if there exists positive
constant C and (n0) such that
0 <= Cg(n) <= f(n) for all n >= n0
n = used to given lower bound on a function
If a function is Ω(n-square) it is automatically Ω(n) as well
Theta Notation – Θ(n)
• Represents the average or exact-case time complexity.
• It gives a tight bound: both upper and lower bounds are the same.
• It defines exact order of growth of time taken by an
algorithm or code with input size.
• Let f(n) define running time of an algorithm.
Mathematically,
0 <= f(n) <= C1g(n) for n >= n0
0 <= C2g(n) <= f(n) for n >= n0
Merging both the equation, we get :
0 <= C2g(n) <= f(n) <= C1g(n) for n >= n0
• The equation simply means there exist positive constants C1
and C2 such that f(n) is sandwich between C2 g(n) and
C1g(n).
Difference Between Big oh, Big Omega and Big Theta :
S.No. Big O Big Omega (Ω) Theta (Θ)
It is like (<=) It is like (>=) It is like (==)
1. rate of growth of an algorithm is less than or equal to a specific rate of growth is greater than or equal to a meaning the rate of growth is equal to a
value. specified value. specified value.
The bounding of a function from above and
The upper bound of a function is represented by Big O notation. The lower bound of a function is represented below is represented by theta notation. The
2. Only the time taken function is bounded by above. B by Omega notation. exact asymptotic behavior is done by this
theta notation.
3. Big O - Upper Bound Big Omega (Ω) - Lower Bound Big Theta (Θ) - Tight Bound
To find Big O notation of time/space,. we consider the case To find Big Omega notation of time/space,. An algorithm's general time/space cannot be
4. when an algorithm takes maximum time/space. we consider the case when an algorithm represented as Theta notation, if its order of
takes minimum time/space. growth varies with input.
Mathematically: Big Omega is 0 <= Cg(n) <= Mathematically - Big Theta is 0 <= C2g(n) <=
5. Mathematically: Big Oh is 0 <= f(n) <= Cg(n) for all n >= n0 f(n) for all n >= n0 f(n) <= C1g(n) for n >= n0
Notation Meaning Case Describes
O(f(n)) At most f(n) steps Worst-case Upper bound
Ω(f(n)) At least f(n) steps Best-case Lower bound
Θ(f(n)) Exactly f(n) steps Average-case Tight bound (best
& worst same)
Assignment-I
Submitted Date 2081-2-12
1. Explain the need for data structures. Describe various types of data structures along with
their characteristics.
2. Define Abstract Data Type (ADT). Explain how ADTs help in efficient algorithm design
with suitable examples.
3. Discuss different algorithm design techniques with suitable examples. Compare their
approaches and use cases.
4. What do you understand by time and space complexity? Explain how to calculate both
with examples.
5. Define asymptotic notations. Explain Big O, Big Ω (Omega), and Big Θ (Theta) with
appropriate examples. Also, analyze an algorithm using these notations.