0% found this document useful (0 votes)
2 views

S2 Data Structures

The document provides an overview of algorithms and data structures, emphasizing the importance of analyzing running times and the impact of hardware and software environments. It covers various data structures such as arrays, linked lists, stacks, and queues, detailing their operations, advantages, and applications. Additionally, it discusses sorting algorithms and the concept of dynamic allocation in arrays.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

S2 Data Structures

The document provides an overview of algorithms and data structures, emphasizing the importance of analyzing running times and the impact of hardware and software environments. It covers various data structures such as arrays, linked lists, stacks, and queues, detailing their operations, advantages, and applications. Additionally, it discusses sorting algorithms and the concept of dynamic allocation in arrays.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 25

Unit 1

4.2 Analysis of Algorithms


A data structure is a systematic way of organizing and accessing data,
and an algorithm is a step-by-step procedure for performing some task
in a finite amount of time.
The running time of an algorithm or data structure method increases
with the input size.
The running time is affected by the hardware environment (processor,
clock rate, memory, disk, etc.) and software environment (operating
system, programming language, compiler, interpreter, etc.) in which
the algorithm is implemented, compiled, and executed.

4.2.1 Experimental Studies


Limitations of experimental studies of running times:
Experiments can be done only on a limited set of test inputs; hence,
they leave out the running times of inputs not included in the
experiment.
Difficulty comparing the experimental running times of two algorithms
unless the experiments were performed in the same hardware and
software environments.
We have to fully implement and execute an algorithm in order to study
its running time experimentally.

4.2.2 Primitive Operations


We define a set of primitive operations such as the following:
• Assigning a value to a variable
• Calling a function
• Performing an arithmetic operation (for example, adding two
numbers)
• Comparing two numbers
• Indexing into an array
• Following an object reference
• Returning from a function

Counting Primitive Operations


A primitive operation corresponds to a low-level instruction with an
execution time that is constant. Instead of trying to determine the
specific execution time of each primitive operation, we simply count
how many primitive operations are executed, and use this number t as
a measure of the running time of the algorithm.
This operation count correlates to an actual running time in a specific
computer, since each primitive operation corresponds to a constant-
time instruction, and there are only a fixed number of primitive
operations.
The number, t, of primitive operations an algorithm performs is
proportional to the actual running time of that algorithm.

Asymptotic notations are used to write the fastest and slowest


possible running time for an algorithm. These are also referred to as
'best case' and 'worst case' scenarios respectively.

Unit 2

Data Structure
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.
Linear data structure:
Data structure in which data elements are arranged linearly, where each element
is attached to its previous and next adjacent elements, is called a linear data
structure.

● Static data structure:


Static data structure has a fixed memory size. It is easier to access the
elements in a static data structure. (Ex. Array)

● Dynamic data structure:


In dynamic data structure, the size is not fixed. It can be randomly updated
during the runtime which may be considered efficient concerning the
memory (space) complexity of the code. (Ex. Queue, Stack, Linked List)

Non-linear data structure:


Data structures where data elements are not placed linearly are called non-linear
data structures. In a non-linear data structure, we can’t traverse all the elements
in a single run only. (Ex. Trees)

ARRAYS
An array is a collection of items stored at contiguous memory locations.
The idea is to store multiple items of the same data type together.

Array Operations:
1. Insertion Operation
In the insertion operation, we are adding one or more elements to the array.
Based on the requirement, a new element can be added at the beginning, end, or
any given index of array. This is done using input statements of the programming
languages.

2. Deletion Operation
In this array operation, we delete an element from the particular index of an
array. This deletion operation takes place as we assign the value in the
consequent index to the current index. Elements can be deleted from an array by
shifting the elements that come after it to fill the gap.

3. Search Operation
Searching for elements: Arrays can be searched for a specific element using
linear search or binary search algorithms. The search operation can be
performed by linear traversal from the first element to the last element.
Algorithm (Linear Search) :
1. Start
2. Create an Array of a desired data type and size.
3. Initialize a variable ‘i’ as 0.
4. Enter the element at ith index of the array.
5. Increment i by 1.
6. Repeat Steps 4 & 5 until the end of the array.
7. Stop

4. Sorting elements
Elements in an array can be sorted in ascending or descending order using
algorithms like bubble sort, insertion sort, or quick sort, count sort.

5. Display Operation
This operation displays all the elements in the entire array using a print
statement.

6. Updating elements
Elements in an array can be updated or modified by assigning a new value to a
specific index.

7. Traversing elements
The elements in an array can be traversed in order, visiting each element once.

