Professional Documents
Culture Documents
Screenshot 2024-04-16 at 8.52.48 AM
Screenshot 2024-04-16 at 8.52.48 AM
Ahmad Maccido
BSc, MSc, PhD(in view)
2
What is data structure?
• A particular way of storing and organizing data in a
computer so that it can be used efficiently and effectively.
• Data structure is the logical or mathematical model of a
particular organization of data.
• A group of data elements grouped together under one
name.
• For example, an array of integers
Data Types & Data Structures
• Applications/programs read data, store data temporarily,
process it and finally output results.
• What is data? Numbers, Characters, etc.
4
Data Types & Data Structures
• Data is classified into data types. e.g. char, float, int, etc.
• A data type is (i) a domain of allowed values and (ii) a set of operations
on these values.
• Compiler signals an error if wrong operation is performed on data of a
certain type. For example, char x,y,z; z = x*y is not allowed.
5
Data Types & Data Structures
• Examples
6
Types of Data Structures
7
Types of Data Structures
Arra
y
Linked List
Queue Stac
Tree
k
There are many, but we named a few. We’ll learn these
data structures in great detail!
Non-Primitive Data Structure
9
Static 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.
An example of this data structure is an array.
10
Basic Terms of An Array Data Structure
In arrays, an element refers to a particular item that is stored.
Each element carries an index - a location with respect to a
base value.
The base value is the memory location of the first element of
the array.
We simply add offsets to this value which makes it easier for
us to use the reference and identify items.
11
Here are a few important properties of an array:
•Each entry in an array has the same data type and size,
which is 4 bytes.
12
Why do we need arrays?
• It is simpler to sort and search for a value in an array
• Arrays are ideal for processing many values with ease
• Arrays are useful for storing a variety of values in a single variable. Most
applications in computer programming necessitate keeping a significant
amount of data of a similar type.
• To hold this much data, we must define a large number of variables. While
writing the programs, it would be quite tough to remember the names of all
the variables. Instead of naming each variable a different name, it’s simpler
to build an array and store all of the elements within it.
• Applications of Array
• We’ve already discussed everything about arrays in our previous article.
Here we’ll try to understand the applications of arrays in the programming
world using proper examples and images. Let's get started:
13
Pointers
• A pointer is a variable which stores the address of another variable.
• There are two main operations when working with pointers in C++:
1. The Address Operator => &
2. The Value Operator => *
14
LINKED LISTS
• Linked list is one of the fundamental data structures
• It can be used to implement other data structures.
• It consists of a sequence of nodes, each containing arbitrary
data fields and one or two links pointing to the next and/or
previous nodes.
• The principal benefit of a linked list over a conventional array
• It allows items to be traversed in a different order.
• Single node of the linked list can have data of multiple data
types,
15
NODE INSERTION:
16
NODE INSERTION:
17
NODE INSERTION:
• Consider a linked list made up of several nodes. If it is required
to insert a new node after a specific node in the linked list, that
specific node should be first searched in the linked list.
Following is a method to add a new node after a specific node
in the linked list:
• Initialize a variable which stores the data of the node to be
searched.
• Traverse the linked list (p = p->next inside a loop) from start to
NULL and compare data of every node with the data to be
searched (using an if condition).
• When that specific node is found, use references (pointers) to
help insert the new node
• Initialize data to variables of the new node.
• Check if the link is connected to all the nodes (including the
new node)
18
Stack ADT
• stack: a list with the restriction that insertions/deletions can
only be performed at the top/end of the list
• Last-In, First-Out ("LIFO")
• The elements are stored in order of insertion,
but we do not think of them as having indexes.
• The client can only add/remove/examine
the last element added (the "top").
19
Applications of Stacks
• Programming languages:
• method calls are placed onto a stack (call=push, return=pop)
return var
method3 local vars
parameters
return var
method2 local vars
parameters
• Matching up related pairs of things: return var
method1 local vars
• find out whether a string is a palindrome parameters
• Sophisticated algorithms:
• searching through a maze with "backtracking"
• many programs use an "undo stack" of previous operations
20
Class Stack
Stack<E>() constructs a new stack with elements of type E
push(value places given value on top of stack
)
pop() removes top value from stack and returns it;
throws EmptyStackException if stack is empty
peek() returns top value from stack without removing it;
throws EmptyStackException if stack is empty
size() returns number of elements in stack
isEmpty() returns
Stack<Integer> s = newif Stack<Integer>();
true stack has no elements
s.push(42);
s.push(-3);
s.push(17); // bottom [42, -3, 17] top
System.out.println(s.pop()); // 17
21
Labs: Primitive data type
• #include <iostream>
• #include <cstdio>
• #include <string>
• using namespace std;
• int main()
• {
• float a=34.9;
• string b="HELLO";
• float c=35.9;
• double d =12323.34;
• string msg ="HELLO ALL" ;
• cout << msg << endl;
• cout << b << endl ;
• cout<< c << endl;
• cout << a << endl;
• cout << d << endl;
• }
What is Pseudo-code?
● if condition then
true-actions
[else
false-actions]
● We use indentation to indicate what actions should be included in the true-
actions and false-actions
● For example
Input range
for num←0; num<=range; num←num+1 do
if num % 2 = 0 then
print num is even
else
print num is odd
endif
endfor
Algorithm Design: Practice
• Example 1: Determining even/odd number
• A number divisible by 2 is considered an even number, while
a number which is not divisible by 2 is considered an odd
number. Write pseudo-code to display first N odd/even
numbers.
1. Implementation Method
2. Design Method
3. Design Approaches
4. Other aspect
Why Algorithm Classification?
Divide and Conquer: This involves dividing the problem into sub-problem, recursively solving them, and then recombining them for the final answer.
Dynamic Programming: The approach of Dynamic programming is similar to divide and conquer. The difference is that whenever we have recursive
function calls with the same result, instead of calling them again we try to store the result in a data structure in the form of a table and retrieve the results
from the table. Thus, the overall time complexity is reduced. “Dynamic” means we dynamically decide, whether to call a function or retrieve values
from the table.
Linear Programming: In Linear Programming, there are inequalities in terms of inputs and maximizing or minimizing some linear functions of inputs.
Reduction(Transform and Conquer): This solve a difficult problem by transforming it into a known problem for which we have an optimal solution.
Basically, the goal is to find a reducing algorithm whose complexity is not dominated by the resulting reduced algorithms.
Backtracking: This technique is very useful in solving combinatorial problems that have a single unique solution. Where we have to find the correct
combination of steps that lead to fulfillment of the task. Such problems have multiple stages and there are multiple options at each stage. This approach
is based on exploring each available option at every stage one-by-one. While exploring an option if a point is reached that doesn’t seem to lead to the
solution, the program control backtracks one step, and starts exploring the next option. In this way, the program explores all possible course of actions
and finds the route that leads to the solution.
Branch and Bound: This technique is very useful in solving combinatorial optimization problem that have multiple solutions and we are interested in find
the most optimum solution. In this approach, the entire solution space is represented in the form of a state space tree. As the program progresses each
state combination is explored, and the previous solution is replaced by new one if it is not the optimal than the current solution.
Classification by Design Approaches
• Top-Down Approach: In the top-down approach, a large problem is divided into small sub-
problem. and keep repeating the process of decomposing problems until the complex problem
is solved.
• Bottom-up approach: The bottom-up approach is also known as the reverse of top-down
approaches.
In approach different, part of a complex program is solved using a programming language and
then this is combined into a complete program.
Classification by other aspect
Apart from classifying the algorithms into the above broad categories, the algorithm can be
classified into other broad categories like:
• Randomized Algorithms: Algorithms that make random choices for faster solutions are
known as randomized algorithms.
Example: Randomized Quicksort Algorithm.
• Classification by complexity: Algorithms that are classified on the basis of time taken to get a
solution to any problem for input size. This analysis is known as time complexity analysis.
Example: Some algorithms take O(n), while some take exponential time.
• Classification by Research Area: In CS each field has its own problems and needs efficient
algorithms.
Example: Sorting Algorithm, Searching Algorithm, Machine Learning etc.
• Branch and Bound Enumeration and Backtracking: These are mostly used in Artificial
Intelligence.
Analysis of Algorithms
Algorithm analysis provides theoretical estimation for the required
resources of an algorithm to solve a specific computational problem.
It is the determination of the amount of time and space resources required
to execute it.
Efficiency or running time of an algorithm is related to input length,
number of steps, these known as time complexity, and a volume of
memory known as space complexity.
In a not shell, analysis of algorithm can be of these forms:
1. Algorithms and Complexities
2. Asymptotic analysis
3. Asymptotic notations
4. Amortized analysis
5. Space Complexity
6. Pseudo Polynomial Type
Algorithms and Complexities
The complexity of an algorithm computes the amount of time and
spaces required by an algorithm for an input of size (n).
The complexity of an algorithm can be divided into two types. The time
complexity and the space complexity.
1. Time Complexity of an Algorithm: This is defined as the process
of determining a formula for total time required towards the execution
of that algorithm.
This calculation is totally independent of implementation and
programming language.
2. Space Complexity of an Algorithm: Space complexity is defining
as the process of defining a formula for prediction of how much
memory space is required for the successful execution of the
algorithm.
The memory space is generally considered as the primary memory.
Asymptotic Analysis
Asymptotic analysis, determine the performance of the algorithm based on the input size. it usually find the relation between the running time and
the input size.
For the space complexity, the goal is to get how much space in the main memory is occupied to complete the algorithm.
Asymptotic Behavior
For a function f(n) the asymptotic behavior is the growth of f(n) as n gets large.
Our task is to find how much time it will take for a large value of the input.
For example,
f(n) = c * n + k as linear time complexity.
f(n) = c *(n*n) + k is quadratic time complexity.
Ideally, the analysis of algorithms can be divided into three different cases. Viz:
Best Case − Here the lower bound of the running time is calculated. It describes the behavior of an algorithm under optimal conditions.
Average Case − In this case, we calculate the region between the upper and lower bound of the running time of algorithms.
In this case, the number of executed operations are not minimum and not maximum.
Worst Case − In this case we calculate the upper bound of the running time of algorithms. In this case, a maximum number of operations are
executed.
Asymptotic Notations
Asymptotic notations are used to represent the complexities of algorithms for asymptotic analysis.
These notations are mathematical tools to represent the complexities.
There are three notations that are commonly used.
Big Oh Notation
• Big-Oh (O) notation g
We write f(n) = O(g(n)), If there are positive constantsn0 and c such that, to the right of n0 the f(n)
always lies on or below c*g(n).
• O(g(n)) = { f(n) : There exist positive constant c and n0 such that 0 ≤ f(n) ≤ c g(n), for all n ≥
n0}
Asymptotic Notations
Big Omega Notation
Big-Omega (Ω) notation gives a lower bound for a function f(n) to within a constant factor.
We write f(n) = Ω(g(n)), If there are positive constantsn0 and c such that, to the right of n0 the f(n)
always lies on or above c*g(n).
Ω(g(n)) = { f(n) : There exist positive constant c and n0 such that 0 ≤ c g(n) ≤ f(n), for all n ≥ n0}
Asymptotic Notations
Big Theta Notation
Big-Theta(Θ) notation gives bound for a function f(n) to within a constant factor.
We write f(n) = Θ(g(n)), If there are positive constantsn0 and c1 and c2 such that, to the right of n0
the f(n) always lies between c1*g(n) and c2*g(n) inclusive.
Θ(g(n)) = {f(n) : There exist positive constant c1, c2 and n0 such that 0 ≤ c1 g(n) ≤ f(n) ≤ c2 g(n),
for all n ≥ n0}