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

AD3251 - DS - Unit 1- ABSTRACT DATA TYPES

The document provides an overview of Abstract Data Types (ADTs), data types, and data structures, explaining their definitions, differences, and classifications. It discusses the importance of data structures in various fields and highlights the advantages of using ADTs, such as encapsulation and data abstraction. Additionally, it covers the role of classes in Object-Oriented Programming (OOP) and how they facilitate the creation of user-defined data structures.

Uploaded by

zabuzarkhan00
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
132 views

AD3251 - DS - Unit 1- ABSTRACT DATA TYPES

The document provides an overview of Abstract Data Types (ADTs), data types, and data structures, explaining their definitions, differences, and classifications. It discusses the importance of data structures in various fields and highlights the advantages of using ADTs, such as encapsulation and data abstraction. Additionally, it covers the role of classes in Object-Oriented Programming (OOP) and how they facilitate the creation of user-defined data structures.

Uploaded by

zabuzarkhan00
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 62

UNIT I ABSTRACT DATA TYPES

Topic: Abstract Data Types (ADTs)

What is a Data?

Data is a collection of information gathered by observations, measurements, research


or analysis.
They may consist of facts, numbers, names, figures or even description of things.
Data is organized in the form of graphs, charts or tables
In a computer's storage, data is stored in the form of a series of binary digits (bits)
that contain the value 1 or 0.
Data can be Sound, Video, Single character, Number (integer or floating-point),
Picture, Boolean (true or false), Text (string)

Representation of Data items:

A data item is a piece of information or a record.


For example, Employee, ID, Name, Gender, Street, Middle etc are all Data items
The value each Data item holds is Data

What is a Data Type?

In programming, a data type is a classification or grouping of data values


Data type informs the compiler about the kind of data, a particular variable will hold
and how much memory space it requires

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.

What is a Data Structure?

1. A data structure is a way to store and organize data efficiently in the memory.

2. Examples:

 Array: A collection of elements identified by index or key


 Linked List: A sequence of nodes where each node contains data and a reference
to the next node in the sequence.
 Stack: A collection of elements that supports last-in, first-out (LIFO) semantics
for inserts and deletes.
 Queue: A collection of elements that supports first-in, first-out (FIFO) semantics
for inserts and deletes.
 Tree: A hierarchical structure consisting of nodes with a parent-child relationship.
 Graph: A collection of nodes connected by edges.

How Data Structure varies from Data Type?

Data Type Data Structure


1. Data type informs the compiler about 1. Data structure is a way to store and
the kind of data, a particular variable organize data efficiently in memory
will hold and how much memory
space it requires
2. Values can be assigned to Data type 2. Data is assigned to the Data structure
variables. object using operations like push(),
insert(), remove() etc
3. Data type is abstract implementation. 3. Data structure is a concrete
implementation.
4. There is no time complexity in the 4. In data structure objects, time
case of data types. complexity plays an important role.
5. Examples: int, float, double, 5. Examples: stack, queue, tree, etc.

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.

Why data structure (Advantages)?


1. Data structures allow us to store, organize, and manipulate data effectively.
2. Data structures and algorithms are essential for solving real-world problems.
3. They help us perform operations like insertion, deletion, and retrieval efficiently.
4. SQL queries, Linux commands, and other software depend on algorithms and data
structures.

Classification of Data Structures (Types):

3
Data Structures are normally divided into two broad categories:
(1) Primitive Data Structures
(2) Non-Primitive Data Structures

(1). Primitive Data Structure:


1. Primitive Data Structures are the data structures consisting of the numbers and the
characters that come in-built into programs.
2. These data structures can be operated directly by machine-level instructions.
3. Basic data types like Integer, Float, Character, and Boolean come under the
Primitive Data Structures.
4. These data types are also called Simple data types, as they contain characters that
can't be divided further.

(2). Non - Primitive Data Structure:


1) Non-Primitive Data Structures are those data structures derived from Primitive Data
Structures.
2) These data structures can't be operated directly by machine-level instructions.
3) Non-Primitive data structures can store and organize data elements that is either
homogeneous (same data type) or heterogeneous (different data types).
4) Based on the structure and arrangement of data, we can divide Non-Primitive Data
Structures into:

I. Linear Data Structures


II. Non - Linear Data Structures

Linear Data Structure:


 The data is arranged in single level linearly (sequential) in the Data structure, where
