You are on page 1of 118

Data Structures

And
Algorithms
DCS/CSC -204

Lecturer: Ntaye Emmanuel

www.ubids.edu.gh.com 1
AIM
❖ Introduce students to :

❖The fundamental building blocks for efficient computational


problems solution design.
✓Data structures
✓Algorithms
❖The course will focus on the logical structures of data, its design,
implementation and analysis of the complexity of their
implementing algorithms.

www.ubids.edu.gh.com 2
Course Outline
❑Definition of Data structure
❑Types of Data Structures
❑ Implementations in C++
✓ List
✓ Stacks
✓ Queue

❑ Algorithms and Operations


❑Time Complexity Analysis with Big O

www.ubids.edu.gh.com 3
Reading Materials:
1. Jay Wengrow (2020) A Common-Sense Gide to Data Structures
and Algorithms (Second Edition). The Pragmatic Programmers,
LLC.

2. Narashimha Karumanchi (2017) Data Structures and Algorithms


Made Easy. Career Monk.

3. Mark Allen Weiss (2014) Data Structures and Algorithms Analysis


in C++; Peason.

4. Robert Sedgewick and Kevin Wayne (2011) Algorithms. Addison-


Wesley.

www.ubids.edu.gh.com 4
What is Data Structure?
❖Data Structure is a particular way arranging, storing and
organizing data in the memory of the computer so that the data
can easily be retrieved and efficiently utilized in the future when
required.

❖Data structures define the relationship between the data


elements, how they are stored in memory, and the operations that
can be performed on them. They are designed to optimize the
efficiency of common operations such as insertion, deletion,
retrieval, and traversal of data.

www.ubids.edu.gh.com 5
What is Data Structure?
❖The choice of data structure for a particular task depends on
the type and amount of data to be processed, the operations
that need to be performed on the data, and the efficiency
requirements of the program.

❖Efficient use of data structures can greatly improve the


performance of a program, making it faster and more
memory-efficient.

❖An efficient data structure also uses minimum memory


space and execution time to process the structure.

www.ubids.edu.gh.com 6
Why should we learn Data Structures?
1) Data Structures and Algorithms are two of the key aspects of
Computer Science.

2) Data Structures allow us to organize and store data, whereas


Algorithms allow us to process that data meaningfully.

3) Learning Data Structures and Algorithms will help us become


better Programmers.

4) We will be able to write code that is more effective and


reliable.

5) We will also be able to solve problems more quickly and


efficiently
www.ubids.edu.gh.com 7
Objectives of Data Structures

• Correctness: Data Structures are designed to operate correctly for


all kinds of inputs based on the domain of interest. In order words,
correctness forms the primary objective of Data Structure, which
always depends upon the problems that the Data Structure is meant
to solve.

• Efficiency: Data Structures also requires to be efficient. It should


process the data quickly without utilizing many computer
resources like memory space. In a real-time state, the efficiency of
a data structure is a key factor in determining the success and
failure of the process

www.ubids.edu.gh.com 8
Significant Features of Data Structures

• Robustness: Generally, all computer programmers aim to produce


software that yields correct output for every possible input, along
with efficient execution on all hardware platforms. This type of
robust software must manage both valid and invalid inputs.

• Adaptability: Building software applications like Web Browsers,


Word Processors, and Internet Search Engine include huge software
systems that require correct and efficient working or execution for
many years. Moreover, software evolves due to emerging
technologies or ever-changing market conditions.

www.ubids.edu.gh.com 9
Significant Features of Data Structures

• Reusability: The features like Reusability and Adaptability go


hand in hand. It is known that the programmer needs many
resources to build any software, making it a costly enterprise.
However, if the software is developed in a reusable and adaptable
way, then it can be applied in most future applications. Thus, by
executing quality data structures, it is possible to build reusable
software, which appears to be cost-effective and timesaving

www.ubids.edu.gh.com 10
Basic terminologies related to Data Structures
Data Structures are the building blocks of any software or
program. Selecting the suitable data structure for a program is an
extremely challenging task for a programmer.
✓Data: We can define data as an elementary value or a
collection of values. For example, the Employee's name and
ID are the data related to the Employee.
✓Data Items: A single unit of value is known as Data Item.

✓ Group Items: Data Items that have subordinate data items


are known as Group Items. For example, an employee's name
can have a first, middle, and last name.

www.ubids.edu.gh.com 11
Basic terminologies related to Data
Structures
✓ Field: A single elementary unit of information symbolizing the
Attribute of an Entity is known as Field.
✓ Record: A collection of different data items are known as a
Record. For example, if we talk about the employee entity, then
its name, id, address, and job title can be grouped to form the
record for the employee.
✓Elementary Items: Data Items that are unable to divide into sub-
items are known as Elementary Items. For example, the ID of an
Employee.
✓Entity and Attribute: A class of certain objects is represented by
an Entity. It consists of different Attributes. Each Attribute
symbolizes the specific property of that Entity. For example
www.ubids.edu.gh.com 12
✓File: A collection of different records of one entity type is known as a
File. For example, if there are 100 employees, there will be 25 records in
the related file containing data about each employee

www.ubids.edu.gh.com 13
Types of Data Structures
Data Structures

Primitive Non-Primitive
Structure Data Structure

Linear Non-linear
int
(Sequential) (Random)

float Static Dynamic Trees Graphs

char Arrays Stacks Lists Queues Binary Directional graphs

One-Dimensional Non-directional
duoble Siingle-linked list Binary Search Trees
Arrays graphs

Two -Dimensioanl
Pointer Double-Linked List B-trees
Arrays