Applications of Array:
1. Sorting: Arrays can be used to sort data in ascending or
descending order. Sorting algorithms such as bubble sort, merge
sort, and quicksort rely heavily on arrays.
2. Storing and accessing data: Arrays are used to store and retrieve
data in a specific order. For example, an array can be used to store
the scores of a group of students, or the temperatures recorded by a
weather station.
3. Searching: Arrays can be searched for specific elements using
algorithms such as linear search and binary search.
4. Matrices: Arrays are used to represent matrices in mathematical
computations such as matrix multiplication, linear algebra, and
image processing.
5. Stacks and queues: Arrays are used as the underlying data
structure for implementing stacks and queues, which are commonly
used in algorithms and data structures.
Real-time applications of arrays:
● Financial Analysis: Arrays are used in financial analysis to store historical
stock prices and other financial data.
● Scientific Computing: Arrays are used in scientific computing to
represent numerical data, such as measurements from experiments and
simulations.
Advantages of array data structure:
● Efficient access to elements
● Memory efficiency
● Fast data retrieval
● Easy to implement

Sorting:
A Sorting Algorithm is used to rearrange a given array or list of elements
according to a comparison operator on the elements. The comparison operator is
used to decide the new order of elements in the respective data structure.
Insertion Sort:
Insertion Sort is a simple sorting algorithm that builds the final sorted array
one element at a time. It works by iteratively considering each element in
the input array and inserting it into its correct position in the already sorted
portion of the array. The algorithm is called "Insertion Sort" because it
inserts each element into its correct position.
Algorithm:
To sort an array of size N in ascending order, iterate over the array and
compare the current element (key) to its predecessor, if the key element is
smaller than its predecessor, compare it to the elements before. Move the
greater elements one position up to make space for the swapped element.

Characteristics:
● Simplest algorithms with a simple implementation.
● Efficient for small data values.
● Adaptive in nature; appropriate for data sets that are already partially
sorted.

Two-dimensional (2D) arrays:


● Arrays that are indexed by two subscripts, one for the row and one for the
column.
● Array that is organized in a grid or matrix-like structure with rows and
columns.
● It is essentially an array of arrays, where each element of the main array is
itself an array.
● This allows you to store data in a tabular form with rows and columns.
● To access elements in a 2D array, you need to specify both the row and
column index.

Dynamic allocation of arrays:


● Dynamic allocation of arrays refers to the process of allocating memory for
an array at runtime, instead of declaring it at compile time with a fixed size.
This allows you to create arrays whose size can be determined during
program execution, providing flexibility in handling data structures of
varying sizes.
● Dynamic allocation is particularly useful when you don't know the size of
the array in advance or when the size may change during program
execution.
● Dynamic allocation of arrays allows you to efficiently manage memory
usage and work with data structures whose size can change during
program execution, making it a valuable tool in many programming
scenarios.

LINKED LIST
● A linked list consists of nodes where each node contains a data field
and a reference(link) to the next node in the list.
● A linear data structure, in which elements are not stored at a contiguous
location, rather they are linked using pointers.
● Linked List forms a series of connected nodes, where each node stores
the data and the address of the next node.

Node Structure: A node in a linked list typically consists of two


components:
Data: It holds the actual value or data associated with the node.
Next Pointer: It stores the memory address (reference) of the next node in
the sequence.
Head and Tail: The linked list is accessed through the head node, which
points to the first node in the list. The last node in the list points to NULL or
nullptr, indicating the end of the list. This node is known as the tail node.

Types of Linked Lists

1. Singly Linked List


● It is the simplest type of linked list in which every node contains
some data and a pointer to the next node of the same data type
● A single linked list allows the traversal of data only in one way (forward).
● Head represents the first node, tail represents the last node.
● Accessing elements in a singly linked list requires traversing the list from
the head to the desired node, as there is no direct access to a specific
node in memory.

2. Doubly Linked List:


● In a doubly linked list or two way linked list, each node contains
references to both the next and previous nodes.
● Allows for traversal in both forward and backward directions, but it requires
additional memory for the backward reference.
● Delete operation in DLL is more efficient if a pointer to the node to be
deleted is given.
● It is used by web browsers for backward and forward navigation of web
pages.
● Contains three parts:
➔ data,
➔ a pointer to the next node, and
➔ a pointer to the previous node.

● A node can be inserted in a DLL in 3 ways:


➔ At front

➔ In between two nodes

➔ At end

3. Circular Linked List


