AD3251 - DS - Unit 1- ABSTRACT DATA TYPES
AD3251 - DS - Unit 1- ABSTRACT DATA TYPES
What is a Data?
1
Example:
1. Int: Represents integer values like 1, 2, 3.
2. Float: Used for floating-point numbers, which are numbers with a decimal point.
3. Char: Stands for character data, which can include any symbol, letter, or number.
4. String: A sequence of characters forming text data.
5. Boolean: Can only hold two values: true or false.
1. A data structure is a way to store and organize data efficiently in the memory.
2. Examples:
2
Data Structures are widely used in the given below areas:
1. Compiler Design
2. Operating System
3. Database Management Systems (DBMS)
4. Artificial Intelligence
5. Graphics
6. Simulation
7. Numerical Analysis Etc.
3
Data Structures are normally divided into two broad categories:
(1) Primitive Data Structures
(2) Non-Primitive Data Structures
4
Based on memory allocation, the Linear Data Structures are further classified into
two types:
1. Static Data Structures
2. Dynamic Data Structures
5
An abstract data type (ADT) is a logical and high-level description of a data
structure and its associated operations.
An ADT provides an implementation-independent view of a data type. Hence it is an
interface.
It specifies what operations can be performed on the data type, but not how those
operations are implemented.
ADT is a black box that hides the inner structure and design of the data structures.
Users (Application programs) interact with the ADT based on its defined operations
like insert(), remove().
Classes are the Python representation for Abstract Data Types in Object Oriented
Programming.
It is a pure interface, with no mention of an implementation—hence abstract.
ADTs are reusable software components
e.g., Stacks, Queues, Lists, Dictionaries, Trees, Graphs
9. For each ADT the programmer must be clear about:
The list of supported operations(i.e., interface)
Time and space complexity
10. ADT types:
Simple ADTs: Predefined Data types. Examples: int, float, double, char, bool
Complex ADTs: List, Set, Graph, Stack, Queue etc.
6
The Abstract data type model is a combination of abstraction and encapsulation.
Abstraction means hiding internal details and showing only functionality.
Combining the data and the member function in a single unit is considered
encapsulation.
1. ADT Data Structure - All data that is being processed is maintained in a data structure
and its implementation must not to be known to the user.
2. ADT operations - Data is inserted, deleted and updated using the Data structure inside
the memory by the application program via the interface.
7
Operations of Abstract Data Types (ADTs) on Non-Primitive Data
Structure:
1. An abstract data type is defined only by the operations that may be performed on it.
Abstract Data Defined by operations like:
Type
Abstract Array Adding elements
Sorting / Searching elements
Re-arranging the elements
Performing matrix operations
Abstract List Insertion / Deletion
Searching
Abstract Stack - Push - Inserts an item into the stack stk
last-in-first-out Pop - Returns a data item from stack stk
Data structure, Peek() - Returns top most element without removing it from
the stack
Size() - Returns no of elements currently in the stack
isEmpty() - Returns true if stack is empty, and false otherwise
Abstract Queue - enqueue to join the queue;
first-in-first-out dequeue, to remove the first element from the queue; and
Data structure front, in order to access and serve the first element in the
queue.
Abstract Tree Searching
Insertion, Deletion
Sort
8
Characteristics (Advantages )of Abstract Data Types (ADTs)
Encapsulation: ADTs provide a way to encapsulate data and operations into a single
unit, making it easier to manage and modify the data structure.
Data Abstraction: ADTs provide a level of abstraction from the implementation details
of the data. Users only need to know the operations that can be performed on the data,
not how those operations are implemented.
Data Structure Independence: ADTs can be implemented using different data
structures, which can make it easier to adapt to changing needs and requirements. For
example: To maintain a record of quantity of items sold in a sale, we can use a linear
list or an array to save space and dynamic memory allocation or a linked list so that
there is no missing item. We can use the data structures without knowing the
underlying internal working of the data structures.
Information Hiding: ADTs can protect the integrity of the data by allowing access
only to authorized users and operations. This helps prevent errors and misuse of the
data.
Modularity: ADTs can be combined with other ADTs to form more complex data
structures, which can increase flexibility and modularity in programming.
9
Procedure Oriented Languages Object Oriented Languages
1. Program is divided into small parts 1. Program is divided into parts called
called functions objects
2. Does not have access specifiers, by 2. Has access specifiers named – Public,
default, it is Public only. Eg: All Private, Protected etc
functions are Public
3. Does not have proper way hide data, 3. Provides data hiding, so it is secure
so it not secure
4. Overloading is not possible 4. Overloading is possible – function
overloading and operator overloading
5. Most functions use Global data for 5. Data cannot move easily from function
sharing that can be accessed freely to function, it can be kept Public or
from function to function in the Private so we can control the access of
system data
6. Examples: C, Visual Basic, Fortran, 6. Examples: C++, Java, Python,
Pascal C#.NET
Classes
In software development, a blueprint can refer to a high-level design that outlines
the structure, behavior, and functionality of a software system
A class is a user defined Data type that serves as a blueprint or template for
creating real-world objects.
10
It is the template that encapsulates both data members (attributes also called
as properties or instance variables) and member functions (methods also called
as behavior or member functions) shared by all objects of a particular type.
For example, a class for a car has attributes like color, model, and year, and
methods like start, accelerate, and brake.
Classes are like cookie cutters, allowing you to create multiple objects that share
the same structure and behavior.
In OOP methodology, the program code is organized in the form of classes.
When you define a Class, no memory is allocated.
Objects
Object is the real-world entity that needs to be represented in the software
application.
An object is an instance of a class
For software application development, the object could be either living entity like
a Student or physical object like Car or a business concept like Bank account
Objects are runtime entities created during program execution. Creation of
objects require memory allocation.
Each object consists of:
State: The state of an object is defined by its member variables
(attributes/properties/instance variables) and represent the data.
Behavior: The object behaviour is defined by its member methods/functions. It
represents the response of an object when another object interacts through method
calls.
Identity: Unique name given to an object and helps objects to interact with each
other by sending messages (also called methods or member functions)
For example:
11
Use of Classes in OOP:
Classes allow you to create user-defined data structures.
Classes serve as a template to define Object structure and Behavior.
We can create multiple objects with shared behaviors by specifying attributes and
methods within a Class
Classes in OOP help to design and create well-structured, modular, software systems
with modularity, reusability and code organization
Class Methods:
A method is a function that is defined within a class and describes the behavior of
an Object
Methods are messages sent by one Class object to another object, to perform a
certain action.
Methods are defined within a class using a specific syntax, and can take
parameters just like regular functions.
When an object’s method is called, the method operates on the data associated
with that object (called as state/properties) and can modify the object’s state.
For example:
12
Example of Class and Object definition
Class Object
1. A class is a logical entity 1. An object represents a physical entity
(conceptual) that serves as a (real) based on the class blueprint.
blueprint or template for creating
objects.
2. When you define a class, no memory 2. When you create an instance (an object)
is allocated. It is a design time entity based on that class that memory is
allocated. It is a run time entity
3. Class defines the variables (data 3. Objects allow you to access and use the
members) and the methods data members and methods defined in
(functions) that are common to all the class.
objects of a certain kind
4. Class is declared once 4. Object is created multiple times as per
the requirement
5. Class can exist without any objects 5. Objects cannot exist without a class
6. Example: 6. Example:
13
Advantages of OOP:
Supports large Software Projects
Better Data protection
Code Re-usability
Better representation of real-world entities
Better software maintenance
Enhanced security
Easy code modification
Python Classes
Python supports the object-oriented programming paradigm through classes.
14
class_name: It is the name of the class
Docstring: It is the first string inside the class and has a brief description of the class.
Although not mandatory, this is highly recommended.
statements: Attributes and methods
Here, we have created a class named ClassName.
Example: Define a class in Python
Syntax of a constructor
Where,
def: The keyword is used to define function.
init () Method:
It is a reserved method called as Constructor.
This method is automatically called after the Class object is created.
It helps to initialize the attributes (instance variables) of an object.
Parameters to init () method is optional
We can define the constructor: init () method with any number of
15
parameters.
self:
The first argument self refers to the current object.
It connects the instance(object) to the init () method.
By using self, we can access the attributes and methods of an object
16
Class Attributes
17
1. Instance variables:
The instance variables are attributes attached to an instance of a class.
We define instance variables inside the constructor ( the init () method
of a class).
Objects do not share instance attributes. Every object has its unique copy of
the instance attribute
2. Class Variables:
A class variable is a variable that is declared inside of class, but outside of
any instance method or init () method.
All instances of a class share the class variables.
Class variables have the same value for all instances of the class.
Way 2: Within the class, outside the instance method by using the dot notation:
instance_name.attribute_name.
Example:
Class Methods
In OOP, Inside a Class, we can define three types of methods:
18
1. Instance method:
Used to access or modify the object state.
If we use instance variables inside a method, such methods are called
instance methods.
It must have a ‘self’ parameter to refer to the current object.
2. Class method:
Used to access or modify the class state.
Inside the method, if we use only class variables, then such type of methods
are declared as a class method.
3. Static method:
Static methods are normally used to define utility methods inside a class.
They do not change the state of the class.
For example:
19
Example – Methods and Attributes of Student Class:
20
Create Multiple Objects of Python Class
We can also create multiple objects from a single class.
For example,
In the above example, we have created two objects employee1 and employee2
of the Employee class.
2. Protected - Protected members are accessible from within the same class and its
sub-classes. Python uses single underscore (_) prefix to make instance variable
protected
3. Private - Private members are denied access from outside the class. Python uses a
21
double underscore ( ) prefix to make an instance variable private.
Topic: Inheritance
1) Python Inheritance
The process of inheriting the properties of the parent class into a child class is
called inheritance.
The existing class is called a base class or parent class or super class
The new class is called a subclass or child class or derived class.
The main purpose of inheritance is the reusability of code because we can use the
existing class to create a new class instead of creating it from scratch.
In inheritance, the child class acquires all the data members, properties, and
functions from the parent class.
Also, a child class can also provide its own implementation (logic) to the
methods of the parent class.
22
2) Types Of Inheritance
Single inheritance
Multiple Inheritance
Multilevel inheritance
Hierarchical Inheritance
Hybrid Inheritance
1) Single Inheritance in Python: A single class inherits from only one Parent class. It
is the simplest and basic form of inheritance.
23
Example for Single Inheritance:
24
Example for Multilevel Inheritance:
3) Multiple Inheritance in Python: When one child class inherits two or more parent
classes, it is called Multiple Inheritance.
To achieve this we can provide multiple classes separated by commas.
25
Example of Multiple inheritance
26
5) Hybrid Inheritance in Python: Hybrid inheritance is a combination of different
types of inheritance.
27
6) Method Overloading in Python
The process of calling the same method with different parameters is known as
method overloading.
Python does not support method overloading unlike other OOPs languages such
as Java and C++.
Python considers only the latest defined method even if you overload the
method. In below example, no error because new method addition(a,b,c) with 3
parameters replaces addition(a,b) with 2 parameters which is overloaded with
new addition(a,b,c)
28
Python will raise a TypeError if you overload the method and try to call old
method.
29
1. Abstraction:
Examples:
1. In database management we use abstraction layers to interact with different databases.
2. Banking Applications: Using Abstraction, we can get the customer information without
worrying about the underlying data retrieval process.
Advantages:
1. Abstraction helps in reducing complexity, improving code maintainability, and
promoting code reusability.
2. By abstracting away the implementation details, we can create modular and loosely
coupled code, making it easier to modify, extend, and test.
2. Encapsulation:
30
Encapsulation refers to the binding of data (attributes or fields) along with the
methods (functions or procedures) that operate on that data into a single unit.
This unit is called a class in OOP.
By encapsulating data within a class, we can restrict direct access to the object’s
internal state. This is also known as information hiding
31
Advantages:
1. Encapsulation promotes modularity, reusability, and maintainability in software
development.
2. It allows us to manage complexity by organizing data and methods into classes.
3. Inheritance:
The capability of a class to derive properties and characteristics from another class is
called Inheritance.
Sub Class: The class that inherits properties from another class is called Sub class or
Derived Class or child class.
Super Class: The class whose properties are inherited by sub class is called Base Class
or Super class or Parent class.
Advantage: Reusability: Inheritance supports the concept of “reusability”, You can
define common functionality in a base class and extend it in subclasses by reusing the
fields(properties) and methods of the existing Base (Parent) class.
Refer previous Notes in earlier section for example and Types of Inheritance
Example:
32
4. Polymorphism:
Polymorphism in Python is the ability of an object to take many forms (Behavior).
In polymorphism, a method can process objects differently depending on the class
type or data type.
Polymorphism is used in:
1. Polymorphism with Built in functions
2. Polymorphism with Inheritance (via Method overriding)
1. Polymorphism with Built in functions : len() returns the count of characters if
object is string. If the object is a list, len() returns the count of items in the list.
33
In below example:
We create three classes - Vehicle (Parent class), Car (Child class) and Truck (Child
class).
The class Truck extends from the class Vehicle so, all properties of the parent class
are available in the child class.
In addition to that, the child class redefined (modified) the method max_speed()
and attribute gears
But the class Car which inherits from the class Vehicle accesses the method and
attributes of Vehicle class without any modification using super()
34
35
Topic: Namespaces
What is namespace?
Python namespaces are containers to map names to objects.
The name can be variables, functions, classes, or any Python object.
Python namespace is like a Python Dictionary of key-value pairs where the
keys are the names, and the values are the associated objects.
Each namespace is a unique space for the object identifier and multiple
namespaces can exist at the same time.
Example:
Example:
The three objects - an integer object, a string object, and a function are stored as
{‘x’: 100, ‘author’: ‘Chetan Ambi’, ‘myfunc’: } in the namespace along with
other objects.
Types of namespace?
The access to the names and objects in the namespaces is determined by the
scope you are currently in.
There are four types of namespaces:
36
1. Built-In
2. Global
3. Local/ function
4. Enclosing
4. Enclosing Namespace:
Enclosing namespaces occur when a function contains other functions (nested
functions.
37
When an inner function uses a variable name, Python first looks in its local
namespace and then in the enclosing namespace.
38
‘manufacturer’ . The class-level variable can be accessed using the class
name: ‘Car.manufacturer’.
2. Instance-level Namespaces:
Instance-level namespaces are created when an object is instantiated from a
class.
They contain instance-specific variables and methods that are unique to each
object.
Example: consider a class named ‘Car’ an instance-level variable ‘color’. The
instance-level variable is accessed using the object name: ‘car1.color’.
In above example, the memory address of the variables num1 and num2 are the
same.
Hence no new object is created by = operator, Only the memory reference of
num 1 is copied to the variable num2
So, if you want to modify any values in new_list or old_list, the change is
visible in both.
39
Using Python Shallow Copy:
The copy() function of the Copy module can be used to make a shallow copy in
Python.
When shallow copying flat lists (think 1-dimensional lists) using the copy()
function, the actual values are copied instead of memory locations.
In above example, List1 and List2 values are stored in different memory
locations.
List 2 value at index 1 modified as 500, is not copied in List1 since for flat
lists, the actual values are copied to the new variable instead of memory
locations
For Lists having nested lists, only their memory locations are copied.
40
In above example, the memory locations of List1 are copied into List2.
Hence, when List2 is changed at index position [0][0] as 500, List 1 is also
changed.
Thus, Shallow Copy is only one level deep, the copy process does not recurse
or create copies of nested objects.
41
A shallow copy does not create new copies of objects for Nested lists and other
Nested objects.
Hence Deep copy is used to copy nested items to brand new memory locations.
To recursively copy the values of all the top level and nested items in a Python
object, like a list, you can use the deepcopy() function of the Copy Module.
Example:
42
Also, the memory locations of the two Lists are different
This is because all the items are recursively copied from List 1 to List 2
instead of their memory locations using deepcopy() function, so after that
any change in List1 will not affect List 2
Algorithms:
Algorithm is the step-by-step unambiguous instructions of how a computer should
solve problems in finite amount of time.
It is considered as a tool that helps to solve a specific computational problem.
Complexity of Algorithms:
43
Generally - Big-O notation is used to express the complexity of an algorithm.
O – represents the complexity (orders)
n - represents the size of the input data set
Examples:
O(n) – “order n”, Linear complexity
O(n2) – “order n squared”, Quadratic complexity
3. Performance Vs Complexity:
Performance: How much time/memory/disk/etc. is used when a program is run. This
depends on the machine, compiler, etc. as well as the code we write.
Complexity: How do the resource requirements of a program or algorithm scale, i.e.
what happens as the size of the problem being solved by the code gets larger.
44
7. Moving Beyond Experimental Analysis:
Our goal is to develop an approach to analyzing the efficiency of algorithms that:
1. Allows us to evaluate the relative efficiency of any two algorithms independent
of the hardware and software environment.
2. Considers all possible inputs.
3. Is performed by studying a high-level description of the algorithm without need
for implementation.
45
Types of Asymptotic Notations:
1. BIG 0 notation (Big Oh)
2. BIG Ω notation (Big Omega)
3. BIG θ notation (Big Theta)
Mathematical Definition:
For any value of n, the running time of an algorithm does not cross the time
provided by O(g(n)).
46
Some general Examples for Big O notation:
The first two functions are linear and hence have a lower order of growth than g(n)
= n2, while the last one is quadratic and hence has the same order of growth as n2.
Example 1:
By Big O notation,
100(1) + 5 ≤ 105*12
100 + 5 ≤ 105
105 ≤ 105
47
2. BIG Omega Ω NOTATION – Ω (big Omega)
2. This notation provides the Best-case time complexity – the best or minimum
amount of time, an algorithm may need to solve a problem.
Mathematical Definition:
For any value of n, the minimum time required by the algorithm is given by Omega
Ω(g(n)).
48
Example 1:
By Big Ω notation,
(23 ) ≥ 1* 22
8 ≥ 1* 4
8≥4
Therefore, n3 ∈ Ω(n2 )
49
3. BIG Theta θ NOTATION – θ (big Theta)
1. It is used to express both the lower bound and the upper bound of an algorithm's
running time.
2. It says that two functions grow at the same rate, up to some constant factors
3. The average running time between best and worst is represented by the theta
notation.
Mathematical Definition:
A function t (n) is said to be in θ(g(n)), denoted t (n) ∈ θ(g(n)), if t (n) is bounded both
above and below by constant factors of g(n), if there exist some positive constants c1
and c2, c1>0 & c2>0 and some non-negative integer n0 such that
If a function f(n) lies anywhere in between c1g(n) and c2g(n) for all n ≥ n0, then f(n) is
said to be asymptotically tight bound.
50
Example 1:
By Big θ notation,
Hence, the complexity of t(n) = 1/2 n(n − 1) can be represented as θ (g (n) ) , i.e. θ
(n2).
Therefore, 1/2 n(n − 1) ∈ θ (n2)
51
Easy to perform and needs only basic mathematical skills
Disadvantages:
Asymptotic analysis does not provide an accurate running time or space usage
of an algorithm.
Two algorithms with the same asymptotic complexity may have different actual
running times or space usage and Asymptotic analysis may not differentiate this
difference.
It is not straightforward to always find the Best case Asymptotic Time
complexity for an algorithm since there may be trade-offs between Time and
Space complexity.
For example, for varying input size n, the order of growth is given in below table:
52
From the table, it is observed:
Topic: Recursion
What is Recursion?
The process in which a function calls itself directly or indirectly is called recursion and
the corresponding function is called a recursive function.
A recursive function solves a particular problem by calling a copy of itself and solving
smaller subproblems of the original problems.
Many more recursive calls can be generated as and when required
53
Topic: Analyzing Recursive algorithms
What is Recursion?
The process in which a function calls itself directly or indirectly is called recursion and the
corresponding function is called a recursive function.
A recursive function solves a particular problem by calling a copy of itself and solving
smaller subproblems of the original problems.
Many more recursive calls can be generated as and when required
Examples:
We know,
n!= 1 .......... (n − 1) . n = (n − 1)! . n for n ≥ 1
and 0!= 1
Hence Factorial Formula is:
F(n) = F(n − 1) . n for n > 0,
54
Algorithm analysis:
Step 1: Input data size parameter = n (Given non-negative integer)
Step 2: Algorithm’s Basic operation is Multiplication
Step 3: Number of times of executing Basic operation
Initial condition refers to the Base Case: Termination condition for the recursive
function
Recurrence Equation:
55
Thus, in Factorial Function problem, the product of n consecutive integers requires the same
number of multiplications, and it does so without the overhead of time and space used for
maintaining the recursion’s stack.
56
57
Algorithm analysis:
Step 1: Input data size parameter = n (Given number of Disks)
Step 2: Algorithm’s Basic operation is the move (movement) of disk
Step 3: Number of times of executing Basic operation
The number of moves M(n) depends on n:
58
Thus, we have an exponential algorithm for Tower of Hanoi Puzzle, which will run
for long time even for moderate values of n
By counting the number of nodes in the Recursive calls tree above, we can get the
total number of calls made by the Tower of Hanoi algorithm
l – is the level in the Recursive Tree
n – is the node
59
3. Example 3: Number of Digits in Binary representation of a positive
decimal number
Algorithm analysis:
Step 1: Input data size parameter = n (A positive decimal integer )
Step 2: Algorithm’s Basic operation is the addition operation
Step 3: Number of times of executing Basic operation
The number of addition operation depends on n:
Recurrence equation:
Hence,
60
4. Example 4: Time complexity of Recursive Fibonacci Series
Algorithm analysis:
Step 1: Input data size parameter = n (A positive integer for Fibonacci number )
Step 2: Algorithm’s Basic operation is the addition operation
Step 3: Number of times of executing Basic operation
The number of addition operation depends on n:
61
Hence,
62