Multi-dimensional
Arrays Circular-Linked List AVL tree
www.ubids.edu.gh.com 14
Primitive Data Structures
❖Primitive data structures: These are the most basic and
predefined data structures and are usually built into programming
languages.
❖Examples include:
✓Integer
✓Float
✓Character
✓Boolean
✓Double
✓Pointer
✓Void www.ubids.edu.gh.com 15
Non-Primitive Data structures
❖Non-primitive data structures: These are complex data structures
that are built using primitive data types.
❖ Non-primitive data structures can be further categorized into the
following types:
✓Arrays: A collection of elements of the same data type, stored in
contiguous memory locations.
✓Linked lists: A collection of elements that are connected by links
or pointers.
✓Stacks: A collection of elements that follow the Last-In-First-Out
(LIFO) principle.

www.ubids.edu.gh.com 16
Non-Primitive data structures
✓Queues: A collection of elements that follow the First-In-
First-Out (FIFO) principle.

✓Trees: A hierarchical data structure consisting of nodes


connected by edges.

✓Graphs: A non-linear data structure consisting of nodes and


edges.

www.ubids.edu.gh.com 17
Differences between
Primitive and Non-Primitive Data Structures
Primitive Data Types Non-Primitive Data Types
1. Primitive data types are 1. Non-primitive data types are
predefined and provided by the
created by the programmer and are
programming language. also called user-defined data types.
2. They are atomic and store a
2. They are composite and store a
single value. collection of values or objects.
3.Primitive data types have a
3. Non-primitive data types can
fixed size in memory. have varying sizes depending on the
number of elements or objects they
contain.
4. They are passed by value 4. They are passed by reference,
when used as arguments in which means a reference to the
methods or functions. original object is passed rather than
the object itself.
www.ubids.edu.gh.com 18
Differences between
Primitive and Non-Primitive Data Structures
5. Primitive data types are stored 1. Non-primitive data types are
on the stack. stored on the heap.
6. They are initialized with default 6. Non-primitive data types need
values automatically (e.g., 0 for to be explicitly initialized by the
integers, false for booleans). programmer.
7. Primitive data types include 7. Non-primitive data types
integers, floating-point numbers, include arrays, strings, classes,
characters, booleans, structures, etc.
etc.
8. They have a limited set of 8. Non-primitive data types can
operations that can be performed have custom operations defined
directly on them (e.g., arithmetic by the programmer through
operations on numbers). methods or functions. 19
www.ubids.edu.gh.com
Differences between
Primitive and Non-Primitive Data Structures
9. Primitive data types are 9. Non-primitive data types may
generally faster to access and require more complex operations
manipulate. and have a higher overhead in
terms of performance.
10. They have a shorter lifespan 10. Non-primitive data types can
as they are short-lived and are have a longer lifespan as they can
destroyed as soon as they go out be dynamically allocated and
of scope. deallocated during program
execution

www.ubids.edu.gh.com 20
www.ubids.edu.gh.com 21
Linear Data Structure
❖ A Linear data structure is a type of data structure in which
data elements are arranged in a sequential order, and each
element has a unique predecessor and successor, except for the
first and last elements. Linear data structures are one-
dimensional and can be traversed sequentially from the first to
the last element. Elements are arranged in one dimension ,also
known as linear dimension.
Element 1 Element 2 Element 3 Element 4 Element 5 Element 5 ...

❖ Example: Arrays, lists, stack, queue, etc.

www.ubids.edu.gh.com 22
Linear Data Structure

Arrays Queues

Single-Linked list
Stacks www.ubids.edu.gh.com 23
Non-Linear Data Structure
❖ Non-linear data structure is a type of data structure in which
data elements are not arranged in a sequential order, and each
element may have one or more predecessors and successors.

❖ Non-linear data structures can represent complex relationships


between data elements, such as hierarchies, networks, and
graphs.

❖Elements are arranged in one-many, many-one and many-many


dimensions.

❖Example: tree, graph, table, etc.


www.ubids.edu.gh.com 24
Difference between Linear and Non-Linear
Data Structures
Linear Data Structures Non-Linear Data Structures
1. Data elements are arranged in a sequential 1. Data elements are not arranged in a
manner where each element has a unique sequential order and may have multiple
predecessor and successor. predecessors or successors.

2. Examples include arrays, linked lists, 2. Examples include trees and graphs.
stacks, and queues.
3. Linear data structures have a simple 3. Non-linear data structures have a
organizational structure. more complex organizational structure.

4. Elements can be accessed and processed 4. Elements may be accessed and


in a sequential manner. processed in various orders, depending
on the structure.
www.ubids.edu.gh.com 25
Difference between Linear and Non-Linear
Data Structures
5. Linear data structures have a 5. Non-linear data structures
fixed traversal order from the start can have multiple traversal
to the end. paths, loops, or cycles.
6. Insertion and deletion of 6. Insertion and deletion
elements are relatively operations can be more
straightforward and can be done at complex and depend on the
the beginning, end, or specific structure of the data.
positions.
7. Linear data structures are 7. Non-linear data structures
typically one-dimensional. can be multi-dimensional, with
relationships between multiple
elements.
www.ubids.edu.gh.com 26
Difference between Linear and Non-Linear
Data Structures
8. Searching for an element is usually 8. Searching for an element may
straightforward and involves traversing involve more complex algorithms,
through the structure sequentially. such as depth-first search or breadth-
first search.
9. Linear data structures have a simpler 9. Non-linear data structures often
memory allocation and deallocation require dynamic memory allocation
process. and more complex memory
management.
10. Linear data structures are suitable for 10. Non-linear data structures are
scenarios where the order and sequence of suitable for scenarios with complex
elements matter. relationships and interconnections
between elements

www.ubids.edu.gh.com 27
STATIC AND DYNAMIC DATA STRUCTURES
• A static data structure refers to a data structure with a fixed size
that is determined at compile time and cannot be altered during
program execution.