● In a circular linked list, the last node points back to the head node,
creating a circular structure. It can be either singly or doubly linked.
● While traversing a circular linked list, we can begin at any node and
traverse the list in any direction forward and backward until we reach the
same node we started.
● A circular linked list has no beginning and no end.
● A node always points to another node, so NULL assignment is not
necessary.
● Any node can be set as the starting point.
● Nodes are traversed quickly from the first to the last.
● Two types of circular linked lists:
➔ Circular singly linked list
➔ Circular doubly linked list

Array VS Linked List


STACK
A stack is a linear data structure in which the insertion of a new
element and removal of an existing element takes place at the
same end represented as the top of the stack.
To implement the stack, it is required to maintain the pointer to the top of the
stack, which is the last element to be inserted because we can access the
elements only on the top of the stack.
LIFO( Last In First Out ):
This strategy states that the element that is inserted last will come out first.

Stack as an ADT:
For the stack data structure, the ADT defines the following operations:
push() : Inserts an element to the top of the stack.
pop() : Removes and returns the element from the top of the stack.
top (): Returns the top element of the stack without removing it.
isEmpty() : Checks if the stack is empty.
size () : Returns the number of elements currently in the stack.

Implementing Stack Using Array:


When using an array to create a stack, the "push" operation involves adding a
new element to the top of the stack by increasing the index of the top element
and placing the new element there. The "pop" operation, on the other hand,
involves removing the top element of the stack by decreasing the index of the top
element and retrieving the value stored at that index.
Advantages:
● Easy to implement.
● Memory is saved as pointers are not involved.
Disadvantages:
● The total size of the stack must be defined beforehand.

Implementing Stack Using Linked List:


When implementing a stack using a linked list, the 'push' operation adds a new
element by creating a new node and updating the 'next' pointer of the current top
node to point to this new node. On the other hand, the 'pop' operation removes
the top element by updating the 'next' pointer of the current top node to point to
the next node in the list and then returns the value of the removed node.

Advantages:
● Can grow and shrink according to the needs at runtime.
Disadvantages:
● Requires extra memory due to the involvement of pointers.
● Random accessing is not possible in stack.

Application of Stacks:
● Redo-undo features at many places like editors, photoshop.
● Forward and backward features in web browsers.
● In Memory management, any modern computer uses a stack as the
primary management for a running purpose. Each program that is running
in a computer system has its own memory allocations.
● Stack also helps in implementing function calls in computers. The last
called function is always completed first.
● Stacks are also used to implement the undo/redo operation in text editors.

In conclusion, a Stack is a linear data structure that operates on


the LIFO principle and can be implemented using an array or a
linked list. The basic operations that can be performed on a
stack include push, pop, and top. Stacks are commonly used in
computer science for a variety of applications, including the
evaluation of expressions, function calls, and memory
management.
Queues
A queue is a linear data structure that is open at both ends and
the operations are performed in First In First Out (FIFO) order.

A queue follows the First-In-First-Out (FIFO) principle, meaning that the first
element added to the queue will be the first one to be removed.

Queue as an ADT:
Operations of a queue are:
1. Enqueue() – Adds an element to the end of the queue.
2. Dequeue() – Removal of elements from the queue.
3. front() – Returns element at front end without removing it
4. rear() – This operation returns the element at the rear end without
removing it.
5. isFull() – Checks if the queue is full.
6. isNull() – Checks if the queue is empty
7. size() – This operation returns the size of the queue i.e. the total number
of elements it contains.

Implementing Queues using Arrays:


● For implementing a queue, we need to keep track of two indices, front and
rear. We enqueue an item at the rear and dequeue an item from the front.
● Increase front and rear in a circular manner.

Steps for enqueue:


● Check the queue is full or not
● If full, print overflow and exit
● If queue is not full, increment tail and add the element
Steps for dequeue:
● Check queue is empty or not
● if empty, print underflow and exit
● if not empty, print element at the head and increment head

Implement Queue using Linked List:


We maintain two pointers, front, and rear.
The front points to the first item of the queue and rear points to the last item.

enQueue(): This operation adds a new node after the rear and moves the rear to
the next node.
deQueue(): This operation removes the front node and moves the front to the
next node.

Double-ended queue as an ADT:


A deque allows elements to be added and removed from both
ends, providing more flexibility than a traditional queue.
Operations on Deque:
push_front() : Inserts the element at the beginning.

push_back() : Adds element at the end.

pop_front() : Removes the first element from the deque.

pop_back() : Removes the last element from the deque.

The size of the deque changes as elements are enqueued and dequeued.

The difference between stacks and queues is in removing. In a stack we