each element is attached to its previous and next adjacent elements.
 But in memory, the arrangement may not be sequential
 The data elements are visited sequentially where only a single element can be
directly reached.
 Examples: Array, List, Stack and Queue

4
 Based on memory allocation, the Linear Data Structures are further classified into
two types:
1. Static Data Structures
2. Dynamic Data Structures

1. Static Data Structure:


 These data structures have fixed size.
 The memory for these data structures is allocated at the compiler time, and their
size cannot be changed by the user during program execution at Run time
 But the data stored in Static data structure can be altered.
 Example: Array – has fixed size and its data can be modified later.

2. Dynamic Data Structure:


 These data structures have dynamic size.
 The memory for these data structures is allocated at the Run time.
 Both the data structure size and the elements stored in Dynamic data structure can
be changed during program execution.
 Examples: Lists, Stacks, and Queues.

Non - Linear Data Structure:


 The data elements are not arranged in sequential order.
 Here, the traversal of data elements and insertion or deletion are not done
sequentially.
 There exists a hierarchical relationship between the individual data items.
 Examples: Tree and Graph

Abstract Data Types (ADTs)

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.

Abstract Data Types (ADTs Model)


There is an interface between Application Program and the Abstract Data Type.
ADT consists of the data structures and the functions(private and public) which are
interconnected with each other.
Since they are completely present within the ADT, they are out of the scope of the
Application Program.

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.

Operations of Abstract Data Types (ADTs) on Primitive Data Structure:

1. Creation: This operation creates a Data structure


2. Display: This operation displays all the elements of the Data structure
3. Insertion: This operation is used to insert any desired element at any desired
position
4. Deletion / Destroy: This operation is used to delete any desired element from the
data structure. This helps in efficient use of memory
5. Modification / Update: This operation is used to modify the desired element’s
value by any desired new value.
6. Selection: This operation is used to access data within a data structure. The
significance of selection operation is provided in file data structure.

7
Operations of Abstract Data Types (ADTs) on Non-Primitive Data
Structure:

 The operations on non-primitive data structure depend on the logical organization of


data and their storage structure.
 Non-primitive data focuses on formation of a set of data elements that are either
homogeneous (same data type) or heterogeneous (different data type).
1. Traversing: Traversing is generally done to check the availability of data elements
in in a Data structure after insertion/deletion.
2. Sorting: Sorting is the technique of arranging the data elements in some logical
order, either ascending or descending order.
3. Merging: Merging is the method of combining the elements in two different sorted
lists into a single sorted list.
4. Searching: Searching is the method of finding the location of an element with a
given key value, or finding the location of an element which satisfies a given
condition.
5. Insertion: Insertion is the method of adding a new element to the data structure.
6. Deletion: Deletion refers to removing an item from the structure.

How do you define Abstract Data Types (ADTs)

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.

Topic: Abstract Data Types (ADTs) and Classes


 Most programming languages use the concept of classes to define and implement an
Abstract Data Type.
 They use the word “class” to define the scope (the body) where the variables will be
declared.

Topic: Introduction to OOP


 Object-Oriented Programming (OOP) paradigm is used to design real-world
entities and their interactions as software objects.
 Python programming language supports different programming approaches like
functional programming, modular programming.
 One of the popular approaches is object-oriented programming (OOP) to solve a
programming problem is by creating objects
 The object contains:
o Data: as properties(attributes)
o Code: as methods (actions which Objects can perform)
 Developed to overcome the limitations of Procedural languages like C language.
 Examples of OOP languages are JavaScript, C++, Java, and Python
 We define the real-world objects in terms of its properties and behavior.

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

Building Blocks / Components of Object-Oriented Programming:

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 Attributes / Properties (State):


 Attributes define the data associated with an object and represents the “state” of the
object at any given point in time.
 Attributes can be simple values, such as strings or numbers, or they can be more
complex data structures, such as arrays or objects.
 Each class may have none, one, or multiple attributes
 Attributes are defined within a class.
 Attributes can be thought of as containers that hold data associated with an object.
 For example:

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

Differences between Classes and Objects on OOP

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:

Class MobilePhone Class MobilePhone


Attributes/ model_name, Attribute/ model_name
Properties/ RAM State/ =’A270’,
State Properties - RAM=’2GB’
Operations/ texting() Values
Methods/ calling() Methods texting()
Behavior calling()

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

Topic: Classes in Python


An object is simply a collection of data (variables) and methods (functions). Similarly, a
class is a blueprint for that object.