• The memory allocation for a static data structure is done in


advance and remains constant throughout the program's lifetime.

• They are efficient in terms of memory usage because the required


memory is allocated in advance and does not change.

• However, their fixed size can be limiting in scenarios where the


amount of data to be stored is unknown or may vary dynamically.

• Examples include static arrays, fixed-size matrices, and static


linked lists.
www.ubids.edu.gh.com 28
Dynamic Data Structure
• A Dynamic data structure refers to a data structure that can grow or
shrink in size during program execution.

• The memory allocation for a dynamic data structure is done at


runtime and can be adjusted based on the current needs of the program.

• Dynamic data structures are commonly implemented using dynamic


memory allocation mechanisms such as pointers or dynamic arrays.

• They allow for efficient memory usage as the memory is allocated


only when needed. Dynamic data structures are flexible and can adapt
to changing data requirements.

• Examples of dynamic data structures include dynamic arrays (e.g.,


ArrayList in Java, std::vector in C++), linked lists, stacks, queues, and
trees.

www.ubids.edu.gh.com 29
Point to note:
• It's important to note the difference between static and
dynamic data structures and static and dynamic typing .
Static and dynamic data structures refer to the management of
memory and data organization, while static and dynamic
typing refer to how data types are handled in a programming
language.
• Example of Statically typed programming languages are C ,
C++,Java, and Swift
• Example of Dynamically typed Programing languages are Python,
PHP, JavaScript, and Ruby.

www.ubids.edu.gh.com 30
DIFFERENCE BETWEEN DATA TYPE AND
DATA STRUCTURE
DATA TYPE DATA STRUCTURE
✓ Data type holds a single ✓ Data structure is a collection
value of a particular type of different kinds of data.

✓ Typically predefined in ✓ Often implemented as user-


programming languages defined or built-in data
structures
✓ Supports basic operations ✓ Supports complex operations
like assignment, like insertion, deletion,
comparison, and arithmetic search, traversal, etc.

www.ubids.edu.gh.com 31
DIFFERENCE BETWEEN DATA TYPE AND DATA
STRUCTURE
DATA TYPE DATA STRUCTURE
✓ There is no time complexity ✓ In data structures time
in the case of data type complexity plays a important
role.
✓ Implementation is easier ✓ Implementation is relatively
difficult.

✓ Examples: integer, float, ✓ Examples: array, linked list,


string, Boolean, double, stack, queue, tree, graph, etc.
char etc.

www.ubids.edu.gh.com 32
Algorithms
•Algorithms are sequence of steps performed
on the data using efficient data structure to
solve a given problem.

•Examples are sorting algorithm, searching


algorithm etc.

www.ubids.edu.gh.com 33
DATA STRUCTURES OPERATIONS
• Data structures support various operations that allow
for efficient manipulation and retrieval of data.

• The specific operations available depend on the type of


data structure being used.

• Some commonly used operations on data structures:


✓Searching or Accessing
✓Inserting
✓Deleting
✓Sorting
✓Updating
www.ubids.edu.gh.com 34
Access/search Operation
• This operation involves retrieving or searching for a
specific element within a data structure.

• It allows you to access a particular item based on its


value or index.

• Examples of access/search operations include:


✓ Finding an element in an array,
✓ Searching for a node in a linked list, or
✓ Looking up a key in a hash table.

www.ubids.edu.gh.com 35
Searching Operation
• Searching operations involve finding the location or
existence of a specific element within a data structure.

• It determines whether a particular item is present in the


data structure and returns its position or a Boolean value
indicating its presence.

• Popular search algorithms include


✓linear search,
✓binary search,
✓breadth-first search (BFS), and
✓depth-first search (DFS).
www.ubids.edu.gh.com 36
Sorting operation
•Sorting operations involve arranging the elements
in a data structure in a specific order, such as
ascending or descending.
•Sorting can be done based on element values or
specific criteria.
•Common sorting algorithms include:
✓Bubble sort
✓Insertion sort
✓Selection sort
✓Merge sort
✓Quicksort
✓Heapsort etc www.ubids.edu.gh.com 37
Deletion operation
• The deletion operation removes an element from a
data structure.

• Similar to insertion, deletion can occur at any


position within the data structure.

• Examples include removing an element from an
array, deleting a node from a linked list, or removing
a key-value pair from a tree or hash table.

www.ubids.edu.gh.com 38
Insertion operation
• The insertion operation involves adding a new element
to a data structure.

• It can be performed at the beginning, end, or any specific


position within the data structure.

• For example, inserting an element into an array, adding


a node to a linked list, or inserting a key-value pair into a
tree or hash table.

www.ubids.edu.gh.com 39
Update/Modification:
• This operation involves modifying the value of an
existing element within a data structure.

• It allows you to change the value of a specific item


without changing its position.

• For instance, updating an element in an array,


modifying the data in a node of a linked list, or
changing the value associated with a key in a hash
table.
www.ubids.edu.gh.com 40
Traversal Operation
•Traversal refers to visiting each element in a data
structure in a specific order or pattern.

•It allows you to process or examine each item


individually.

•Examples of traversal operations include iterating


over elements in an array, traversing through
nodes in a tree or graph, or visiting all keys in a
hash table.
www.ubids.edu.gh.com 41
ARRAYS

• Arrays are composite data types that allow storing a


fixed-size collection of elements of the same data type.
• They provide a way to organize related data under a
single variable name. Each element in an array is
accessed using an index, which represents its position
within the array.
• The value within the array are the element
• The nth element is the last element
• The kth element is the element of priority
www.ubids.edu.gh.com 42
Characteristics of Arrays
• Contiguous Memory: Arrays allocate a block of contiguous memory to
store elements of the same data type. This allows for efficient indexing and
direct access to elements based on their positions.