remove the item the most recently added; in a queue, we remove the item
the least recently added.

Time Complexity Analysis


O(1): Constant time complexity. The algorithm's execution time
remains constant regardless of the input size.
O(n): Linear time complexity. The algorithm's execution time grows
linearly with the input size.
Arrays:
● Access by Index: O(1)
● Search: O(n)
● Insertion/Deletion (at the End): O(1)
● Insertion/Deletion (in the Middle): O(n)
Linked List:
● Access by Index: O(n)
● Search: O(n)
● Insertion/Deletion (at the Beginning): O(1)
● Insertion/Deletion (at the End): O(n)
● Insertion/Deletion (in the Middle): O(n)
Stack:
● Push (Insertion): O(1)
● Pop (Deletion): O(1)
● Top: O(1)
● Search: O(n)
Queue:
● Enqueue (Insertion): O(1)
● Dequeue (Deletion): O(1)
● Front: O(1)
● Search: O(n)

Unit 3
Recursion
● Recursion is a programming technique in which a function calls itself
directly or indirectly to solve a problem.
● A recursive function is one that calls itself as part of its execution.
● Allows complex problems to be broken down into smaller, more
manageable subproblems, making it easier to solve them.
● Has a smaller code size.

Two parts of a Recursive Function:


● Base Case: This is the termination condition that defines when the
recursion should stop. It acts as a stopping criterion for the recursive calls.
Without a base case, the recursion would continue indefinitely, leading to a
stack overflow or infinite loop.
The base case is used to terminate the recursive function when the case
turns out to be true.

● Recursive Case: This is the part of the function where the function calls
itself to solve a smaller subproblem. The recursion continues until the base
case is reached, at which point the function starts to "unwind" and return
the results back through each level of recursion.

Algorithmic steps for implementing recursion in a function :


● Step1 - Define a base case: Identify the simplest case for which the
solution is known or trivial. This is the stopping condition for the recursion,
as it prevents the function from infinitely calling itself.

● Step2 - Define a recursive case: Define the problem in terms of smaller


subproblems. Break the problem down into smaller versions of itself, and
call the function recursively to solve each subproblem.

● Step3 - Ensure the recursion terminates: Make sure that the recursive
function eventually reaches the base case, and does not enter an infinite
loop.

● Step4 - Combine the solutions: Combine the solutions of the subproblems


to solve the original problem.

Every recursive call needs extra space in the stack memory.


Infinite recursion may lead to running out of stack memory (stack overflow).

Linear Recursion
● Linear recursion is a type of recursion where a function calls itself only
once in each recursive call.
● The recursion forms a chain-like sequence, with each recursive call
leading to one subsequent recursive call until the base case is reached.

Binary Recursion
● Binary recursion is a type of recursion in which a function calls itself two
times in each recursive call.
● It's characterized by splitting the problem into two smaller subproblems,
making it a binary branching process.
● Each recursive call generates two subsequent recursive calls until the
base case is reached.
● Binary recursion generates a binary tree-like structure of function calls
leading to the base case.

Unit 4

Trees
● A tree data structure is a hierarchical structure that is used to represent
and organize data in a way that is easy to navigate and search.
● It is a collection of nodes that are connected by edges and has a
hierarchical relationship between the nodes.
● Specialized method to organize and store data in the computer to be used
more effectively.
● The topmost node of the tree is called the root, and the nodes below it are
called the child nodes.

Properties of Tree Data Structure:


● Number of edges: An edge can be defined as the connection between
two nodes. If a tree has N nodes then it will have (N-1) edges. There is
only one path from each node to any other node of the tree.
● Depth of a node: The depth of a node is defined as the length of the path
from the root to that node. Each edge adds 1 unit of length to the path. So,
it can also be defined as the number of edges in the path from the root of
the tree to the node.
● Height of a node: The height of a node can be defined as the length of
the longest path from the node to a leaf node of the tree.
● Height of the Tree: The height of a tree is the length of the longest path
from the root of the tree to a leaf node of the tree.
● Degree of a Node: The total count of subtrees attached to that node is
called the degree of the node. The degree of a leaf node must be 0. The
degree of a tree is the maximum degree of a node among all the nodes in
the tree.

Binary Trees
A binary tree is a tree data structure in which each node can have at most two
children, which are referred to as the left child and the right child.

Properties of Binary Trees:


● The maximum number of nodes at level ‘l’ of a binary tree is 2l.
● The maximum number of nodes in a binary tree of height ‘h’ is 2h – 1
● Each node in a binary tree can have at most two child nodes
● The height of a binary tree is defined as the number of edges from the root
node to the deepest leaf node
● In a full binary tree, every node except the leaves has exactly two children