Python Classes
Python supports the object-oriented programming paradigm through classes.

Define Python Class


We use the class keyword to create a class in Python. For example,

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

Creating Objects From a Class in Python – Objects in Python


 When we create an object of the class, it is called instantiation.
 The object is also called the instance of a class
 A constructor is a special method used to create and initialize an object of a class.
This method is defined in the class.
 In Python, Object creation is divided into two parts as:
 Object Creation: Internally, the new is the method that creates the object
 Object initialization: Using the init () method we can implement
constructor to initialize the object.

 Syntax to create an object:

 Example code to create the object of a Student class:

 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

 Complete example code:

16
Class Attributes

When we design a class, we use instance variables and class variables


In Class, attributes can be defined into two parts:
Instance Variables
Class Variables

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.

Accessing instance variables:


 Way 1: Within the class in instance method by using the object reference (self)
Example:

 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.

Public vs Non-Public Members

 In Python, we have three levels of access control for class members:


1. Public - Public members (usually methods declared in a class) are accessible from
outside the class. Default is Public

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.

 Syntax of Inheritance in Python

 Here, we are inheriting the sub_class from the super_class.


 In child class, we can call and access the parent class attributes and methods by
using the super() function
 super() function returns a proxy/temporary object of the parent class using which
we can call a parent class method inside a child class method.
 The super() function support code reusability
 Python built-in function issubclass() helps us to verify whether a particular class is
a subclass of another class. This function returns True if the given class is the
subclass of the specified class. Otherwise, it returns False
 Example for Inheritance: In below example, super() in Car sub class is used to
access super class Vehicle’s attribute – wheels and method – Vehicle_info()

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:

2) Multilevel Inheritance in Python: In multilevel inheritance, a class inherits from a


child class or derived class.
Suppose three classes A, B, C. A is the superclass, B is the child class of A, C is the
child class of B.
In other words, we can say a chain of classes is called multilevel 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.

Multiple Inheritance is allowed in Python but not allowed in Java

25
Example of Multiple inheritance

4) Hierarchical Inheritance in Python: When multiple classes inherit the same


Parent class, it is called Hierarchical Inheritance.

Example for Hierarchical Inheritance:

26
5) Hybrid Inheritance in Python: Hybrid inheritance is a combination of different
types of inheritance.

Example for Hybrid 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.

Features Of Object-Oriented Programming:

29
1. Abstraction:

 Abstraction refers to the practice of hiding implementation details of the software


system from the user
 It provides a simplified view of a complex system to its users by exposing only the
necessary features and behaviors, and hides its complexity.
 In the context of OOP, abstraction is achieved through the use of abstract classes and
interfaces.
 Through Abstraction, we can hide the properties and methods of the Class objects from
the outer world using access modifiers like Private and Protected.

 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.

2. Polymorphism with Inheritance (via Method Overriding)


 Polymorphism is used in Inheritance.
 Using method overriding, polymorphism allows us to define methods in the child
class that have the same name as the methods in the parent class.
 This process of re-implementing the inherited method in the child class is known
as Method Overriding.
 Method overriding is useful when a parent class has multiple child classes, and one
of that child class wants to redefine the method with its own new implementation
logic.
 The other child classes can use the parent class method without any modification.
Due to this, we don’t need to modification the parent class code

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

1. The Built-In Namespace:


 The Built-in namespace contains all the standard objects.
 These objects are available at all times during program execution and do not need
import statements
 It includes the Built in functions like print(), max(), len(), then Built in errors and
exceptions like 'ArithmeticError', TypeError and also Data types like int and
str
 To explore the objects in Built in namespaces, use the command:

2. The Global Namespace:


 The global namespace contains names defined at the top level of the main
program/module (a single .py file)
 They are available throughout the entire program/module.
 Global namespace includes all the variable names, functions, classes and objects,
etc. defined in a Python module (.py file).
 Also, the interpreter creates a global namespace for any module that Python
program loads with the import statement

3. The Local/Function Namespace:


 Inside a function, any names you define (like function parameters or local
variables) belong to the local namespace.
 This namespace is available only inside the function.

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.

3. Python Variable Scope Resolution Rules (LEGB)


 Python variables are searched in the following order of namespaces.

 If a name is not found in the namespace hierarchy, NameError is raised.

4. Namespaces and Object-Oriented Programming - Python

 Namespaces help organize and access class-level and instance-level variables