• Fixed Size: Arrays have a fixed size that is determined at the time of
declaration. The size remains constant throughout the lifetime of the array,
and it cannot be dynamically changed without creating a new array.

• Random Access: Elements in an array can be accessed directly using their


index values. This enables efficient and constant-time retrieval of elements.

• Homogeneous Elements: Arrays store elements of the same data type. All
elements in an array have the same size, allowing for efficient memory
allocation and access.

www.ubids.edu.gh.com 43
Characteristics of Arrays
• Indexing: Arrays use zero-based indexing, where the first
element is accessed using the index 0, the second element
with index 1, and so on. The index allows for quick and
direct access to any element within the array.

• Efficiency: Arrays provide efficient access to elements due to


their constant-time indexing. It makes them suitable for tasks
such as searching, sorting, and random access operations.

• Memory Efficiency: Arrays have a small memory overhead.


They only require memory to store the elements themselves,
along with some additional memory to store the size and the
starting address of the array.
www.ubids.edu.gh.com 44
Characteristics of Arrays
• Sequential Storage: Elements in an array are stored
sequentially in memory, which allows for cache-friendly
access and efficient traversal.

• Limited Flexibility: Arrays have a fixed size and cannot be


easily resized or expanded once created. Modifying the size
of an array often involves creating a new array and copying
the elements.

• Fast Insertion and Deletion at Ends: Adding or removing


elements at the ends of an array (first or last) can be done in
constant time. However, inserting or deleting elements in the
middle of the array requires shifting elements, resulting in a
time-consuming operation
www.ubids.edu.gh.com 45
Applications of Arrays
•Storing and accessing data:
•Mathematical and statistical operations:
•Sorting and searching
•Representing matrices and multidimensional
data:
•Implementing data structures:
•Graphics and image processing:
•Dynamic programming:.

www.ubids.edu.gh.com 46
Real World Applications of Arrys
• Databases: Databases often use arrays to store and organize data efficiently.
For example, an array can be used to store a list of customer names, product
information, or employee details. Arrays allow for quick retrieval and
manipulation of data in database management systems.

• Social media networks: Social media platforms employ arrays to handle


large amounts of user data. Arrays can store information such as user profiles,
posts, comments, and connections between users. By using arrays, social
media networks can efficiently manage and display user-generated content.

• Financial applications: Arrays are extensively used in financial applications


to manage and analyze financial data. Stock market data, portfolio values,
transaction history, and other financial information can be stored and
processed using arrays. Financial algorithms rely on arrays for computations,
analysis, and modeling.

www.ubids.edu.gh.com 47
Real World Applications of Arrays

• Gaming: Arrays are widely used in game development for various


purposes. For instance, an array can represent a game board, storing the
state of each cell or tile. Arrays can also hold information about game
assets, such as player attributes, enemy positions, or item inventories.
Game developers leverage arrays to implement game logic, collision
detection, and artificial intelligence.

• Geographic Information Systems (GIS): GIS applications use arrays to


represent geographical data, such as maps, satellite imagery, or terrain
models. Arrays can store information about elevation, land cover,
population density, and other spatial attributes. GIS algorithms rely on
arrays to perform spatial analysis and generate visualizations.

• Image and signal processing: Arrays are crucial in image and signal
processing applications. Images and signals are represented as
multidimensional arrays, where each element corresponds to a pixel or a
data point. Arrays enable manipulation of images and signals through
operations like filtering, noise removal, compression, and feature
extraction. www.ubids.edu.gh.com 48
Real World Applications of Arrays

• Scientific simulations: Arrays play a vital role in scientific


simulations and computational modeling. They are used to represent
grids, meshes, or other spatial structures in simulations of physical
systems. Arrays allow scientists and researchers to store and process
data from simulations, enabling analysis and visualization of complex
phenomena.

• Web development: Arrays are utilized in web development for tasks


like storing and manipulating form data, managing user sessions, and
handling data retrieved from databases. Arrays can be used to
represent lists of products, user preferences, or search results,
providing a structured way to store and process information on web
applications.

www.ubids.edu.gh.com 49
Types of Arrays
1. One-Dimensional Arrays: One-dimensional arrays, also
known as vectors or lists, store elements in a linear sequence.
Elements are accessed using a single index. For example, an
array of integers [3, 7, 2, 9, 5] is a one-dimensional array.
2. Multi-Dimensional Arrays: Multi-dimensional arrays
organize elements in multiple dimensions, such as rows and
columns or higher-dimensional arrangements. Common
examples include matrices, which are two-dimensional arrays,
and cubes, which are three-dimensional arrays.
3. Static Arrays: Static arrays have a fixed size defined at the
time of their declaration and cannot be resized during runtime.
The size of a static array is typically determined explicitly,
such as int [5] representing an array of five integers.

www.ubids.edu.gh.com 50
Types of Arrays
1. Dynamic Arrays: Dynamic arrays, also known as resizable
arrays or vectors, allow the size to be dynamically adjusted
during runtime. Dynamic arrays are particularly useful when the
number of elements is unknown or may change. Programming
languages may provide dynamic array implementations or
resizable data structures like ArrayList in Java or vectors in C++.
2. Jagged Arrays: Jagged arrays, also called ragged arrays, are
multi-dimensional arrays where each row can have a different
length. In contrast to regular multi-dimensional arrays with fixed
row and column sizes, jagged arrays provide flexibility in
accommodating varying row lengths.
3. String Arrays: String arrays store a collection of strings, where
each element is a string data type. They are commonly used to
hold lists of names, words, or any textual information.
www.ubids.edu.gh.com 51
Implementation of Arrays

• Declaration of Arrays:

type arrayName[arrySize];

Eg. Int a [5]; // a is an array of 10 elements