Inorder Traversal (left-current-right):


● Visit the current node after visiting all nodes inside the left subtree but
before visiting any node within the right subtree.
● Here, the traversal is left child – root – right child.
● It means that the left child is traversed first then its root node and finally the
right child.
● In-order traversal visits the left subtree, the node itself, and then the right
subtree.
Unit 5
Binary Search Trees
A Binary Search Tree is a special type of binary tree in which the left child of a
node has a value less than the node’s value and the right child has a value
greater than the node’s value. This property is called the BST property and it
makes it possible to efficiently search, insert, and delete elements in the tree.
The root of a BST is the node that has the largest value in the left subtree and
the smallest value in the right subtree.

Properties of Binary Search Tree :


● The left subtree of a node contains only nodes with keys lesser than the
node’s key.
● The right subtree of a node contains only nodes with keys greater than the
node’s key.
● This means everything to the left of the root is less than the value of the
root and everything to the right of the root is greater than the value of the
root. Due to this performance, a binary search is very easy.
● The left and right subtree each must also be a binary search tree.
● There must be no duplicate nodes.

Operations that can be performed on a


BST

Insertion Operation
A new key is always inserted at the leaf.
Start searching for a key from the root till a leaf node. Once a leaf node is found,
the new node is added as a child of the leaf node.

Time Complexity: O(N), where N is the number of nodes of the BST

Deletion Operation
It is used to delete a node with a specific key from the BST and return the new
BST.

Different scenarios for deleting the node:


● Node to be deleted is the leaf node : It's simple you can just null it out.
● Node to be deleted has one child : You can just replace the node with the
child node.
● Node to be deleted has two child :
If taking it from the left subtree, we have to take the largest value in the left
subtree.
If taking it from the right subtree, we have to take the smallest value in the
right subtree.
Time Complexity: O(log N), where N is the number of nodes of the BST

Searching Operation
Algorithm to search for a key in a given Binary Search Tree:
● We compare the value to be searched with the value of the root.
● If it’s equal we are done with the search. If it's smaller we know that we
need to go to the left subtree because in a binary search tree all the
elements in the left subtree are smaller and all the elements in the right
subtree are larger.
● Repeat the above step till no more traversal is possible
● If at any iteration, a key is found, return True. Else False.

Balanced Binary Search Tree


It is a type of binary tree in which the difference between the height of the left and
the right subtree for each node is either 0 or 1.

A balanced binary tree is a binary tree that follows the 3 conditions:


● The height of the left and right tree for any node does not differ by more
than 1.
● The left subtree of that node is also balanced.
● The right subtree of that node is also balanced.

Advantages of Balanced Binary Tree:


● Efficient Operations: They have quick search, insertion, and deletion
operations with a time complexity of O(log n), making them suitable for
large datasets.
● Guaranteed Performance: The worst-case time complexity is always
O(log n), ensuring consistent performance.
● Fast Search: Balanced trees ensure fast access to specific elements,
improving data retrieval tasks.
● Memory Efficiency: They don't require extra memory for balancing.

Unit 6
Binary Heap
A Binary Heap is a complete Binary Tree which is used to store data
efficiently to get the max or min element based on its structure.

● A Binary Heap is either Min Heap or Max Heap.


● In a Min Binary Heap, the key at the root must be minimum among all
keys present in Binary Heap.
● In a Max Binary Heap, the key at the root must be maximum among all
keys present in Binary Heap.

The traversal method use to


achieve Array representation is
Level Order Traversal.
This is a min binary heap.

Motivations of using a binary heap


● Efficient Operations: Binary heaps support essential priority queue
operations like insertion, deletion, and finding the highest (or lowest)
priority element .
● Simple Structure: Binary heaps are easy to implement using arrays.
● Space Efficiency: Binary heaps have a space-efficient representation.
● Priority Queue Applications.
● Heap Sort: Binary heaps also serve as the underlying data structure for
the Heap Sort algorithm
Priority Queues
● A priority queue is a type of queue that arranges elements based on their
priority values.
● Elements with higher priority values are typically retrieved before elements
with lower priority values.
● In a priority queue, each element has a priority value associated with it.
When you add an element to the queue, it is inserted in a position based
on its priority value.
● For example, if you add an element with a high priority value to a priority
queue, it may be inserted near the front of the queue, while an element
with a low priority value may be inserted near the back.
● Used in real-time systems, where the order in which elements are
processed can have significant consequences.

You might also like