and methods.
1. Class-level Namespaces:
 In OOP, classes have namespaces containing class-level variables and methods.
 These variables and methods are accessible without creating an instance
(object) of the class.
 Example: Consider a class named ‘Car’ with a class-level variable

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’.

Topic: Shallow and Deep copying

Three ways of copying Mutable objects


Using an assignment operator
Shallow copying an object
Deep copying an object

Using an assignment operator:


The assignment operator simply copies the memory reference of an object into
the new object instead of making new copies of the values stored by a variable.
Example:

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.

3. Using Python Deep Copy:

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:

 In the above Example, we use deepcopy() function creates new copies of


both Flat item like 10, 20 of List 1 and also nested items like [1,2,3], [4,5,6]
of List1 in List 2
 This means, both the old_list and the new_list are independent.
 When List2 is changed at index 0 as 100 and index[2][0] as 500, only List 1
is modified and not List 2

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

Topic: Introduction to analysis of algorithms

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.

4. Design and Analysis of Algorithms:

 Focuses on designing algorithms that effectively addresses specific challenges of


the given problem and
 Analyzing the algorithmic efficiency in terms of time and space complexity.

1. Experimental Analysis of Algorithms:


 Experimental analysis complements theoretical analysis by evaluating algorithms
through practical experiments and real-world data
 It calculates the algorithm performance using actual implementations and empirical
measurements.
 Algorithms are tested on real-world data
 Performance metrics are CPU times, memory usages etc
 Advantage: Reflects practical execution conditions.

2. Limitations of Experimental Analysis of Algorithms:


 In experimental Analysis, the execution time of an algorithm is calculated as:

 To find the algorithm with better Time efficiency(running time), it is difficult to


compare the Experimental running times of two algorithms unless the
experiments are performed in the same hardware and software environments.
 Experiments can be done only on a limited set of test inputs, hence there may be
missing inputs
 An algorithm must be fully implemented in order to execute it to study its running
time experimentally.

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.

Topic: Asymptotic Notations

What is Asymptotic Analysis?


 Asymptotic analysis refers to computing the running time of any algorithm in
mathematical units of computation.
 Asymptotic analysis refers to the theory of approximation.
 The efficiency of algorithms is calculated using asymptotic analysis, independent of
the given data set or programming language.
 In most cases, we are interested in the order algorithm instead of the exact time
required for running an algorithm. This time is also known as Asymptotic Running
Time.
 Asymptotic analysis approximates time complexity by considering only the highest
degree of a polynomial.
 Lower-order terms and multiplicands are generally ignored as the constants are
dependent on the machine in which the algorithm runs.
 It is a technique of representing limiting behavior of algorithmic functions as
inputs approach infinity or some other limit value.
 Time complexity of an algorithm (Algorithmic analysis) has three types:
1. Best Case − Minimum time required for program execution. Example: In
bubble sort, when the input array is already sorted, the time taken by the
algorithm for sorting elements is linear i.e. the best case. [Fastest algorithm]
2. Average Case − Average time required for program execution. Example:
When the input array is neither sorted nor in reverse order, then it takes
average time [Input is random]
3. Worst Case − Maximum time required for program execution. Example:
when the input array is in reverse condition, the sorting algorithm takes the
maximum time (quadratic) to sort the elements i.e. the worst case. [Slowest
Algorithm]

What is Asymptotic Notation?


 Asymptotic notation is shorthand and mathematical way of representing the space or
time complexity of an algorithm (performance) like f(n).
 The Best case, worst case and average case Time complexity are denoted using
asymptotic notations.
Examples: An algorithm has O(n) or θ(n2) or Ω(n log n) time complexity

45
Types of Asymptotic Notations:
1. BIG 0 notation (Big Oh)
2. BIG Ω notation (Big Omega)
3. BIG θ notation (Big Theta)

1. BIG O NOTATION – O(big oh)

What is BIG O notation?

1. Big O notation provides an asymptotic upper bound for a function.


2. It describes how the running time or space complexity of an algorithm grows
as the input size increases.
3. This notation provides the worst-case time complexity – the maximum
amount of time or the longest time, an algorithm may need to solve a
problem.

Mathematical Definition:

Let t(n) be a non-negative function representing the Running time of our


algorithm.
Let g(n) be the asymptotic tight upper bound on function t(n)
Let c and n be positive constants representing the Execution time for Basic
operation and Input size respectively

A function t (n) is said to be in O(g(n)), denoted as: t (n) ∈ O(g(n)),