www.ubids.edu.gh.com 52
Implementation of Arrays

• C++ Array Initialization


In C++, it's possible to initialize an array during declaration. For
example,

// declare and initialize and array


int x[6] = {19, 10, 8, 17, 9, 15};

• Access Elements in C++ Array


• In C++, each element in an array is associated with a number. The number is known as an
array index. We can access elements of an array by using those indices.

• // syntax to access array elements


• array[index];

www.ubids.edu.gh.com
53
Practice
• Declare an array of any size with different types (int, float, string,
double etc)
• Initialize the elements
• Access each element and print out
• Print out all elements

• Declare with no size


• Insert members
• Access and print out

www.ubids.edu.gh.com 54
Implementation of Arrays

Taking Inputs
from User

www.ubids.edu.gh.com 55
Max and Min Value in Arrays

www.ubids.edu.gh.com 56
www.ubids.edu.gh.com 57
Algorithms
Algorithm refers to a well-defined set of instructions
or a step-by-step procedure for performing specific
operations on data structures.

It outlines the computational steps required to


manipulate or access the elements stored within a data
structure.

An algorithm can be seen as a recipe or a blueprint for


how to interact with a particular data structure.

www.ubids.edu.gh.com 58
Steps in writing and an Algorithm
• Understand the problem: Begin by thoroughly understanding the problem
or task you need to solve. Clarify the requirements, constraints, and expected
input-output behavior.

• Identify the inputs and outputs: Determine the input values or data required
by the algorithm, as well as the expected output or result.

• Break down the problem: Break down the problem into smaller,
manageable subtasks or steps. Identify the key operations or decisions needed
to solve the problem.

• Define the logical flow: Determine the logical flow of the algorithm. Use
constructs like conditionals (if-else statements), loops, and function calls to
control the flow and handle different cases.

www.ubids.edu.gh.com 59
• Write the steps in pseudocode: Express the algorithm steps in
pseudocode, which is a high-level, human-readable description of the
algorithm using plain language. Pseudocode should be clear, concise,
and independent of any specific programming language.

• Refine and validate the algorithm: Review the pseudocode,


ensuring that each step is correct, complete, and unambiguous.
Consider edge cases or potential issues that may arise. Validate the
algorithm's logic by walking through it manually for sample inputs.

• Implement the algorithm: Translate the pseudocode into a specific


programming language of your choice. Adapt the algorithm steps
using the syntax and constructs of the chosen language.

www.ubids.edu.gh.com 60
• Test and debug: Test the algorithm implementation with various test
cases, including typical inputs, edge cases, and boundary values.
Verify that the algorithm produces the expected outputs. If any issues
arise, debug and fix the algorithm accordingly.

• Analyze the algorithm's efficiency: Assess the time and space


complexity of the algorithm. Analyze its performance characteristics,
such as its scalability and efficiency for different input sizes.
Optimize the algorithm if necessary, considering algorithmic
techniques or data structures that may improve its efficiency.

• Document the algorithm: Document the algorithm by providing a


clear explanation of its purpose, inputs, outputs, and any relevant
assumptions or limitations. Include a description of its steps,
pseudocode, and any additional notes that may aid understanding

www.ubids.edu.gh.com 61
Sorting Algorithms for Arrays

www.ubids.edu.gh.com 62
Sorting Algorithm
•A sorting algorithm is a procedure or a set of
steps that arranges elements in a specific order.

•It takes an input sequence of elements, such as


an array or a list, and rearranges the elements
according to a predefined comparison criterion.

•The goal is to bring the elements into a particular


order, often in ascending or descending order,
based on their values or other defined attributes.

www.ubids.edu.gh.com 63
•Sorting algorithms vary in their approach,
complexity, and efficiency. Some algorithms
compare pairs of elements and swap them if
they are out of order, while others divide the
input into smaller subproblems and recursively
sort them.

•The choice of a sorting algorithm depends on


factors such as the size of the input, the
distribution of the data, stability requirements,
and time complexity considerations.
www.ubids.edu.gh.com 64
Bubble Sort
• Bubble sort repeatedly compares adjacent elements and
swaps them if they are in the wrong order.

• The process is repeated until the array is sorted.

• Bubble sort has a time complexity of O(𝑛2 )

✓O(𝑛2 ) indicates that the algorithm's performance is


directly proportional to the square of the input size.
As the input size grows, the time taken or the number
of operations performed by the algorithm increases
significantly.
www.ubids.edu.gh.com 65
Bubble Sort Steps
1) Start at the beginning of the array.
2) Compare the first and second elements. If the first element
is greater than the second element, swap them.
3) Move to the next pair of elements (second and third), and
continue comparing and swapping until reaching the end of
the array.
4) At this point, the largest element will be at the last position
of the array.
5) Repeat steps 1-4 for the remaining elements (excluding the
last element, which is already in its correct position).
6) After each pass, the next largest element will be placed in
its correct position from the end of the array.
7) Repeat steps 1-6 until the entire array is sorted, i.e., no
more swaps are needed.
www.ubids.edu.gh.com 66
Pseudocode For Bubble Sort

www.ubids.edu.gh.com 67
Bubble Sort

www.ubids.edu.gh.com 68
Implementation in C++

Write a an Algorithm for Bubble sort in


arrays and implement in C++

www.ubids.edu.gh.com 69
Selection Sort
✓Selection sort finds the minimum element from the
unsorted part of the array and swaps it with the element
at the beginning of the unsorted part.

✓The process is repeated until the array is sorted.

✓Selection sort has a time complexity of O(n^2).


➢This notation is derived from Big O notation, which is used
to describe the upper bound or worst-case time complexity of
an algorithm. The "n" in O(n^2) represents the input size or
the number of elements being processed, and the exponent of
2 signifies the polynomial relationship between the input size
and the time complexity.