if there exist some positive constants c and n0 such that

For any value of n, the running time of an algorithm does not cross the time
provided by O(g(n)).

t(n) always lies on or below c*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:

Let us consider a given function t (n) = 100n + 5


Consider g(n) = n2

By Big O notation,

Let us prove function 100n + 5 ∈ O(n2 )

100n + 5 ≤ c. n2 , for all n ≥ n0,

Let c = 105 and n0 =1 and n=1

100(1) + 5 ≤ 105*12
100 + 5 ≤ 105
105 ≤ 105

Hence, the complexity of t(n) = 100n + 5 can be represented as O (g (n) ) ,


i.e. O (n2).

47
2. BIG Omega Ω NOTATION – Ω (big Omega)

What is BIG Ω notation?

1. It provides the asymptotic lower bound or limit of an algorithm’s running time or


space usage.

2. This notation provides the Best-case time complexity – the best or minimum
amount of time, an algorithm may need to solve a problem.

3. Big omega notation is the inverse of the Big 0 notation

Mathematical Definition:

Let t(n) be a non-negative function representing the Running time of our


algorithm.
Let g(n) be the asymptotic tight lower bound on function t(n)
Let c and n be positive constants representing the Execution time for Basic
operation and Input size respectively

A function t (n) is said to be in Ω (g(n)), denoted as: t (n) ∈ Ω(g(n)),

if there exist some positive constants c and n0 such that

For any value of n, the minimum time required by the algorithm is given by Omega
Ω(g(n)).

t(n) always lies on or above c*g(n).

48
Example 1:

Let us consider a given function t (n) = n3


Consider g(n) = n2

By Big Ω notation,

Let us prove function n3 ∈ Ω(n2 )

n3 ≥ c. n2 , for all n ≥ n0,

Let c = 1 and n0 =1 and n=2

(23 ) ≥ 1* 22
8 ≥ 1* 4
8≥4

Hence, the complexity of t (n) = n3 can be represented as Ω (g (n) ) , i.e. Ω (n2).

Therefore, n3 ∈ Ω(n2 )

49
3. BIG Theta θ NOTATION – θ (big Theta)

What is BIG θ notation?

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:

Let t(n) be a non-negative function representing the Running time of our


algorithm.
Let g(n) be the asymptotic tight upper and lower bound on function t(n)
Let c and n be positive constants representing the Execution time for Basic
operation and Input size respectively

A function t (n) is said to be in θ (g(n)), denoted as: t (n) ∈ θ (g(n)),

if there exist some positive constants c1 and c2 and n0 such that

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:

Let us consider a given function t (n) = 1/2 n(n − 1)


Consider g(n) = n2

By Big θ notation,

Let us prove function: 1/2 n(n − 1) ∈ θ (n2)

C1. n2 ≤ 1/2 n(n − 1) ≤ c2. n2 , for all n ≥ n0,

Let c1 = 0.25, c2 = 0.50 and n0 =1 and n=2

0.25* 22 ≤ 1/2 * 2(2 − 1) ≤ 0.5 * 22


1 ≤1 ≤ 2

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)

Advantages and Disadvantages of Asymptotic analysis:

Advantages of Asymptotic analysis:


1. To provide a high-level understanding of how an algorithm performs with
respect to input size
2. To compare the efficiency of different algorithms and selecting the best one for
a specific problem
3. To predict how an algorithm will perform on larger input sizes, which is
essential for real-world applications

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.

What is Order of Growth / Rate of Growth?


 It is the process of measuring the efficiency of algorithm with respect to input size.
 Rate of growth is helpful in understanding the behaviour of the algorithms

Steps to measure Order of Growth:


Step 1: Measure the complexity of an algorithm t(n) for larger values of n.
Step 2: Compare the complexity of our algorithm with the different functions with
same growth rate so that our algorithm can be ranked.

For example, for varying input size n, the order of growth is given in below table:

52
From the table, it is observed:

1. Logarithmic function is slowest growing function


2. Exponential function 2n is the fastest growing function , and it is difficult to compute
as n grows larger.
Hence algorithms with lower degree of functions are called more efficient.

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

Analysis of Recursive algorithms:


 The analysis of recursive algorithms requires recurrence equations.
 A recurrence relation is an equation which represents a sequence based on some rule. It
helps in finding the subsequent term (next term) dependent upon the preceding term
(previous term).