www.ubids.edu.gh.com 70
Selection Sort:

www.ubids.edu.gh.com 71
Algorithm for Selection sort

www.ubids.edu.gh.com 72
www.ubids.edu.gh.com 73
Quick Sort
• Quick sort uses a divide-and-conquer strategy by
selecting a pivot element and partitioning the array into
two sub-arrays, one containing elements smaller than the
pivot and the other containing elements greater than the
pivot.
• The process is recursively applied to the sub-arrays until
the entire array is sorted.
• Quick sort has an average time complexity of O(n log n).
• Quicksort is an in-place sorting algorithm, meaning it
does not require additional memory proportional to the
input size. It swaps elements within the array during
partitioning, resulting in lower memory usage.
www.ubids.edu.gh.com 74
Quick Sort

www.ubids.edu.gh.com 75
Merge Sort
•Merge sort is a sorting algorithm that follows
the divide-and-conquer approach.

•It divides the input array into smaller


subarrays, recursively sorts them, and then
merges them back together to obtain a fully
sorted array.

•It is known for its efficiency and stability.

www.ubids.edu.gh.com 76
Merge Sort

www.ubids.edu.gh.com 77
Search Algorithm
• A search algorithm is a procedure or method used to find
the location, existence, or specific properties of a target
element or value within a given data structure.

• Search algorithms operate on various data structures such


as arrays, linked lists, trees, graphs, or hash tables.

• They employ different techniques and strategies to traverse


and examine the elements of these data structures to find
the desired target.
www.ubids.edu.gh.com 78
Search algorithms
• Linear Search: This is a simple and straightforward search algorithm
that sequentially checks each element of the data structure until the
target element is found or the entire collection has been examined.
• Linear search has a time complexity of O(n), where n is the size of
the collection.

www.ubids.edu.gh.com 79
Linear Search Algorithm
• Linear Search ( Array A, Value x)
• Step 1: Set i to 1
• Step 2: if i > n then go to step 7
• Step 3: if A[i] = x then go to step 6
• Step 4: Set i to i + 1
• Step 5: Go to Step 2
• Step 6: Print Element x Found at index i and go to step 8
• Step 7: Print element not found
• Step 8: Exit

www.ubids.edu.gh.com 80
Binary Search
• Binary Search: Binary search is an efficient search
algorithm that can be applied on sorted collections. It
repeatedly divides the search space in half by comparing
the target element with the middle element of the
collection.

• It continues this process until the target is found or the


search space is exhausted. Binary search has a time
complexity of O(log n), where n is the size of the
collection.

www.ubids.edu.gh.com 81
Steps of Binary Search
1. Sort the Array: Ensure that the array is sorted in ascending order.
Binary search requires the array to be sorted for accurate results.

2. Set Search Bounds: Define the lower bound (low) and upper
bound (high) for the search. Initially, set low to 0 (the first index of
the array) and high to the length of the array minus 1 (the last
index).

3. Start Binary Search: While low is less than or equal to high, do


the following steps:

a. Find the Middle Element: Calculate the middle index (mid) as the
average of low and high (rounded down to the nearest integer).

b. Compare with Target Value: Compare the value at the mid index with the
target value you are searching for.

www.ubids.edu.gh.com 82
Steps of Binary Search
• If the value at mid is equal to the target value, the search is successful, and
you can return mid as the position of the target value.
• If the value at mid is greater than the target value, set high to mid - 1 to search
in the lower half of the array.
• If the value at mid is less than the target value, set low to mid + 1 to search in
the upper half of the array.
4. Repeat the Binary Search: Go back to step 3 and repeat the process
until the target value is found or until low becomes greater than high.

5. Target Value Not Found: If the search exits the loop and low is
greater than high, it means the target value is not present in the array.

6. Return Result: If the target value is found, return the index of the
target value. Otherwise, return an indication that the target value is not
present in the array

www.ubids.edu.gh.com 83
Example of Binary search of Arrays
• Let's consider the sorted array: [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

• Initialize the search boundaries:

• low = 0 (index of the first element: 2)


• high = 9 (index of the last element: 20)
• Calculate the middle index:

• mid = (low + high) / 2 = (0 + 9) / 2 = 4 (index of the middle element:


10)
• Compare the target value (assume the target is 12):

• arr[mid] = arr[4] = 10
www.ubids.edu.gh.com 84
• Since 10 < 12, set low = mid + 1 = 4 + 1 = 5
• Repeat steps 2 and 3:

• Calculate the new middle index:


• mid = (low + high) / 2 = (5 + 9) / 2 = 7 (index of the middle element: 16)
• Compare the target value (12):
• arr[mid] = arr[7] = 16
• Since 16 > 12, set high = mid - 1 = 7 - 1 = 6
• Repeat steps 2 and 3:

• Calculate the new middle index:


• mid = (low + high) / 2 = (5 + 6) / 2 = 5 (index of the middle element: 12)
• Compare the target value (12):
• arr[mid] = arr[5] = 12
• The target value is found! Return the index 5.
www.ubids.edu.gh.com 85
www.ubids.edu.gh.com 86
Depth-First Search (DFS)
• Depth-First Search (DFS): DFS is a graph search algorithm
that explores as far as possible along each branch or path
before backtracking. It is often used to traverse and search for
elements in a tree or graph data structure. The time
complexity of DFS depends on the size and complexity of the
graph or tree being traversed.

• Breadth-First Search (BFS): BFS is another graph search


algorithm that explores all the vertices of a graph in breadth-
first order, i.e., it visits all the vertices at the same level
before moving to the next level. BFS is often used to find the
shortest path or to search for elements in a graph. The time
complexity of BFS depends on the size and complexity of the
graph being traversed.

www.ubids.edu.gh.com 87
• Hashing: Hashing is a technique used to index and search data in
hash tables. It involves mapping the target element to a unique
identifier called a hash value.
• By using the hash value as an index, the search algorithm can directly
access the corresponding element in constant time on average.
However, in the worst case, hashing can have a time complexity of
O(n), where n is the number of elements in the hash table.

• These are just a few examples of search algorithms. The choice of the
most appropriate search algorithm depends on various factors,
including the properties of the data structure, the size of the dataset,
and the specific requirements of the search operation.

www.ubids.edu.gh.com 88
www.ubids.edu.gh.com 89
Linked List
• A linked list is a linear data structure where each
element, known as a node, contains a value and a
reference (or link) to the next node in the sequence.
• Types of Linked list include;
• A singly-linked list is a type of linked list where
each node contains a value and a reference to the
next node in the sequence.
• In a singly linked list, traversal can only be done in
one direction, from the head (the first node) to the
tail (the last node).

www.ubids.edu.gh.com 90
Singly-linked list

A doubly-linked list is a type of linked list where


each node contains a value and two references: one
to the previous node and one to the next node in the
sequence. Unlike a singly linked list, a doubly
linked list allows traversal in both forward and
backward directions.
www.ubids.edu.gh.com 91
Doubly-linked list

www.ubids.edu.gh.com 92
Queue
• A queue is an abstract data type (ADT) that represents a
collection of elements with a specific order.

• It follows the principle of "First-In-First-Out" (FIFO),


meaning that the element that is inserted first will be the
first one to be removed.

• Think of a queue as a line of people waiting for a


service where the person who arrives first is served first.

www.ubids.edu.gh.com 93
Queue

www.ubids.edu.gh.com 94
Key characteristics of a queue
• Enqueue: Adding an element to the queue is called enqueue. The
new element is inserted at the end of the queue, becoming the last
element.

• Dequeue: Removing an element from the queue is called dequeue.


The element that has been in the queue the longest (i.e., the first
element) is removed.

• Front: The front of the queue refers to the element that will be
dequeued next. It represents the earliest added element in the
queue.

• Rear: The rear of the queue refers to the element that was most
recently added. It represents the last element in the queue.

www.ubids.edu.gh.com 95
Key characteristics of a queue contd.
• Empty Queue: If there are no elements in the
queue, it is considered empty, and attempting to
dequeue an element will result in an error or an
empty value.

• Queues have applications in various scenarios,


including task scheduling, resource allocation,
printing tasks, breadth-first search algorithms, and
more. They provide an ordered and predictable way
of managing elements based on their arrival order.

www.ubids.edu.gh.com 96
Stack
• A stack is an abstract data type (ADT) that represents
a collection of elements with a specific order.

• It follows the principle of "Last-In-First-Out" (LIFO),


meaning that the element that is inserted last will be
the first one to be removed.

• Think of a stack of books, where the last book placed


on top is the first one you can remove.
www.ubids.edu.gh.com 97
Stack

www.ubids.edu.gh.com 98
Characteristics of stacks
• Push: Adding an element to the stack is called push.
The new element is inserted on top of the stack,
becoming the most recently added element.

• Pop: Removing an element from the stack is called


pop. The element that was most recently added (i.e.,
the top element) is removed.

• Top: The top of the stack refers to the element that


will be popped next. It represents the most recently
added element in the stack.
www.ubids.edu.gh.com 99
Characteristics of Stacks
• Empty Stack: If there are no elements in the stack, it is
considered empty, and attempting to pop an element will
result in an error or an empty value.

• Stacks have applications in various scenarios, including


function call management (call stack), expression
evaluation (postfix evaluation), undo/redo functionality,
and more.

• They provide a structured way of managing elements based


on their order of addition and removal
www.ubids.edu.gh.com 100
Time complexity analysis
• Time complexity analysis is a method used to analyze
and evaluate the efficiency of an algorithm in terms of
the time it takes to run as the input size increases. It
provides a way to estimate how the running time of an
algorithm grows relative to the size of the input.

• The time complexity of an algorithm is typically


expressed using big O notation, which provides an upper
bound on the growth rate of the algorithm's running time.
It describes the worst-case scenario for the algorithm's
performance.
www.ubids.edu.gh.com 101
Cases or scenarios that are considered to evaluate
the performance of an algorithm.
(Types Algorithm Analysis)
• Best-case Time Scenario/Complexity: This represents the minimum possible
running time of an algorithm for a given input size. It assumes the input is in its
most favorable or best state, resulting in the most efficient execution of the
algorithm. The best-case time complexity provides an optimistic view of the
algorithm's performance.

• Worst-case Time Scenario/Complexity: This represents the maximum possible


running time of an algorithm for a given input size. It assumes the input is in its
most unfavorable or worst state, resulting in the least efficient execution of the
algorithm. The worst-case time complexity provides an upper bound on the
algorithm's performance and is often the most important case to consider.

• Average-case Time Scenario/Complexity: This represents the expected or


average running time of an algorithm for a given input size, considering all
possible inputs. It takes into account the distribution of inputs and their
probabilities. Average-case time complexity provides a more realistic estimation
of the algorithm's performance, assuming inputs are randomly distributed.
www.ubids.edu.gh.com 102
Time Complexity Analysis
• Time complexity notations, also known as asymptotic
notations, are used to describe the growth rate of an
algorithm's running time as the input size increases.
• In time complexity analysis, the focus is on the dominant
factors that contribute to the algorithm's running time as the
input size increases.

• These factors are usually expressed in terms of elementary


operations, such as comparisons, assignments, arithmetic
operations, and accessing elements in data structures.
www.ubids.edu.gh.com 103
How to analyse an Algorithm
• Major criteria
➢Time
➢Space