General Plan for Analyzing the Time Efficiency of Recursive Algorithms


Step 1: Decide on a parameter (or parameters) indicating an input’s size.
Step 2: Identify the algorithm’s basic operation.
Step 3: Check whether the number of times the basic operation is executed can vary on
different inputs of the same size; if it can, the worst-case, average-case, and best-
case efficiencies must be investigated separately.
Step 4: Set up a recurrence relation, with an appropriate initial condition, for the number
of times the basic operation is executed.
Step 5: Solve the recurrence or, at least, ascertain the order of growth of its solution

Examples:

1. Example 1: Compute the factorial function F(n) = n! for an arbitrary


nonnegative integer n.

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,

Recursive algorithm to compute the Factorial function:

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

The number of multiplications M(n) needed to compute Factorial function:

Step 4: Set up Recurrence Equation with appropriate initial condition


Initial Condition: It is the condition that makes the algorithm stop its recursive
calls
if n = 0 return 1.
When n =0, no multiplication operation, Hence M(n) = 0

Initial condition refers to the Base Case: Termination condition for the recursive
function

Recurrence Equation:

Step 5: Solve Recurrence Equation through Backward Substitution

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.

2. Example 2: Tower of Hanoi puzzle

Problem - What is Tower of Hanoi Puzzle:


 We are given 3 rods/pegs, and we have n number of disks of different sizes that can
slide onto any of three pegs.
 Consider A (source), B (auxiliary), and C (Destination) rods/pegs.
 Initially, all the disks are on the first peg (leftmost one) in order of size, the largest on
the bottom and the smallest on top. (such that no smaller disk is under the larger one).
 The goal / objective is to move all the disks from the first tower to the third peg
(rightmost rod) , using the second one as an auxiliary, if necessary

Rule / Condition of Tower of Hanoi Puzzle:


 We can move only one disk at a time, and it is forbidden to place a larger disk on top
of a smaller one.

Recursive Solution of Tower Of Hanoi Puzzle:


(1). If we want to transfer n disks from source to destination tower.
(2). Let's consider the bottommost disk, it is the largest disk so cannot be placed to any other
tower except the destination tower.
(3). We first move the n-1 smallest disks from First Peg (Source) to the Temporary Peg B
using Recursion
(4). Then move the largest disk into the third Peg (Destination) C
(5). Then, move n-1 disks from the temporary tower to the destination tower C.
(6). The number of Moves depends on the number of Disks n

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:

Step 4: Set up Recurrence Equation with appropriate initial condition


i. Initial Condition: M(1) = 1
Initial condition refers to the Base Case: Termination condition for the
recursive function
Recurrence Equation:

Step 5: Solve Recurrence Equation through Backward Substitution

58
 Thus, we have an exponential algorithm for Tower of Hanoi Puzzle, which will run
for long time even for moderate values of n

Recursion Tree or Tree of Recursive calls:


 A recursion tree is a graphical representation that illustrates the execution flow of a
recursive function.
 It provides a visual breakdown of recursive calls
 The tree structure helps in analysing the time complexity and understanding the
recursive process involved.
 Each node in a recursion tree represents a particular recursive call.
 The initial call is depicted at the top, with subsequent calls branching out below it.
 The depth of the tree corresponds to the number of recursive calls before reaching the
base case (termination condition for a recursive function)

 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:

Step 4: Set up Recurrence Equation with appropriate initial condition


i. Initial Condition: A(1) = 0
Initial condition refers to the Base Case: Termination condition for the
recursive function
Recurrence Equation:

Step 5: Solve Recurrence Equation through Backward Substitution


The presence of [n/2] in the function’s argument makes Backward Substitution
method difficult for values of n that are not powers of 2.
So, apply Smoothness rule  n = 2k
Hence, A(2k) = A(2k /2) +1
A(2k) = A(2k-1) + 1

Recurrence equation:

Since initial condition is A(1), we substitute k= i, to obtain A(20) = A(0)

Hence,

60
4. Example 4: Time complexity of Recursive Fibonacci Series

Fibonacci numbers are the elements of Fibonacci sequence:


0,1, 1, 2, 3, 5, 8,……

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:

Step 4: Set up Recurrence Equation with appropriate initial condition


i. Initial Condition: A(0) = A(1) = 0
Initial condition refers to the Base Case: Termination condition for the
recursive function
Recurrence Equation:

Step 6: Solve Recurrence Equation through Backward Substitution

61
Hence,

62

You might also like