• Minor Criteria
➢Network Consumption
➢ Power
➢CPU registers

www.ubids.edu.gh.com 104
Common Natation of time Complexity
• Big O notation (O)
➢Big O notation represents the upper bound or worst-case
scenario of an algorithm's time complexity. It provides an
estimation of how the running time grows relative to the input
size. For example, if an algorithm has a time complexity of
O(n), it means the running time grows linearly with the input
size, or if it has a time complexity of O(n^2), it means the
running time grows quadratically with the input size.
•Omega notation (Ω)
➢Omega notation represents the lower bound or best-case
scenario of an algorithm's time complexity. It provides an
estimation of the minimum growth rate of the running time.
For example, if an algorithm has a time complexity of Ω(n), it
means the running time is at least linear, or if it has a time
complexity of Ω(n^2), it means the running time is at least
quadratic. www.ubids.edu.gh.com 105
•Theta notation (Θ)
➢Theta notation represents both the upper and
lower bounds of an algorithm's time complexity. It
provides a tight estimation of the growth rate. For
example, if an algorithm has a time complexity of
Θ(n), it means the running time grows linearly
with the input size, and it neither grows slower
nor faster than that

www.ubids.edu.gh.com 106
Time complexity with Big O
• O(1) - Constant Time: The running time is constant and does
not depend on the input size. Regardless of the input, the
algorithm takes a fixed amount of time to execute.

• O(log n) - Logarithmic Time: The running time grows


logarithmically with the input size. Algorithms with logarithmic
time complexity often divide the input in half at each step, such
as in binary search.

• O(n) - Linear Time: The running time grows linearly with the
input size. For an algorithm with linear time complexity, the
running time increases proportionally to the size of the input.

www.ubids.edu.gh.com 107
Time complexity notations
• O(n log n) - Linearithmic Time: The running time grows in a
combination of linear and logarithmic growth. This complexity often
arises in efficient sorting algorithms like merge sort or quicksort.

• O(n^2) - Quadratic Time: The running time grows quadratically with


the input size. Algorithms with quadratic time complexity often
involve nested loops, causing the running time to increase
significantly for larger inputs.

• O(2^n) - Exponential Time: The running time grows exponentially


with the input size. Algorithms with exponential time complexity are
highly inefficient and are often considered impractical for larger
inputs.

www.ubids.edu.gh.com 108
Time Complexity graph

www.ubids.edu.gh.com 109
Growth rates/Performance of Sort
Algorithms

www.ubids.edu.gh.com 110
Steps for Big-O Analysis
• Identify the input size: Determine what parameter(s) of the
algorithm determine the size of the input. For example, in an
algorithm that sorts an array, the input size is typically the length
of the array.

• Identify the basic operations: Identify the individual operations


that are executed repeatedly in the algorithm. Look for loops,
recursive calls, or other iterations that involve a significant
portion of the input.

• Count the number of operations: Determine the number of


times the identified basic operations are executed as a function
of the input size. This step may involve analyzing loops,
recursion, nested loops, and conditional statements.
www.ubids.edu.gh.com 111
Steps Contd.
• Simplify the expression: Express the count of operations as a
simplified mathematical expression, removing any constants or lower-
order terms. For example, if the count of operations is 5n^2 + 3n + 2,
simplify it to O(n^2) by discarding the constants and lower-order
terms.

• Determine the time complexity class: Based on the simplified


expression, determine the time complexity class using Big O notation.
The time complexity class indicates how the algorithm's running time
grows relative to the input size. Common time complexity classes
include O(1), O(log n), O(n), O(n log n), O(n^2), O(2^n), etc.

• Analyze the worst-case scenario: Consider the worst-case scenario


where the input size and the algorithm's behavior result in the
maximum number of operations. This helps to provide an upper
bound on the algorithm's running time

www.ubids.edu.gh.com 112
Example
•Constant Time Complexity (O(1))
int x = 5;
➢This statement assigns the value 5 to the variable x. It executes in constant
time because it performs a single operation, regardless of the input size.

•Linear Time Complexity (O(n))


for (int i = 0; i < n; i++) {
cout << i << endl;
}
➢This loop prints the numbers from 0 to n-1. The time it takes to execute the
loop grows linearly with the value of n, resulting in a linear time complexity.

www.ubids.edu.gh.com 113
Examples
•Quadratic Time Complexity (O(n^2))

for (int i = 0; i < n; i++) {


for (int j = 0; j < n; j++) {
cout << i << " " << j << endl;
}
}

➢This nested loop prints all combinations of i and j, where n is the input value.
Since there are two nested loops, the time complexity becomes quadratic,
resulting in O(n^2).

www.ubids.edu.gh.com 114
Example
• Logarithmic Time Complexity (O(log n))
int num = n;
while (num > 1) {
num = num / 2;
}

➢This loop repeatedly divides the variable num by 2 until it becomes


less than or equal to 1. The number of iterations required to reach this
condition is logarithmic to the initial value of n, resulting in a
logarithmic time complexity.

www.ubids.edu.gh.com 115
Example
• Exponential Time Complexity (O(2^n))

int Fibonacci(int n) {
if (n <= 1) {
return n;
} else {
return Fibonacci(n - 1) + Fibonacci(n - 2);
}
}
➢This recursive function calculates the nth Fibonacci number. The
number of recursive calls grows exponentially with the input value n,
resulting in an exponential time complexity.

www.ubids.edu.gh.com 116
Example of Time and Space complexity analysis
with Big-O
def sum_array(arr){
total = 0
for num in arr
total += num
return total
• Time Complexity: O(n)
• Space Complexity: O(1)

www.ubids.edu.gh.com 117
SORTING OF ARRAYS

www.ubids.edu.gh.com 118

You might also like