Cc103-Data Structures and Algrorithm

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 112

CC103- Data Structures and Algorithms Worktext

UNIT I. INTRODUCTION TO DATA STRUCTURE AND


ALGORITHM

Overview

This unit enlightens the students about the basics of data structures and algorithms. It
also introduced the Python programming and showed how the primitive data structures are
implemented. Array and its operations are also discussed.

Learning Objectives
In this unit, I will learn:
1. To define data structure;
2. To distinguish data structure from algorithm;
3. Understand the behavior of primitive from non-primitive data structures;
4. Implement array to python programs; and
5. Appreciate Python programming and its data structures.

Setting Up
1. Assume you have a plate of spaghetti. Can you enumerate your procedures on how you
eat this messy food?
2. You did laundry, and it was already dry. How can you manage those clean clothes?
3. If you have a ten stack of chairs, how can you remove the chair number 6?

Lesson Proper

Data Structure Overview

The data structures deal with how the data is organized and stored in the memory when
the program processes it and the algorithms are used to work data in these structures. It also
refers to a system for storing data. In other words, a data structure is an arrangement of data in
computer memory in such a way that it can quickly render the data accessible to the processor
for the necessary calculations.
An Algorithm is a set of instructions to process the data for a specific purpose.
Algorithms are implemented in the form of methods or functions or routines. An efficient
algorithm will be used to solve the problems quickly. One criterion of efficiency is the
algorithm's time, and another could be the memory it takes at run time.(
www.hashirharis.wordpress.com/category/python/)

Data Types

“The data structures are actually an implementation of Abstract Data Types or ADT. This
implementation requires a physical view of data using some collection of programming
constructs and basic data types.
• Data types are attributes or characteristics of data. It classifies data according to its
purpose.
• Data structures can have two categories, the primitive and non-primitive.

1
CC103- Data Structures and Algorithms Worktext

• The primitive is the simplest form of data representation, whereas the non-primitive is
more advanced.

Overview of Data Structure (Courtesy of DataCamp)

Primitive Data Structures

Jaiswal(2017) stated that the primitive data structures are the basic data structures. They
are the building blocks for data manipulation and contain pure, simple values of a data.

The following are the four primitive variable types of Python:

2
CC103- Data Structures and Algorithms Worktext

Characteristics of Non-Primitive Data Structures

Array

Courtesy from programiz.com

Stack

Queue

3
CC103- Data Structures and Algorithms Worktext

Data Structures in Python

The Python programming language was originally developed by Guido van Rossum in the
early 1990s, and has since become a prominently used language in industry and education. The
second major version of the language, Python 2, was released in 2000, and the third major
version, Python 3, released in 2008.
Python is formally an interpreted language. Commands are executed through a piece of
software known as the Python interpreter. The interpreter receives a command, evaluates that
command, and reports the result of the command.
For Python, source code is conventionally stored in a file named with the .py suffix (e.g.,
hello.py).

Python Applications

Python can be used to different aspects and scenarios. The following are the list of
different ways where you can apply Python.

1. Web and Internet Development


2. Desktop GUI Applications
3. Scientific and Numeric
4. Software Development
5. Education
6. Business Applications
7. Database Access
8. Network Programming
9. Games and 3D Graphics

Advantages of Python

There are many reasons you need to study Python, and the list below are some of its
advantages:

• Python is Interactive: You can actually sit at a Python prompt and interact with the
interpreter directly to write your programs.
• Python is Interpreted: Python is processed at runtime by the interpreter. You do not
need to compile your program before executing it.
• Python is Object-Oriented: Python supports Object-Oriented style or technique of
programming that encapsulates code within objects.
• Python is a Beginner’s Language: Python is an excellent language for the beginner-
level programmers and supports the development of a wide range of applications
from simple text processing to WWW browsers to games.
(https://hashirharis.wordpress.com/category/python/)

4
CC103- Data Structures and Algorithms Worktext

Built-in Data-structures in Python

User-defined Data-structures:

Arrays: It is similar to Lists, but the difference is it can store single element/datatype
Stack: Linear LIFO (Last-In-First-Out) Data structure
Queues: Linear FIFO (First-In-First-Out) data structure
Trees: Non-Linear data structures having a root and nodes
Linked Lists: Linear data structures that are linked with pointers
Graphs: Store a collection of points or nodes along with edges
Hash Maps: It is the same as Dictionaries.

5
CC103- Data Structures and Algorithms Worktext

Installing Python

Windows Installation

• Open a Web browser and go to https://www.python.org/downloads/.


• Download the
• Run the downloaded file. When the downloaded file is running the Python wizard
will show and process. It takes minutes to finish this wizard and you must set to the
default settings and wait until the installation is done.
• Click this icon

Python shell for instant calculations

6
CC103- Data Structures and Algorithms Worktext

Python script for coding

Save your file to your folder Python34/ and use .py extension name file.

How to Run

7
CC103- Data Structures and Algorithms Worktext

output

Python Identifiers

“A Python identifier is a name used to identify a variable, function, class, module or other
object.

• The identifier is also starts with a lowercase letter or capital letters or it has an
underscore (_) followed by letters or numbers (0 to 9).
• Punctuation characters like %, @, and $ within identifiers are not valid.
• It is also case sensitive programming language where Power and power are two
dissimilar identifiers”

Some Rules for Python identifiers

• Class names begins with the capital letter and other identifiers start with a lowercase
letter.
• An identifier with a single leading underscore specifies as private identifier.
• An identifier with two leading underscores specifies a strongly private identifier.
• The identifier with two trailing underscores ends defined as special name”(

Reserved Words

The following are the Python reserved words and cannot be used as constant or variable or
any other identifier names.

8
CC103- Data Structures and Algorithms Worktext

“Lines and Indentation of Python

• Python don’t have braces. The blocks of code are signified by line indentation which
is strictly required.
• The number of spaces in the indentation is variable, and all statements must be
indented all within the block.

Quotation in Python

• It accepts single (‘), double (“) and (‘’’ or “””) quotes to represent string literals, as
long as the same type of quote starts and ends the string.
• The triple quotes are used to span the string across multiple lines. The following
examples are valid:

How to use Comments in Python?

• A hash tag sign (#) is used to begin in a comment. All typescripts/characters after the
# and ip to the end of the physical line are part of the comments.

9
CC103- Data Structures and Algorithms Worktext

Output:

10
CC103- Data Structures and Algorithms Worktext

11
CC103- Data Structures and Algorithms Worktext

12
CC103- Data Structures and Algorithms Worktext

Python Strings

Strings are identified as a contiguous set of characters represented in the quotation marks.

Python allows for either pairs of single or double quotes. “Subsets of strings can be taken
using the slice operator ([] and [:]) with indexes starting at 0 in the beginning of the string and
working their way from -1 at the end. The plus (+) sign is the string concatenation operator and
the asterisk (*) is the repetition operator( www.studocu.com/de/document/wheaton-
college/computer-literacy/uebungen/python-tutorial/2712597/view)

Try This!

Output:

Array

An array is a data structure, which can store a fixed-size collection of elements of the same
data type. An array is used to store a collection of data, but it is often more useful to think of
an array as a collection of variables of the same type.

Python can also handle containers with specified data types. Array can be handled in python
by module named “array “. It can be useful in manipulating a specific data type value.(
www.datacamp.com/community/tutorials/data-structures-python)

13
CC103- Data Structures and Algorithms Worktext

Operations on Array

1. array(data type, value list) :- This function is used to make an array with data type and
value list specified in its arguments.

2. append() :- This function is used to add the value at the end of the array in its arguments.

3. insert(i,x) :- This function is used to add the value at the location specified in its argument.

Initializing array with array values

Try This!

Output:

4. pop() :- This function removes the element at the location mentioned in its argument, and
returns it.

5. remove() :- This function is used to remove the first occurrence of the value mentioned in
its arguments.

14
CC103- Data Structures and Algorithms Worktext

Removing/Popping Element

Try This!

6. index() :- This function returns the index of the first occurrence of value mentioned in
arguments.

7. reverse() :- This function reverses the array.

15
CC103- Data Structures and Algorithms Worktext

Try This!

Output:

Below are some more functions:

1. typecode :- This function returns the data type by which array is initialized.

2. itemsize :- This function returns size in bytes of a single array element.

3. buffer_info() :- Returns a tuple representing the address in which array is stored and
number of elements in it.

16
CC103- Data Structures and Algorithms Worktext

References

1. Urooj, Wajiha.How to Implement Data Structures and Algorithms in Python. Updated


last January 17, 2020 retrieved from http://www.edureka.co/blog/data-structures-and-
algorithms-in-python
2. Jaiswal, Sejal.Python Data Structures Tutorial. Updated December 8, 2017
retrieved from https://www.datacamp.com/community/tutorials/data-structures-
python
3. www.tutorialsduniya.com/notes/data-structures-notes
4. www.tutorialspoint.com/python/python_basic_syntax.htm
5. www.jiwaji.edu/pdf/ecourse/computer_sci_app/PGDCA Python Notes UNIT - 1.pdf
6. www.hashirharis.wordpress.com/category/python/
7. www.tehapps.com/basic-syntax-in-python/
8. https://blog.csdn.net/qq_27009517/article/details/87273744

17
CC103- Data Structures and Algorithms Worktext

NAME: ___________________________________DATE:_____/_____/2020__
SECTION:_BSIT-__________________ _______SCORE:_______/50_______
QUIZ #1

GENERAL INSTRUCTION: STRICTLY NO ERASURES. Any form of erasure will be


considered wrong.
I. MULTIPLE CHOICE. Choose the letter of the correct answer and write your
answer inside the box (2 points each).

______1. A data structure should be seen as a logical concept that must address two
fundamental concerns, except
a. arrangement of b. how the c. what operations will d. manipulate the
data in computer's data will be performed on it data in those
memory be stored structures

______2. It is the implementation of Abstract Data Types or ADT.

a. Algorithm b. Data c. Abstraction d. Encapsulation


structure

_____3. Data structures can be divided into two categories in computer science such as
.
a. numbers and b. primitive and c. float and double d. string and
characters non primitive float

_____4. It represents numeric data, and more specifically, whole numbers from negative
infinity to infinity.
a. float b. string c. integer d. boolean

_____5. It is a named memory location and can hold only one value at a time
.
a. data type b. Object c. variable d. constant

_____6. You can use it for rational numbers, usually ending with a decimal figure
a. data type b. Object c. variable d. constant

_____7. It is step by step set of instruction to process the data for a specific purpose

a. Algorithm b. Switch c. Data structure d. None of the


Case above

_______ 8. Version of Python installed in our laboratory


a. Python3.6 b. . Python3.5 c. . Python3.7 d. . Python3.4

_____9. It can be useful when we have to manipulate only a specific data type values
a. list b. tuple c. array d. dictionary

______10. It is a name used to identify a variable, function, class, module or other


object terminated.
a. string b. identifier c. float d. variable

18
CC103- Data Structures and Algorithms Worktext

Part II. ENUMERATION: (18 Points)

Python’s four primitive data Give at least 4 linear data structures Operation OF Array
types
1 1 1

2 2 2
3 3 3
4 4 4
Reserved Words in Python 5
1 6
2 7
3

III. Identify the characteristics of the following data structures

Data Structure Advantage Disadvantage

Array

Stack
Queue
Linked List
Binary Tree
Heap

19
CC103- Data Structures and Algorithms Worktext

NAME: ___________________________________DATE:_____/_____/2020__
SECTION:_BSIT-__________________________SCORE:_______/30_______
QUIZ #2

GENERAL INSTRUCTION: STRICTLY NO ERASURES. Any form of erasure will be


considered wrong.

ESSAY. Write the answer on the space provided.

1. Explain why data structures are important in programming?

_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
______________________________
2. I discovered that_______________________________________________________

_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
______________________________
3. How does Python implement data structures?

_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
__________________

20
CC103- Data Structures and Algorithms Worktext

NAME: _____________________________ DATE: _____/_____/2020__


SECTION:_BSIT-_______________________SCORE:_______/30_______
LABORATORY EXERCISE # 1: String

Direction: Make the output below using the string


str =” Hello Students of Data Structure and Algorithms”. Send the image of your script/code
and its output.

Hello
Students
Of
Data Structure
and Algorithms
Hello Students of Data Structure and Algorithms

21
CC103- Data Structures and Algorithms Worktext

NAME: _____________________________________ DATE: _____/_____/2020__


SECTION:_BSIT-_______________________SCORE:_______/30_______
LABORATORY EXERCISE # 2: Comments

Direction: Use comment for the requirement given below. Send the image of your script/code
and its output.

Requirements: Using Python script window, print the statements and answers of the following
equation and add comments of each equation

• print the (10 + 5), add the comment # Addition


• print the (10 * 5), add the comment # Multiplication
• print the (10 - 5), add the comment # Subtraction
• print the (10 / 10), add the comment # Division

Example Output:

10+5 15 Addition

22
CC103- Data Structures and Algorithms Worktext

NAME: _____________________________ DATE: _____/_____/2020__


SECTION:_BSIT-_______________________SCORE:_______/30_______
LABORATORY EXERCISE # 3: Assigning Values

Direction: Send the image of your script/code and its output.

Requirements: Suppose you have $100, which you can invest with a 10% return each year.
After one year, it's 100×1.1=110 or 100×1.1=110 dollars. After two years
it's 100×1.1×1.1=121. Make a code that calculate how much money you end up with after 7
years. Print the result

23
CC103- Data Structures and Algorithms Worktext

NAME: _____________________________ DATE: _____/_____/2020__


SECTION:_BSIT-_______________________SCORE:_______/30_______
LABORATORY EXERCISE # 4: Array

Direction: Send the image of your script/code and its output.

Requirements:

1. Create an array with the following content:


“one”,” two”, “three”, “four”
2. Insert “five” in between of “two” and “three”
3. Delete “four”.
4. Display the array content

24
CC103- Data Structures and Algorithms Worktext

UNIT 2. LINKED LIST, STACK AND QUEUES

Overview

This unit kills four birds with one stone: You develop a strong understanding of
the stacks and queues, strengthen your abilities in working with arrays, and develop a
moderate facility with linked lists.

Learning Objectives
At the end of the lesson, the students are expected to:
1. Write a program using array-based lists;
2. Write programs using linked lists; and
3. Write a program using doubly linked list.
Setting-Up
1. What linked lists are and when you should use them
2. How to use collections.deque to implement queues and stacks
3. How to implement your own linked list and node classes, plus relevant methods
4. What the other types of linked lists are and what they can be used for

Lesson Proper

Linked list
Linked lists are an organized set of items. Linked lists are distinct from lists because they
retain items in memory. Although lists use a single block of memory to store their data
references, related lists store references as one of their own components.
Main Concepts
Each element of a linked list is called a node, and every node has two different fields:
1. Data contains the value to be stored in the node.
2. Next contains a reference to the next node on the list.
Here’s what a typical node looks like:

25
CC103- Data Structures and Algorithms Worktext

A linked list is a collection of nodes. The first node is called the head, and it is used as the
starting point for any iteration through the list. The last node must have its next reference
pointing to None to determine the end of the list. Here’s how it looks:

Practical Applications
Linked lists represent a variety of real-world purposes. These will be used for the creation
of queues or stacks (spoiler alert!) as well as diagrams. These are often beneficial for even more
complicated functions, such as life-cycle management for an application to operating system.
Queues or Stacks
Queues and stacks only vary in how items are recovered. You'll need a First-In / First-Out
strategy (FIFO) with a line. This assumes the first item to be recovered added in the chart is the
first item to:

You can see the front and rear components of the queue in the image above. These can move to
the far end as you add new items to the list. They'll be pulled from the front of the list as you
grab objects.
You use a Last-In / Fist-Out method (LIFO) for a stack, implying the last item placed in the list
is the first one to be retrieved:

26
CC103- Data Structures and Algorithms Worktext

Within the example above it indicates that at the bottom is the first element placed on the
stack (index 0), and at the top is the last element placed. The last item inserted (at the top) would
be the first to be retrieved because stacks use the LIFO method.
One of the most convenient ways to implement those data structures is to insert and retrieve
elements from the edges of queues and stacks, linked lists.

Graphs
Graphs can be used to display object relationships, or to represent different network types.
A graphic depiction of a graph, for example — say a directed acyclic graph (DAG)—might
look like this:

27
CC103- Data Structures and Algorithms Worktext

There are different methods of applying graphs such as the above, but one of the more
common is to use an adjacency chart. An adjacency list is a set of linked lists in which each
graph vertex is placed alongside a selection of linked vertices:

In the table above, the left column lists every vertex in the line. The right column includes
a set of related lists that store the other vertices in the left column which are bound to the
corresponding vertex. This adjacency list may also be described with a dictum in code:

This dictionary's keys are the vertices of the source, and a list is the meaning for any
word. Typically the set is enforced as a connected array

Implementing graphs using adjacency lists is very effective in terms of both speed and
memory as contrasted with, for example, an adjacency matrix. For this function connected
lists are so useful to execute graphs.

28
CC103- Data Structures and Algorithms Worktext

Performance Comparison: Lists vs Linked Lists


Implementing graphs using adjacency lists is very effective both in terms of speed and
memory, as contrasted with an adjacency matrix, for example. Lists attached for this purpose
are so useful for executing graphs.
As the gap in memory use between the lists and the related lists is too small, when it comes
to time complexity, it is easier to concentrate on their output disparities.
Insertion and Deletion of Elements
List initialization times differ based on how often the current collection has to resize.
Python over allocates array space according to their production. This means that inserting a new
element into a list, depending on whether the existing array needs to be resized, can take
anywhere from Θ(n) to Θ(1)
The same holds true with the elimination of elements from the list. When the array size is
smaller than half the allocated height, otherwise Python must shorten the list. Or, all and all, the
addition or omission of elements from an array has an average complexity of Θ(n). time.
Nonetheless, connected lists are much easier when it comes to adding and removing items
at the beginning or end of the document, where the uncertainty of their duration is constant:
Θ(1) . This performance advantage is why linked lists are so useful for queues and stacks, where
elements are inserted and removed from the edges continuously.
Retrieval of Elements
Lists do even easier when it comes to the lookup of items than connected lists. Lists will
execute this procedure in Θ(1) time if you know which item you want to reach. Trying to do
the same for a connected list will take Θ(n) because to locate the item you need to go through
the entire list.
Nevertheless, all lists and connected lists behave quite similarly when looking for a
particular item, with a time-complexity of range(n). For all instances, to locate the thing you
are searching for, you will iterate over the whole collection.

Introducing collections.deque
In Python, the collections module contains a specific object you can use for linked lists
called deque(pronounced "deck"), which stands for double-ended queue.
Collections.deque uses a connected list application in which items may be viewed, added
or deleted from the beginning or end of a list with constant O(1) output.
How to Use collections.deque
There are quite a few methods which come with a deque object, by default. However,
you'll just focus on a couple of them in this post, mainly for incorporating or deleting
components.
Next, building a related chart. To do so with deque, you may use the following piece of
code:

29
CC103- Data Structures and Algorithms Worktext

The code above should generate a list of empty connections. If you want it to be filled in
at development, you may give it an iterable as input:

You may transfer any iterable as an input while initializing a deque object, including a string
(also an iterable) or a list of objects.
Now that you know how to create a deque object, by adding or removing elements, you
can interact with that. You can create a linked list with abcde and add a new element f like this:

30
CC103- Data Structures and Algorithms Worktext

Both append () and pop() add or subtract items from the related list on the right side.
Moreover, you may also use deque to add or delete items from the list easily from the left
side, or head:

Using the deque object, adding or removing elements from both ends of the list is fairly
straightforward. Then you're able to know how to build a list or a stack using
collections.deque.

How to Implement Queues and Stacks


The biggest distinction between a list and a stack is how items are extracted from each. You
can then figure out how sets should be found. Deque to have both data structures implemented.

31
CC103- Data Structures and Algorithms Worktext

Queues
For queues, you want to attach elements to a list (enqueue), and when the timing is right,
you want to delete the longest (dequeue) item in the list. Think of a line at a cool, completely
booked bar, for example. When you wanted to introduce a equal guest seating scheme then you
should start by establishing a queue and introducing people when they arrive:

Now you are in queue with Mary, John, and Susan. Know, because queues are FIFO, the
first person who has joined the queue will be the first one to get out.
Now assume that some time will pass and that a few tables will become available. You want
to bring people out of the queue in the appropriate order at this point. Then you'd put something
like this:

Each time you call popleft(), (the head item is removed from the linked list, mimicking a
real-life queue.

32
CC103- Data Structures and Algorithms Worktext

Stacks
What if then you wanted to build a stack? Ok, the principle is pretty much the same as for
the list. The only difference is that the stack uses the LIFO approach , which means the last
element to be inserted into the stack should be removed first.

If you want this action to be transformed into a stack so you could do something like this:

In this case, you generated an empty history array, and you attached it to your history
variable using appendleft() any time the user visited a new site. Doing so meant that the
connected list header was applied to each new feature.
Now imagine they wanted to go back to the Actual Python homepage to pick a new article
to read after the consumer read all posts. Knowing you have a stack and want components
extracted using LIFO, you can do the following:

You go there! You deleted items from the header of the related list by using popleft() before
you entered the home page of Real Python.

33
CC103- Data Structures and Algorithms Worktext

You will see from the examples above how helpful it would be to have collections.deque
in your toolbox, so make sure you use it the next time you have to overcome a list- or stack-
based problem.
How to Create a Linked List
Firstly, build a class to display the linked list:

For a related list the only detail you need to store is where the item begins (the item
header). Next, construct a separate class to reflect any node in the linked list:

You will see the two principal elements of each single node in the following class
definition: data and next. You may also apply a _repr_ to all groups to properly describe the
objects:

34
CC103- Data Structures and Algorithms Worktext

Look at an example of how to easily build a linked list of three nodes using the classes above:

35
CC103- Data Structures and Algorithms Worktext

You can construct a linked list very easily by specifying the data of a node and its next
values. The starting points for our implementation are those LinkedList and Node groups. From
now on, it's all about getting them fully usable.
Here is a minor improvement to the init( ) (linked list, which helps you to easily build linked
lists of some data:

With the above change it will be much easier to build linked lists to be used in the examples
below.
How to Traverse a Linked List
Traversing it is one of the most common things you'll do with a linked list. Traversing means
going through each single node, beginning with the linked list header and finishing on the node
that has a next None tag.
Traversing is just a fancy way of saying iterate. So, with that in mind, create a _ iter _ to
add the same behavior you would expect from a normal list to the linked lists:

The latter procedure goes down the list and yields to a single node. The most critical thing
to note about this _iter _ is that you will verify at all times that the present node is None. This
indicates you've hit the end of your related list when the condition is valid.
You want to move to the next node on the list, after yielding the current node. For this
function you add node = node.next. Here is an example of random list traversing and printing
per node:

36
CC103- Data Structures and Algorithms Worktext

You may see the traversing described in other articles into a different method called
traverse). Nonetheless, utilizing built-in methods from Python to accomplish such actions
makes the design of this related list a little more Pythonic.

How to Insert a New Node


There are different ways to insert new nodes, each with its own implementation and level
of complexity, into a linked list. That's why you'll see them split into specific methods for
inserting them at the start, end, or between a list nodes.
Inserting at the Beginning
Inserting a new node at the beginning of a list is potentially the simplest addition, because
you don't have to cross the whole list to do so. This is just about generating a new node, then
referring to it at the top of the list.
Look at the following specification for the LinkedList class add first():

In the case above, you set self.head as the next reference of the new node, and the new node
refers to the old self.head. After that you must state that the inserted node is the new head of
the list.

37
CC103- Data Structures and Algorithms Worktext

Here's how the reference set behaves:

As you can see, add_first() still applies the node to the list header, even though the list was
still zero.
Inserting at the End
Inserting a new node at the end of the list will allow you to search the whole linked list first,
and then add the new node when you reach the top. You can't only connect to the end like you
do in a normal list, since you don't know which node is last in a connected list.
Below is an example of a function applying the assignment of a node to a linked list ending:

Next, you want to traverse the whole list before you hit the end (i.e. before the StopIteration
clause activates the for loop). Next, you want the current node to be set to the last node on the
list. Ultimately, you would like to add the new node to the current node as the next key.
Here, in practice, is an example of add_last():

38
CC103- Data Structures and Algorithms Worktext

You start by generating a list of 4 values (a, b, c , and d) in the code above. Instead, you
will see that the nodes are still appended to the end of the list as you add new nodes using
add_last().

Inserting Between Two Nodes


Inserting between two nodes introduces even another dimension of difficulty to the already
complicated insertions of the connected list, since you may use two separate approaches:
1. Inserting after an existing node
2. Inserting before an existing node
Dividing this into two approaches may seem odd, but connected lists work differently from
regular lists, so you need a separate implementation for each event.
Here's a method which adds a node with a different data value after an existing node:

39
CC103- Data Structures and Algorithms Worktext

In the code above, you are moving through the related list in pursuit of the node, with data
showing that you want to attach a new node. Once you locate the node you are looking for, you
attach the current node directly after it and rewire the next connection to maintain the list intact.
The main examples are if the list is null, which forbids the addition of a new node following
an current node, or whether the list does not include the attribute you are looking for. Below
are few details of how add_after() will behave:

An exception would be to try to use add_after() on an empty list. The same happens when
you try to add a node after it doesn't exist. Everything the rest operates only as planned.
If you decide to enforce add_before() so anything like this would look like this:

While implementing the above there are a few things to keep in mind. First, as with
add_after(), if the linked list is empty (line 2), or the node you are looking for is not present
(line 16), you want to make sure you raise an exception.

40
CC103- Data Structures and Algorithms Worktext

Second, if you try to add a new node in front of the list header (line 5), then you can reuse
add_first() because the node you are inserting will be the new list header.
Finally, for any other case (line 9) you should use the prev_node variable to keep track of
the last checked node. Then, when you find the target node, you can rewire the next values
using that prev_node variable.
An explanation worth a thousand lines, once again:

Using add_before(), you now have all the methods you need to insert nodes in your
collection however you want.

How to Remove a Node


To delete a node from a connected list, you need to search the list first before the node you
want to exclude is identified. When you have identified the goal, you want to connect its
preceding and next nodes. This re-link is what excludes the destination node from the chart.
Which means you need to keep track of the corresponding node while you move down the
sequence. Check at an Implementation example:

41
CC103- Data Structures and Algorithms Worktext

First you verify in the code above that your list is not empty (line 2). If it is true, so you are
creating an exception. Before that, you test whether the current head of the list (line 5) is the
node to be deleted. If it is, then you want to become the new head of the next node in the list.
If none of the above happens, then you continue to traverse the sequence, trying to delete
the node (line 10). When you notice it, you need to change the previous node to lead to the next
node, which will immediately delete the node from the list. Finally, if you are running around
the whole list without locating the node to be deleted (line 16), then you are creating an
exception.
Note how you use previous node in the code above to keep track of the last, well, node.
Using this makes sure the entire thing becomes even easier until you consider the correct node
to be removed.
Here is an illustration which uses a list:

42
CC103- Data Structures and Algorithms Worktext

How to Use Doubly Linked Lists


Doubly linked lists vary from independently connected lists, as they have two references:
1. The previous field references the previous node.
2. The next field references the next node.
The final result is as follows:

If you decided to incorporate the above, you might make certain modifications to your current
Node class to add a previous field:

43
CC103- Data Structures and Algorithms Worktext

This kind of design will allow you to traverse a list in both directions instead of utilizing just
the next. You could use to go backwards, next to go forward and then.
In terms of structure, this would look like a doubly connected list:

Earlier you heard that collections.deque is utilizing a related list as part of its data structure.
That's the kind of connected list that it requires. For doubly connected lists, deque is able to
attach or remove items from both ends of a queue for O(1) output constant.
How to Use Circular Linked Lists
Circular linked lists are a form of linked list where the last node points back to the head of
the list rather than to Zero. It renders them round. There are also a few fascinating usage cases
for circular connected lists:

• Take turns of rising character in a cooperative game


• Managing the life cycle of a specified operating system
• Implementing a Stack of Fibonacci
This is what a related round list looks like:

44
CC103- Data Structures and Algorithms Worktext

Some of the advantages of circular connected lists is you can traverse the whole list
beginning at every node. Because the last node points to the head of the chart, as you hit the
starting point, you will make sure that you avoid traversing. Otherwise you are likely to wind
up in an endless loop.
Circular linked lists are very similar to single linked lists as per execution. The only
difference is that if you traverse the list you will identify the starting point:
Traversing the list also provides an extra statement, start_point, which is used to describe
the start and the end of the iteration cycle because the list is recursive. Besides that, most of the
application is the same as the one we had in our LinkedList series.
To wrap up with a final illustration, take a look at how this latest list form conducts when you
offer it any data:

45
CC103- Data Structures and Algorithms Worktext

You will find that when traversing the list, you no longer have the None. That's how a
revolving chart has no clear conclusion. You will also see that it can make subtly different
versions of the same collection by selecting separate start nodes.

46
CC103- Data Structures and Algorithms Worktext

REFERENCES
1. https://devsday.ru/blog/details/15450
2. https://www.tuicool.com/articles/fmaMFvY
3. https://realpython.com/linked-lists-python/
4. https://flosshub.org/aggregator/sources/13?page=36
5. https://www.flosshub.org/aggregator?page=115
6. moz-extension://a071a1d5-e026-4c58-a261-ddf2e8898cdb/html/block_page.html
7. https://digitechbuy.com/fkeujms/create-circular-queue-in-python.html
8. https://www.codementor.io/@codementorteam/a-comprehensive-guide-to-
implementation-of-singly-linked-list-using-c_plus_plus-ondlm5azr
9. https://www.cs.auckland.ac.nz/compsci105s1c/lectures/Bruce/19-LinkedList(3).pdf
10. https://www.softwaretestinghelp.com/linked-list/
11. https://www.cs.auckland.ac.nz/compsci105s1c/lectures/Bruce/19-LinkedList(3).pdf
12. https://faisalgama.com/wp-content/uploads/CSC-214.pdf
13. https://start-concurrent.github.io/chunked/chap17.html
14. https://files.transtutors.com/cdn/uploadassignments/2847860_3_modules-1-14.pdf
15. https://medium.com/@mariam.jaludi/data-structures-linked-lists-8f277b61cca
16. https://www.mathworks.com/help/matlab/matlab_oop/example-implementing-linked-
lists.html
17. https://www.slideshare.net/DSBasha/sulthans-data-structures
18. https://www.freekeyworddifficultytool.com/find/linked-list-node-class
19. https://www.crashwhite.com/advtopicscompsci/materials/lectures/unit4.html
20. https://www.flosshub.org/aggregator?page=105
21. https://docplayer.net/23933376-UNIT-7-queues-and-deques.html
22. https://vigyancode.blogspot.com/2016/10/data-structure-and-algorithm.html
23. https://www.plagscan.com/highlight?doc=132994921&source=24#2
24. https://www.researchgate.net/publication/2349751_Design_And_Implementation_Of
_A_Generic_Graph_Container_In_Java
25. https://www.slideshare.net/widespreadpromotion/6-linked-list-data-structures-using-
c-by-varsha-patil
26. https://www.plagscan.com/highlight?doc=132994921&source=27
27. https://programmingwithmosh.com/net/csharp-collections/
28. https://www.linkddl.com/search/linkedlist-list

47
CC103- Data Structures and Algorithms Worktext

29. https://smartcatcontrol.com/lgdrlg8/7aff9.php?qp=implement-queue-using-linked-list-
geeksforgeeks
30. http://core.loyc.net/collections/dlist.html
31. http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.27.4867
32. https://www.sitepoint.com/ruby-interview-questions-linked-lists-and-hash-tables/
33. https://www.researchgate.net/publication/225760992_On_subdominantly_bounded_g
raphs_-_Summary_of_results
34. https://medium.com/the-renaissance-developer/stack-data-structure-a-pretty-simple-
guide-dc749edbb03f
35. https://www.edureka.co/blog/linked-list-in-c/
36. https://www.stltones.com/products/stl-tonehub-plugin
37. https://verificationacademy.com/verification-horizons/june-2013-volume-9-issue-
2/Verifying-High-Speed-Peripheral-IPs
38. https://www.kvraudio.com/news/stl-tones-releases-stl-tonehub-with-special-offer-
48395
39. https://www.udemy.com/course/javascript-bootcamp-2016/
40. https://cad.onshape.com/help/de_DE/Content/selection.htm
41. https://github.com/makinacorpus/webcouturier.dropdownmenu

48
CC103- Data Structures and Algorithms Worktext

NAME: _____________________________ DATE: _____/_____/2020__


SECTION:_BSIT-_______________________SCORE:_______/30_______
LABORATORY EXERCISE # 1:

Direction: Send the image of your script/code and its output.

1. Create a method to retrieve an element from a specific position: get(i) or even llist[i].

49
CC103- Data Structures and Algorithms Worktext

NAME: _____________________________ DATE: _____/_____/2020__


SECTION:_BSIT-_______________________SCORE:_______/30_______
LABORATORY EXERCISE # 2:

Direction: Send the image of your script/code and its output.

1. Create a method to reverse the linked list: llist.reverse().

50
CC103- Data Structures and Algorithms Worktext

NAME: _____________________________ DATE: _____/_____/2020__


SECTION:_BSIT-_______________________SCORE:_______/30_______
LABORATORY EXERCISE # 3:

Direction: Send the image of your script/code and its output.

1. Create a Queue() object inheriting this article’s linked list with enqueue() and
dequeue() methods.

51
CC103- Data Structures and Algorithms Worktext

UNIT 3. RECURSION

Overview
Often considered one of the more conceptually difficult concepts within the field of
Computer Science is recursion. In this unit, you will take an in-depth look at recursion,
learning the recursive steps, the role that recursion plays in common data structures, and what
happens inside the computer when a recursion function is invoked. By the end of this unit,
you will recognize situations that require recursion and be able to apply it appropriately

Learning Objectives

The learner should have the capacity to:

1. Understand the definition of recursion as well as seeing how simple recursive


programs work.
2. Demonstrate skills in tracing, analyzing and designing recursive algorithms and
recursive methods.

Setting Up
1. What is recursion?
2. What are the properties of recursion?
3. How to implement recursion in python?

Lesson Proper

What is recursion?
In literal definition, “It is the determination of a succession of elements by operation on one or
more preceding elements according to a rule or formula involving a finite number of steps” (
https://www.merriam-webster.com/dictionary/recursion)

In mathematical, a recursive method is one that is characterized by a base case and itself.

In programming, it is a procedure for taking care of issues by partitioning a bigger problem


into littler instances of the difficulty itself and afterward comprehending the littler, increasingly
unimportant parts. Recursion is a fantastic programming and critical thinking instrument. It can
be utilized with a broad scope of issues from essential customary emphases to the further
developed backtracking issues.

While recursion is amazing, recursive arrangements are not generally the most productive. In a
few occasions, in any case, recursion is the execution of decision as it permits us to handily build
up an answer for a confused issue that may some way or another be hard to unravel.

52
CC103- Data Structures and Algorithms Worktext

Recursive definitions

• It is a fundamental standard in characterizing new thoughts that they not be characterized


circularly.

• However, things being what they are, many programming construct are characterized as
far as themselves

• Luckily, the proper reason for these definitions is to such an extent that no infringement
of the guidelines happens

• These definitions are called recursive definitions and are frequently used to characterize
interminable sets

• This is on the grounds that a thorough list of such a set is inconceivable, so some others
intends to characterize it is required

• Thus, a method is called recursive if the body of the method calls the method itself, either
straightforwardly or by implication.

Properties of recursion
A recursive method can go unbounded like a circle. To maintain a strategic distance from
unbounded running of recursive method, there are two properties that a recursive method
must have :

• Base case − there must be at any rate one base measures or condition, to such an extent
that, when this condition is met the method quits calling itself recursively.

• Progressive action − the recursive calls should advance so that each time a recursive
call is made it comes nearer to the base case.

Method calls and recursive implementation

• What sort of data must we monitor when a method is invoked?

• If the method has boundaries, they should be introduced to their relating contentions

• In expansion, we have to realize where to continue the calling method once the called
method is finished

• Since methods can be called from different methods, we additionally need to monitor
neighborhood factors for scope purposes

• Because we may not know ahead of time what number of calls will happen, a stack is a
progressively proficient area to spare data

• So we can describe the condition of a method by a lot of data, called an actuation record
or stack outline

• This is put away on the runtime stack, and contains the accompanying data:

53
CC103- Data Structures and Algorithms Worktext

– Values of the method’s parameters, addresses of reference variables (including


arrays)
– Duplicates of local variables
– The return address of the calling method
– A dynamic connect to the calling method’s actuation record
– The method’s return value if it is not void
• Every time a method is called, its actuation record is made and placed on the runtime
stack
• So the runtime stack always contains the current state of the method
• As a representation, consider a method fun1() called from main()
• It thus calls method fun2(), which calls method fun3()
• The present status of the stack, with method fun3()executing, is manifest in fig 3.1
• Once fun3()completes, its record is popped, and method fun2()can resume and access
data in its record
• If fun3()calls another method, the new method has its actuation record pushed onto the
stack as fun3() is suspended

Fig. 3.1 contents of the run-time stack when main()


Calls function func1(), func1()calls func2(), and func2()calls func3()

• The utilization of actuation records on the runtime stack permits recursion to be


executed and taken care of effectively

54
CC103- Data Structures and Algorithms Worktext

• Essentially, when a method calls itself recursively, it pushes a new actuation record of
itself on the stack

• This suspends the calling instance of the method, and permits the new
actuation to carry on the procedure

• Thus, a recursive call makes a progression of initiation records for various


cases of a similar method

Tail and non-tail recursion


❖ If the recursive call is the last thing done by the method it is tail recursion.. There is
no compelling reason to keep record of the past state. Essentially, tail recursion is a loop
; it very well may be supplanted by an iterative algorithm to achieve a similar undertaking.
Indeed, much of the time, languages supporting loops should utilize this build instead
of recursion.
❖ If the recursive call is not the last thing done by the method, it is non-tail recursive,.
Subsequent to returning back, there is some something left to assess.

Consider the basic problem of printing the numbers from 1 to n in reverse order. The
iterative solving for this problem is fairly basic when using a loop build. Be that as it may, it
can likewise be settled recursively, that is, utilizing a recursive method. Assume we have applied
the following tail recursive method in python:

Def printrev( n ):
if n > 0 :
print( n )
printrev ( n-1 )

And we call the method with a parameter of 4:

Printrev( 4 )

the current sequential flow of execution is interrupted and control is


transferred to the printrev() function with a value of 4 being assigned to argument n. The body
of printrev() begins execution at the first statement. Since 4 is greater than 0, the body of the

55
CC103- Data Structures and Algorithms Worktext

if statement is executed. When the flow of execution reaches the printrev(3) function call, the
sequential flow is once again interrupted as control is transferred to another instance of the
printrev() function. The body of this instance begins execution at the first statement, but this
time with n = 3. Figure 3.2 illustrates the execution of the recursive function as a group of
boxes with each box representing a single invocation of the printrev() function. The boxes
contain the contents of local variables and only the statements of the function actually
executed. Each recursive call to printrev() is shown inside its own box with the boxes
positioned at the point where the function was invoked.

These recursive calls precede until a value of zero is passed to the method, at which time
the body of the if statement is skipped and execution arrives at the end of the method. Similarly
as with any method call, when execution arrives at the end of the method or the return statement,
execution comes back to the area where the method was initially called. For this situation, the
call to printrev(0) was done using inside the printrev(1) instance. Along these lines, execution
comes back to the principal proclamation after that conjuring. After execution comes back to the
printrev(1) instance, the end of that method is reached and again execution is come back to the
area where that example was conjured. The outcome is a chain of recursive returns or recursive
loosening up back to the original printrev(4) function call.

Figure 3.2: recursive flow of execution: (a) printrev() and (b) printinc().

56
CC103- Data Structures and Algorithms Worktext

What changes would be required to make a recursive method to print the similar
numbers in increasing order instead of reverse order? We can alter the location of the
recursive call to change the action of the recursive solution. Consider a non-tail recursive
print method:

Def printinc( n ):
if n > 0 :
printinc( n-1 )
print( n )

In this form, the recursive call is done ahead the value of n is printed. The outcome is
a series of recursive calls former to any other action is done. The actual printing of the values
is carry through after each instance of the method returns, as shown in figure 3.2(b).

Indirect recursion

• The earlier topics have concentrated on circumstances where a method, f(), calls itself
recursively which are examples of direct recursion.
• But, in certain circumstances, the method may be invoked not by itself, but by a method
that it calls, forming a chain:
F()→ g() → f()
• This is called as indirect recursion
• the chains of calls may be of discretionary length, such as:
F() → f1() → f2() → ∙∙∙ → fn() → f()
• It is likewise conceivable that a given method may be a part of multiple chains, based
on various calls
• So our past chain may resemble:

57
CC103- Data Structures and Algorithms Worktext

Nested recursion

• Another fascinating sort of recursion happens when a method invoke itself and is also
one of the arguments of the call
• Consider this example:

• From this definition, it is given that the method has solutions for n = 0 and n > 4
• On the other hand, for n = 1, 2, 3, and 4, the method determines a value depend on a
recursive call that requires assessing itself
• This is called nested recursion
• That signifies “recursion inside recursion”.
• Another model is the renowned (or perhaps infamous) ackermann function, defined as:

• first proposed by wilhelm ackermann in 1928 and later changed by rosza peter, it is
portrayed by its fast development

• to get a sense of this development, think about that a(3,m) = 2m+3 – 3, and

• There are (m – 1) 2s in the exponent, so a(4,1) = 216 - 3, which is 65533


• After all, altering m to 2 has a great impact as the value of has 19,729 digits in its
expansion
• As can be deduced from this, the method is splendidly expressed recursively, but quite
a problem to define iteratively

58
CC103- Data Structures and Algorithms Worktext

Excessive recursion

• Recursive algorithms will in general show straightforwardness in their usage and are
regularly simple to peruse and follow
• But, this straightforwardness has few downsides
• Generally, as the number of method calls raise, a program undergo some performance
decrease
• Besides, the amount of stack space required increments drastically with the amount of
recursion that happens
• This can prompt program crashes if the stack comes up short on memory
• More frequently, the expanded execution time produce poor program performance as
an example of this, consider the fibonacci numbers
• They are first referenced regarding sanskrit poetry as far back as 200 bce
• Leonardo pisano bigollo (also known as fibonacci), popularized them to the western
world in his book liber abaci in 1202 ce
• The initial few terms of the sequence are 0, 1, 1, 2, 3, 5, 8, … and can be produced
utilizing the method:

• This disclose us that that any fibonacci number after the initial two (0 and 1) is
characterized as the sum of the two past numbers
• But, as we move further on in the flow, the amount of calculation necessary to produce
successive terms becomes enormous
• This is because every computation ultimately has to depend on the base case to
calculate the values, since no intermediate values are recalled
• The following algorithm executes this definition; once more, notice the modesty of the
code that negates the underlying incapability.

Def fib(n):
if n < 2:
return n
else:
return fib(n-2) + fib(n-1)

• If we apply this to compute fibo(6)(which is 8), the algorithm starts by computing fibo
(4) + fibo (5)

59
CC103- Data Structures and Algorithms Worktext

• The algorithm then have to compute fibo (4) = fibo (2) + fibo (3), and lastly the first
term of that is fibo (2) = fibo (0) + fibo (1)= 0 + 1 = 1
• The whole procedure can be shown using a tree to represents the computation:

Fig. 3.3 the tree of calls for fibo(6).

• Counting the branches, it takes 25 calls to fibo () to compute fibo (6)


• The absolute number of additions needed to compute the nth number can be presented
to be fibo(n + 1) – 1
• With two calls per addition, and the primary call considered, the total number of calls
is 2 ∙ fibo(n + 1) – 1
• values of this are appeared in the following table:

Fig. 3.4 number of addition operations and number of recursive calls to compute fibonacci
numbers

• Notice that it takes right around 3 million calls to determine the 31st fibonacci
number
• This exponential development makes the algorithm inadmissible for anything besides
small values of n
• Fortunately there are adequate iterative algorithms that can be utilized unquestionably
more successfully

Backtracking

60
CC103- Data Structures and Algorithms Worktext

• Backtracking is a way to deal problem solving that utilizes a systematic search among
potential pathways to a solution
• As each path is analyzed, if it is determined the pathway isn’t suitable, it is disposed
and the algorithm comes back to the earlier branch with the goal that an alternate path
can be investigated
• Thus, the algorithm must have the capacity to come back to the past position, and
ensure that all pathways are inspected
• Backtracking is utilized in various applications, including compiling, optimization
problems and artificial intelligence
• Below is an example of searching all possible order of arrangements of a given set of
letters.
• When we pick a couple we apply backtracking to confirm if that exact pair has just
been made or not.
• If not already made, the pair is added to the result list else it is disregarded.

Def perm(list, s):


if list == 1:
return s
else:
return [ y + x
for y in perm (1, s)
for x in perm (list - 1, s)
]

Print(perm (1, ["a","b","c"]))


Print(perm (2, ["a","b","c"]))

• When the code above is performed, it produce the following outputs:

['a', 'b', 'c']


['aa', 'ab', 'ac', 'ba', 'bb', 'bc', 'ca', 'cb', 'cc']

When to use recursion?

▪ When a problem can be break down into pace.


▪ The result of one step can be used in a past step.
▪ There is a situation when you can stop breaking down the problem into pace (pace =
recursive call) and return to a past pace.

61
CC103- Data Structures and Algorithms Worktext

– Algorithm returns to former pace with a partial solution to the problem (back
tracking)
▪ All of the outcomes together solve the problem.

Consideration for alternatives to recursion:

▪ If a loop will answer the problem just as well

Drawbacks of recursion

• Method invocation can be costly


– Consuming up memory
– Consuming up time

Benefits of recursion

▪ Basic solution that’s neater (for some problems)


▪ Simpler to envision solutions (for some people and certain classes of problems – typically
require either: non-tail recursion to be implemented or some form of “backtracking”)

Common issues in recursion

▪ These three issues can brought a runtime error


– No base case
def sum (no): when it will stop?

return (no + sum (no - 1))

– No forwarding towards the base case


def summ (num):
The recursive case doesn’t
if (num == 1): make any forwarding to the
return 1: base (stopping) case
else

62
CC103- Data Structures and Algorithms Worktext

return (num + summ (num - 1))

– Using up too many assets (e.g., var declarations) for each function call
Def func(num):

print(num)

amlist = []

for i in range (0, 10000000, 1):

amlist.append("*")

num = num + 1

func (num)

Func (1)

Wrap-up

• The prior discussion has furnished us with some knowledge into the use of
recursion as a programming tool
• While there are no particular standards that require we use or avoid recursion in
any specific circumstance, we can develop some general guidelines
• Recursion is generally less useful than the iterative or loop equivalent
• but, in the event that the distinction in time of execution is fairly small, other
factors such as simplicity, clarity, and readability might be considered
• Recursion frequently is more devoted to the algorithm’s logic
• The task of converting recursive algorithms into their iterative counterparts can
be frequently hard to perform
• Like we observed with nontail recursion, we usually have to explicitly implement
stack taking care of to deal with the runtime stack processing incorporated into
the recursive form
• Again, this may require examination and judgment by the programmer / coder to
choose the best strategy

63
CC103- Data Structures and Algorithms Worktext

• The text propose a couple of situations where iterative adaptations are desirable
over recursive ones
• First, real-time systems, with their tough time requirements, benefit by the quicker
response of iterative code
• Another circumstance happens in programs that are repeatedly executed, for
example, compilers
• But, even these scenario might changed if the hardware or operating environment
of the algorithm supports processing that speeds the recursive algorithm (consider
a hardware supported stack)
• Sometimes the most ideal approach to choose which version to use relies simply
on coding both structures and testing them
• This is particularly evident in cases involving tail recursion, where the recursive
version might be quicker, and with non-tail recursion where use a stack can’t be
wiped out
• One place where recursion must be inspected carefully is when excessive, repeated
calculations happens to get results
• The discussion of the fibonacci sequence illustrated this concern
• Often, drawing a call tree like in figure 5.8 can be useful
• Trees with a enormous number of levels can threaten stack overflow problems
• On the other hand, shallow, “shaggy” trees may show an appropriate recursive
candidate, provided the number of repetitions is reasonable

64
CC103- Data Structures and Algorithms Worktext

References:

Drozdek ,adam (2013). Data structures and algorithms in c++ fourth edition

Necaise rance d. (2011). Data structures and algorithms using python

https://www.geeksforgeeks.org/types-of-recursions/

https://www.merriam-webster.com/dictionary/recursion

https://www.tutorialspoint.com/data_structures_algorithms/recursion_basics.htm

65
CC103- Data Structures and Algorithms Worktext

NAME: _____________________________ DATE: _____/_____/2020__


SECTION:_BSIT-_______________________SCORE:_______/30_______
LABORATORY EXERCISE # 1:
Direction: Send the image of your script/code and its output
Write a recursive method to output numbers from 1 to 10 in such a way that when number is
odd, add 1 and when number is even, subtract 1.
Output: 2 1 4 3 6 5 8 7 10 9

66
CC103- Data Structures and Algorithms Worktext

NAME: _____________________________ DATE: _____/_____/2020__


SECTION:_BSIT-_______________________SCORE:_______/30_______
LABORATORY EXERCISE # 2:
Direction: Send the image of your script/code and its output

Write a recursive method to output a reversed string input from the user.

67
CC103- Data Structures and Algorithms Worktext

NAME: _____________________________ DATE: _____/_____/2020__


SECTION:_BSIT-_______________________SCORE:_______/30_______
LABORATORY EXERCISE # 3:
Direction: Send the image of your script/code and its output

Write a program with a recursive method that will compute a factorial of a number given by a
user.

68
CC103- Data Structures and Algorithms Worktext

NAME: _____________________________ DATE: _____/_____/2020__


SECTION:_BSIT-_______________________SCORE:_______/30_______
LABORATORY EXERCISE # 4:
Direction: Send the image of your script/code and its output

Write a recursive method that computes and outputs the size of a linked list.

69
CC103- Data Structures and Algorithms Worktext

NAME: _____________________________ DATE: _____/_____/2020__


SECTION:_BSIT-_______________________SCORE:_______/30_______
LABORATORY EXERCISE # 5:
Direction: Send the image of your script/code and its output

Write a recursive method that uses only comparison, addition and subtraction to find the product
of two numbers from the user.

70
CC103- Data Structures and Algorithms Worktext

UNIT IV. BINARY TREE

Overview
This unit covers the discussion on trees such as binary tree, healp, binary search tree
.and balancing a tree
Learning Objectives

At the end of the lesson, you should be able to:


1. define Trees, Binary Trees, Heaps and Binary Search Trees
2. demonstrate skills in Implementing Binary Trees, searching a Binary Search
Tree and Balancing a Tree

Setting Up
1. What is binary tree?
2. What is heap?
3. How to implement binary search tree in Python?

What is a tree?
A tree is a structure of data that is displayed similar to the structure of the real tree. But the
tree structure in real life has its leaves (or nodes) and branches located in the top while the tree
described in this lesson is opposite, the construction is upside down the nodes (or leaves) and
branches are downward and the root of the tree is at the top. Trees can contain a large volume
of connected data which is somehow do not contain a cycle.

Shows the representation of the real tree and the tree in data structure

71
CC103- Data Structures and Algorithms Worktext

What is a Binary Tree

A binary tree represents structure in which every part of branches in the structure contains
two or more children which we call it as nodes, these nodes can be called right node or left
node, we can also call it as left child or right child, Binary tree supports binary search tree and
heap, A binary tree can be characterized in dissimilar methods with independent structures of
data such as list or dictionary and class for a node.

Figure 4.2 Shows the Binary Tree types

The code below will create of Binary Tree that look like these:

/ \

2 3

/ \ / \

4 5 6 7

class Node(object):

def __init__(self, value):

self.value = value

self.left = None

self.right = None

72
CC103- Data Structures and Algorithms Worktext

class BinaryPuno(object):

def __init__(self, root):

self.root = Node(root)

# Set up tree:

tree = BinaryPuno(1)

tree.root.left = Node(2)

tree.root.right = Node(3)

tree.root.left.left = Node(4)

tree.root.left.right = Node(5)

tree.root.right.left = Node(6)

tree.root.right.right = Node(7)

What is the Binary Search Tree?

The subtree in the left of a node contains just node with keys lesser than the node’s key at the
right. The subtree right of a node contains just node with keys more superior than the node’s
key in left. The subtree in right and left must have be another binary search tree

In our Example we will create a tree similar to the figure below:

12

/ \

10 11

/ \ \

13 14 20

/ \ /

15 16 25

73
CC103- Data Structures and Algorithms Worktext

To perform Binary Tree searching we will input a number and our program will determine
which of this number is the closest number in our tree we will create a function
“def closest_value” to perform these action, below is the entirety of our example

class NodeOfTree(object):

def __init__(self, x):

self.val = x

self.left = None

self.right = None

def closest_value(ugat, target):

w = ugat.val

bata= ugat.left if target < w else ugat.right

if not bata:

return w

s = closest_value(bata, target)

return min((w,s), key=lambda x: abs(target-x))

myTree = NodeOfTree(12)

myTree.left = NodeOfTree(10)

myTree.right = NodeOfTree(11)

myTree.left.left = NodeOfTree(13)

myTree.left.right = NodeOfTree(14)

myTree.left.right.left = NodeOfTree(15)

myTree.left.right.right = NodeOfTree(16)

myTree.right.right = NodeOfTree(20)

myTree.right.right.left = NodeOfTree(25)

print("number 17 will be entered")

74
CC103- Data Structures and Algorithms Worktext

result = closest_value(myTree, 17)

print("The closest number to the number 17 is ")

print(result)

Output

number 17 will be entered

The closest number to the number 17 is

20

What is Balanced Binary Search Tree?

Balanced Binary Search Tree is a binary search tree which can balance and stabilize itself,
while this tree can adjust and correct itself to be able to maintain a logarithmic low height
allowing it to speed up operations particularly the insertions and the deletions.

The code below performs Balanced Binary Search Tree it accomplishes the
displaying(printing) of the searched values of the tree, and then balances and orders it by
moving and jumping (Traversing) from one node to another, this is in the form of preorder or
prearrange, in order or in Arrange and post order or postArrange.

class Node(object):

def __init__(self, value):

self.value = value

self.left = None

self.right = None

class BinaryPuno(object):

def __init__(self, root):

self.root = Node(root)

def print_tree(self, traverse_type):

75
CC103- Data Structures and Algorithms Worktext

if traverse_type == "preArrange":

return self.print_in_preArrange(tree.root, "")

elif traverse_type == "inArrange":

return self.print_in_inArrange(tree.root, "")

elif traverse_type == "postArrange":

return self.print_in_postArrange(tree.root, "")

else:

print("traverse type " + str(traverse_type) + " is not supported.")

return False

def print_in_preArrange(self, start, traverse):

"""Root->Left->Right"""

if start:

traverse += (str(start.value) + "->")

traverse = self.print_in_preArrange(start.left, traverse)

traverse = self.print_in_preArrange(start.right, traverse)

return traverse

def print_in_inArrange(self, start, traverse):

"""Left->Root->Right"""

if start:

traverse = self.print_in_inArrange(start.left, traverse)

traverse += (str(start.value) + "->")

traverse = self.print_in_inArrange(start.right, traverse)

return traverse

def print_in_postArrange(self, start, traverse):

"""Left->Right->Root"""

if start:

traverse = self.print_in_postArrange(start.left, traverse)

76
CC103- Data Structures and Algorithms Worktext

traverse = self.print_in_postArrange(start.right, traverse)

traverse += (str(start.value) + "->")

return traverse

tree = BinaryPuno(1)

tree.root.left = Node(2)

tree.root.right = Node(3)

tree.root.left.left = Node(4)

tree.root.left.right = Node(5)

tree.root.right.left = Node(6)

tree.root.right.right = Node(7)

print("preArrange")

print(tree.print_tree("preArrange"))

print("inArrange")

print(tree.print_tree("inArrange"))

print("postArrange")

print(tree.print_tree("postArrange"))

Output:

preArrange

1->2->4->5->3->6->7->

inArrange

4->2->5->1->6->3->7->

postArrange

4->5->2->6->7->3->1->

77
CC103- Data Structures and Algorithms Worktext

What is a Heap?

The Heap is the information structure essentially used to present the priority line. to utilize
this to Python we will use and import the "heapq" module. The property of this information
structure in python is that each time the smallest of load component is popped at whatever
point components are pushed or popped, and the structure is kept up. The heap [0] component
likewise restores the littlest component each time.

The following are the operations of the Heap shown by the comments(#) and the code
below
NOTE: when you put the hashtag (#) in your code with any text on it the Python will just
ignore it

import heapq

#create a list of numbers

lis1 = [1,5,3,7,11,15]

#Organizing lis1 Array as Heaps or in other terms convert the created list into heap

heapq.heapify(lis1)

#print the created heaped list/NOTES the end= is use to connect the print item below

print("The following are the heaped list", end="")

print(list(lis1))

#Lets put a number 87 in the list by using headpush

heapq.heappush(lis1,87)

#Lets see if 87 is inserted

print("the heaped list below inserts the number 87 it did becase of heappush")

print(list(lis1))

#Lets put a number 100 in the list by using heappushpop

heapq.heappushpop(lis1,100)

78
CC103- Data Structures and Algorithms Worktext

#Lets see if 100 is inserted

print("the heaped list inserted the number 100 but pops the number 1 in the list")

print("it happens beacuse of heappushpop")

print(list(lis1))

######################################################

#Now lets make another list

lis2= [2,4,6,8,10,12]

#convert the created list2 into heap

heapq.heapify(lis2)

# Lets display the List2

print("The following are the 2nd heaped list ")

print(list(lis2))

#Lets put a number 200 in the list by using heapreplace

heapq.heapreplace(lis2,200)

# Lets display the List2

print("The following are the 2nd heaped list inserts the ")

print("200 in the center and removes the first number which is number 2")

print(list(lis2))

#Lets perform priorities we now


use nlargest method directly to print to display 3 largest numbers

print("Here is the list2 displaying the 3 largest numbers")

print(heapq.nlargest(3,lis2))

#Lets use nlargest method directly to print to display 3 largest numbers

print("Here is the list2 displaying the 2 smallest numbers")

print(heapq.nsmallest(3,lis

79
CC103- Data Structures and Algorithms Worktext

REFERENCES
https://pythonspot.com/python-tree/
https://www.geeksforgeeks.org/binarytree-module-in-python/
https://docs.python.org/2/library/heapq.html
https://gist.github.com/pavlin-policar/63e237b5e0b9c8dc1b47b0e4f780a88f
https://docs.python.org/2/library/heapq.html

80
CC103- Data Structures and Algorithms Worktext

NAME: _____________________________ DATE: _____/_____/2020__


SECTION:_BSIT-_______________________SCORE:_______/30_______
LABORATORY EXERCISE # 1:
Direction: Send the image of your script/code and its output

Write a python program that will create a binary tree shown below.

50

/ \
45 47
/ \ / \
32 34 35 38
/ \ / \ / \ / \
20 21 22 23 24 25 26 27
/ \ / \ /\ / \
11 12 13 14 16 17 18 19

81
CC103- Data Structures and Algorithms Worktext

NAME: _____________________________ DATE: _____/_____/2020__


SECTION:_BSIT-_______________________SCORE:_______/30_______
LABORATORY EXERCISE # 2:
Direction: Send the image of your script/code and its output

Create a Binary Tree use the answers in the multiplication table of 6 as the nodes of your
binary tree then display the number closest to number 15

82
CC103- Data Structures and Algorithms Worktext

NAME: _____________________________ DATE: _____/_____/2020__


SECTION:_BSIT-_______________________SCORE:_______/30_______
LABORATORY EXERCISE # 3:
Direction: Send the image of your script/code and its output

In the tree of the first question, create another program that will convert the numbers into Post
order Balanced Binary Search Tree.

83
CC103- Data Structures and Algorithms Worktext

NAME: _____________________________ DATE: _____/_____/2020__


SECTION:_BSIT-_______________________SCORE:_______/30_______
LABORATORY EXERCISE # 4:
Direction: Send the image of your script/code and its output

Create an array for these numbers 5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90 and


then convert it into heap, once converted heappush the numbers 90 and 100

84
CC103- Data Structures and Algorithms Worktext

NAME: _____________________________ DATE: _____/_____/2020__


SECTION:_BSIT-_______________________SCORE:_______/30_______
LABORATORY EXERCISE # 5:
Direction: Send the image of your script/code and its output

Create your own array at least 20 numbers convert it into heap and then display the smallest.

85
CC103- Data Structures and Algorithms Worktext

UNIT V. SORTING AND GRAPH


Overview
This unit designed to give you an idea of how to rearrange and position the data in proper
order. The data sorted by numerical, alphabetical, and other means. You will need to filter the
data before using the search algorithms to find a specific piece of data. Also, in this lesson,
you will get an idea of a graph, a set of objects called vertices, together with a collection of
pairwise connections, known as edges. Graphs have applications in many modeling fields,
including geography, transport, computer networks, and electrical engineering application

Learning Objectives:
At the end of this lesson, I can:
1. Develop and implement the practical sorting algorithms; and
2. Use breadth-first, depth-first, and best-first search to introduce data structures for
graphs, and search approaches.

Setting Up
1. What are the different sorting algorithim?
2. What is Decision Tree?
3. What is Graphs Data Structure?

Learning Proper
Sorting
Sorting a process of a collection of items arranged or ordered each item and its successor
satisfies a prescribed relation. The objects may be fundamental values like integers and reals,
or more complex types like student records or dictionary entries. In either case, the items are
ordered based on the value of a sort key. The key is the value itself when sorting simple types,
or when sorting complex models, and it can be a Particular component or a
component combination. We encounter many examples of day-to-day sorting in life. Consider
the listings of a phone book, the definition in a dictionary, or the terms in an index,
all organized in alphabetic order to make it much easier to find an entry.
There are many different algorithms for sorting the data and among few popular ones are
Bubble Sort, Selection Sort and Insertion Sort

Bubble Sort
A simple solution to the problem of sorting is the bubble sort algorithm, which rearranges
the values several times by iterating over the list, allowing more massive amounts to bubble to
the top or end of the list. To illustrate how the algorithm of bubble sorting works,
suppose we have four play cards that we want to order from the smallest to the most
significant face value. As shown here, we start by laying the cards face up on a table:

86
CC103- Data Structures and Algorithms Worktext

The algorithm involves numerous card transfers, each pass starting with the first card and
ending one card earlier than the previous iteration. The cards in both the first and second
positions compared during each move. If the first one is greater than the latter, then the two
cards will be swapped.

Next, they compare the cards in positions two and three. When the first is more significant
than the second, otherwise, they will be swapped. Otherwise, we'll leave it as it was.

For each successive pair of cards, this process continues until the card with the highest face
value positioned at the end.

87
CC103- Data Structures and Algorithms Worktext

The next two passes over the cards shown below. In the second move, the card put in the
next-to-last slot with the second-largest face value. The first two cards will be positioned
correctly on the third and final pass.

(Pass 2) Repeat the process on the first three cards. Compare the 5
and 8. Since five is less than 8, leave them as is.

Compare the 8 and 3. Since eight is more significant than 3, swap


the two cards.

The second-largest card (8) is now in its ordered position.

(Pass 3) Repeat the process on the first two cards. Compare the 5 and 3. Since five is more
significant than 3, swap the two cards.

After swapping the two cards, all of the cards are now in their proper order, from smallest to
largest.

Listing 1. Implementation of the bubble sort algorithm.

# Sorts a sequence in ascending order using the bubble sort algorithm. 1


def bubbleSort( theSeq ): 2
n = len( theSeq ) 3

88
CC103- Data Structures and Algorithms Worktext

# Perform n-1 bubble operations on the sequence 4


for i in range( n - 1 ) : 5
# Bubble the largest item to the end. 6
for j in range( i + n - 1 ) : 7
if theSeq[j] > theSeq[j + 1] : # swap the j and j+1 items. 8
tmp = theSeq[j] 9
theSeq[j] = theSeq[j + 1] 10
theSeq[j + 1] = tmp 11

Selection Sort
A second sorting algorithm, which builds on the bubble sort and works in a manner close to
what an individual would use to sort a list of values, is called the kind of selection. We can
use the play cards set again to demonstrate the algorithm and start by placing five face-up
cards on a table to be sorted in ascending order.

Instead of swapping the cards, we did the bubble sort; we'll scan through the cards and select
the smallest of those on the table and put it in our hand. We identify the three as the lowest,
for our set of cards:

We take the three and put it in our hand, leaving the rest of the cards on the table:

Cards on the Table Our Hand

89
CC103- Data Structures and Algorithms Worktext

The process repeated, and we mark the five as the next smallest face value:
We pick up the five and move it to the proper sorted location on the right side as there are no
cards left on the table with a lower face value.

Card on the table Our Hand

The process continued until all the cards are picked up and placed in our hands from smallest
to most significant in the correct sorted order. The method we've used to sort the set of
five cards is similar to the selection sort algorithm approach. But the algorithm preserves both
the sorted and unsorted values within the same sequence-structure when
implementing insertion sort in code.

The selection sort, which improves on the kind of bubble, makes several passes over the
series, but unlike the bubble sort, after each pass, it only makes one swap. The selection sort
algorithm to implemented given in Listing 3.

the result pick up the last pick up the next Pick up the next
our hand
card (9) smallest card (8) smallest card (6)

90
CC103- Data Structures and Algorithms Worktext

Listing 3. Implementation of the selection sort algorithm.

# Sorts a sequence in ascending order using the selection sort algorithm. 1


def selectionSort( theSeq ): 2
n = len( theSeq ) 3
for i in range( n - 1 ): 4
# Assume the ith element is the smallest. 5
smallNdx = i 6
# Determine if any other element contains a smaller value. 7
for j in range( i + 1, n ): 8
if theSeq[j] < theSeq[smallNdx] : 9
smallNdx = j 10
11
# Swap the with value and smallNdx value only if the smallest value is 12
# not already in its proper position. Some implementations omit testing 13
# the condition and always swap the two values. 14
if smallNdx != i : 15
tmp = theSeq[i] 16
theSeq[i] = theSeq[smallNdx] 17
theSeq[smallNdx] = tmp 18

Insertion Sort

The insertion sort is another commonly studied sorting algorithm. Continuing with our
analogy of classifying a set of play cards to illustrate the sorting algorithms, consider five
cards that are stacked face up in a deck:

The deck

We take the top card from the deck and place it in our hand:

91
CC103- Data Structures and Algorithms Worktext

the deck our hand

Since this is the first card, there is no decision to make about its position. We pick up the
top card from the deck again and compare it with the card already in our hand, insert it in
its proper sorted position:

the our hand


deck

The process repeated after we have placed the eight into our hands. We
pick up the five this time and find its position in our hand and insert it in the correct place:

the our hand


deck

This process continues, one card at a time, until all of the cards are withdrawn from the table
and put in their correct sorted location in our hand.

92
CC103- Data Structures and Algorithms Worktext

pick up the pick up the next


the resulting han
last card (6) card on top (9)

The insertion sort holds a selection of various items and a collection of things to be sorted.
An analogy of playing card, deck, represents the collection to be sorted, and the cards in our
hand are the ones already sorted. The algorithm maintains both the sorted and unsorted
collections within the same sequence-structure when implementing insertion sort in a system.
The algorithm holds the list of sorted values at the front of the sequence and selects
the next unsorted value from the first one that still positioned. Place the next element, and
a search performed to find the correct spot within the sequence of sorted values. The slot has
to open after the right location identified by moving the items down one position—
Python implementation of the sort algorithm for insertion given in Listing 4.

Listing 4. Implementation of the insertion sort algorithm.

# Sorts a sequence in ascending order using the insertion sort algorithm. 1


def insertionSort( theSeq ): 2
n = len( theSeq ) 3
# Starts with the first item as the only sorted entry. 4
for i in range( 1, n ) : 5
# Save the value to be positioned. 6
value = theSeq[i] 7
# Find the position where value fits in the ordered part of the list. 8
pos = i 9
while pos > 0 and value < theSeq[pos - 1] : 10
# Shift the items to the right during the search. 11
theSeq[pos] = theSeq[pos - 1] 12
pos -= 1 13
14

93
CC103- Data Structures and Algorithms Worktext

# Put the saved value into the open slot. 15


the Seq[pos] = value 16

Decision Trees
Another way to get the meaning interpreted is by using a decision tree. A decision tree
models a series of decisions or choices in which selections made at each point in stages from
between several alternatives. The decision steps are depicted as nodes, while the divisions
display the conclusions that can draw at each location. The dreaded automated telephone
menu is a common usage of the decision tree you should have to familiarize.
Once the computerized system answers your call, it begins at the root of the tree and
gives multiple options you can choose. You presented with a sub-menu after making your
initial selection, from which you will make a second selection, and then probably a third
selection, and so on.
The automated system's presentation of the menu options are the stages of the decision
and represented as nodes in the tree. Branches from those nodes indicate the menu choices
from which you can pick at each level. You may use the same concept to decode a series of
Morse code. Although every sequence of the system is unique, they have no particular
prefixes. The set for the letters R and S, for example, start with a dot. We need to look at more
of the series to differentiate between the two.
The second symbol in the R series is a dash, while the S series has a dot. It is not until the
third part of the series that we can separate the R from the S altogether. To make the situation
even more complicated, letter A is represented by the set of two (.-) symbols which is the
prefix of sequence R. A subset of the International Morse Code provided here:

P .--. K -.- F ..-. A .-


U ..-
V ...- Q --.- L .-.. G --. B -...
W .-- R .-. M -- H .... C -.-.
X -..- S ... N -. I .. D -..
Y -.-- T- O --- J .--- E.
Z --.
We can build a decision tree that models the Morse code to help decode a sequence, as
illustrated in figure 1. The nodes represent the letters and symbols that form part of Morse
code, and the branches include either a dot (left branch) or dash (right branch) selection.
The root node is empty, and when decoding a sequence, it indicates the starting position.
We start at the root to decode a given course and follow the left or right branch to the next
node, depending on the current symbol in our sequence.
To decode (.-.), for example, we start at the root and analyze the first symbol. Since the first
symbol is a dot, we must follow the left branch to the next node, leading us to the E node. We
evaluate the next character in the series each time we pass on to a node. Since the second
symbol is a dash, we take the right branch from Node E to the Node A. We take the left
branch from that node since the third symbol is a dot. Brings us to Node R. When all

94
CC103- Data Structures and Algorithms Worktext

the symbols in the sequence have consumed, the last node visited will contain the character
corresponding to the sequence given. In this case, the letter R represented by the series (.-.)

Morse code as modeled as binary tree decision

. Decoding the Morse code sequence (.-.)

What if we seek to decode an incorrect sequence? Try decoding the sequence (-.- ..,) for
example. Will take us from the root node to node T, from left to node N, from right to node K,
and from left to node C. The last symbol in the sequence is a dot which indicates that we are
supposed to take the left branch at node C, but as illustrated in Figure 3, it has no left child.
If you encounter a null child relation during tree navigation, we know the sequence is invalid.

Decoding an invalid Morse Code sequence (-.-..).

95
CC103- Data Structures and Algorithms Worktext

Define: Morse code Tree ADT


A Morse code tree is a decision tree containing the letters of the alphabet in its nodes and
other special symbols. The nodes arranged according to the sequence of the Morse code,
which corresponds to each letter and symbol.

✓ MorseCodeTree(): Builds the Morse Code tree consisting of the letters of the alphabet and
other special symbols.
✓ Translate ( codeSeq ): Translates and returns the given Morse Code sequence to its
equivalent character if the series is valid or returns None otherwise.

Graph
A graph is a pictorial representation of a set of objects, where links connect some pairs of
objects. The interconnected objects represented by dots called vertices, and the edges are
called the links that connect the vertices. Formally, a graph is a pair of sets (V, E), where V is
the set of vertices and E is the set of edges, connecting the vertical pairs. Find the following
graph −
In this graph,

V = {a, b, c, d, e}
cd, de} E = {ab, ac, bd,
Graph Data Structure
The data structure can represent mathematical graphs. Use an array of vertices and a two-
dimensional array of edges; we can represent a graph. Before we move on, let's get acquainted
with some critical words –
Vertex. Within the graph, each node was identified as a vertex. The labeled circle
represents vertices in the following example. And the vertices are A to G. We can reflect
them with an array, as hown in the image below. You may define A by index 0 here. You may
use index 1 to classify B, and so on.
Edge. Edge illustrates a path or line between two vertices. In the following example, sides
are represented by lines A to B, B to C, and so on. We can use a two-dimensional array
to serve a collection, as seen in the image below. Here AB may be represented as 1 in row 0,
column 1, BC as 1 in row 1, column 2, and so forth, with other combinations as 0.
Adjacency. Two nodes or vertices are adjacent to each other if an edge connects them. In
the example below, B is adjacent to A, C is adjacent to B, and so on.

Path – Path is a series of edges between the two vertices. In the example below, ABCD
describes away from A to D.

96
CC103- Data Structures and Algorithms Worktext

Types of Graphs
Various graph models depend on the number of vertices, the number of edges, the
interconnectivity, and the overall structure. In this lesson, we'll just cover a few essential
types of graphs.

Non-Directed Graph
A non-directed graph contains edges, but the edges not directed ones

Example

In this graph, 'a', 'b', 'c', 'd', 'e', 'f', 'g' are the vertices, and 'ab', 'bc', 'cd',
'da', 'ag', 'gf', 'ef' are the edges of the graph. Since it is a non-directed
graph, the edges' ab' and 'ba' are same. Similarly other edges also
considered in the same way.

Directed Graph
In a directed graph, each edge has a direction.

97
CC103- Data Structures and Algorithms Worktext

Example
We have seven vertices in the graph above, 'a,' 'b,' 'c,' 'd,' 'e,' 'f' and
'g,' nd eight edges, 'ab,' 'cb,' 'dc,' 'ad,' 'ec,' 'fe,' 'gf' and 'ga.' Since it is
a directed graph, each edge bears an arrow mark showing its path.
Note that 'ab' is different from 'ba' in a Directed Graph.

Graph Representations
The graph data structure represented using the following representations
1. Adjacency Matrix
2. Adjacency List

1. Adjacency Matrix

In this representation, the graph can represent using a matrix of the total number of
vertices by the total number of vertices; it implies that a 4-vertex figure can represent using a
4X4-size array. Rows and columns in this matrix also represent vertices. The model is either 1
or 0 filled in. Here, 1 represents an edge between row vertex and column vertex, and 0
represents that there is no edge between row vertex and column vertex.
Adjacency Matrix: let G = (V, E) with n vertices, n ≥ 1. The adjacency matrix of G is a 2-
dimensional n x n matrix, A, A(i, j) = 1 iff (vi , vj) E(G) (vi , vj for a diagraph), A(i, j) = 0
otherwise.

Example: for directed

For an undirected graph, the adjacency matrix is symmetric; the adjacency matrix for a
digraph does not need to be symmetric.

For a Directed graph

98
CC103- Data Structures and Algorithms Worktext

Adjacency Matrix merits:


Determining the relation of vertices from the adjacency matrix is easy.
The degree of a vertex is

For a digraph, out-degree is the row sum, while in degree is the sum of the column.

The space required to represent a graph using matrix adjacency is n 2 bits. Adjacency matrices
should expect at least O(n2) time to identify the edges in a figure.
2. Adjacency List

Each vertex of a graph in this representation contains a list of its adjacent vertices—the
adjacency matrix n rows represented as n chains. The nodes in the chain, which I depict,
are adjacent to the vertex i.
It can be depicted in two ways. An array is used in one form to store n vertices, and the
chain used to store its adjacencies. To give an example:

So we can use the adjacency list in O(1) time for any vertex. Adjlist[i] is a guide to the first
node for vertex I in the adjacency list.

Graph traversal

Since graphs do not always have an ordered structure, it may be more challenging to traverse
a graph. Traversal usually means keeping track of which nodes or vertices have already
visited and which ones do not. A standard tactic is to follow a direction until an impasse
reached, then back up until there is an alternate route. Also, we can travel iteratively from
one node to another to traverse the entire or part of the graph.

99
CC103- Data Structures and Algorithms Worktext

Breadth-first search
The breadth-first search algorithm begins at a node, selects that node or vertex as its root
node, and visits the neighboring nodes, after which it explores adjacent in the next graph step.
Find the diagram below as a graph:

The diagram shows an example of an undirected graph. We tend to use this kind of figure
to help promote clarification without being too repetitive.

For the graph the adjacency list is as follows:


graph = dict()
graph['A'] = ['B', 'G', 'D']
graph['B'] = ['A', 'F', 'E']
graph['C'] = ['F', 'H']
graph['D'] = ['F', 'A']
graph['E'] = ['B', 'G']
graph['F'] = ['B', 'D', 'C']
graph['G'] = ['A', 'E']
graph['H'] = ['C']

We will use a queue to try to traverse this graph breadth-first. The algorithm creates a list
to store the visited nodes as the traversal process proceeds. From Node A, we will begin our
traversal.

Node A is filed in aqueue and added to the list of nodes visited. We then use a while loop to
effect graph traversal. Node A dequeued in the while sequence. The corresponding, unvisited
nodes B, G, and D are sorted and queued in alphabetic order. The queue now contains
the nodes B, D, and G. These nodes will also be added to the list of nodes visited.
Starting another iteration of while looping this stage because the queue isn't empty, does not
mean the traversal is over.

100
CC103- Data Structures and Algorithms Worktext

Node B dequeued. Node A has already visited out of its adjacent nodes A, F, and E. Then
we just enqueuer in alphabetical order the nodes E and F. Instead, nodes E and F are added
to the list of nodes visited.
At this position, our queue now contains the following nodes: D, G, E, and F. The list of
nodes visited includes: A, B, D, G, E, F.
Node D dequeued, but all its neighboring nodes were visited, so we only dequeued it.
The next node on the queue front is G. We dequeue node G, but we also find out that all of its
neighboring nodes were visited as they are in the list of nodes visited. Node G dequeued,
too. We dequeue node E, as well as all of its nodes, were visited. Already the one node in the
queue is node F.
Node F dequeued, and we know that only node C not visited from its neighboring nodes
B, D, and C. Afterwards, we enqueue node C and add it to the list of nodes visited. Node C
dequeued. Node C has neighboring nodes F and H, but F has visited already, leaving node
H. Node H is enqueued and added to the list of nodes you have visited.
Eventually, the last iteration of the while loop will trigger dequeued of node H. It has
already passed the only neighboring node C. The loop stops until the queue is empty.
The output in the diagram to traverse the graph is A, B, D, G, E, F, C, H.
In the worst-case scenario, every vertex or node and edge must traversed, so the
algorithm's time complexity is O(|V| + |E|), where |V| is the number of vertices or nodes, and
|E| is the number of edges in the graph.

Depth-first search
This algorithm, as the name suggests, traverses the depth of any particular path in the
graph before passing its breadth. As such, child's nodes are first visited before sibling nodes.
This runs on finite graphs and needs the use of a stack to hold the algorithm state:

def depth_first_search(graph, root):


visited_vertices = list()
graph_stack = list()

graph_stack.append(root)
node = root

The algorithm begins by building a list in which to store the nodes visited. The stack variable
graph_stack used to support the traversal process. We use a standard Python list as
a stack, for the sake of consistency.

The starting node, called root, is passed by the adjacency matrix graph, root is inserted into
the stack. Node = root holds first stack node:

101
CC103- Data Structures and Algorithms Worktext

while len(graph_stack) > 0:

if node not in visited_vertices:


visited_vertices.append(node)
adj_nodes = graph[node]

if set(adj_nodes).issubset(set(visited_vertices)):
graph_stack.pop()
if len(graph_stack) > 0:
node = graph_stack[-1]
Continue
else:
remaining_elements =
set(adj_nodes).difference(set(visited_vertices))

first_adj_node = sorted(remaining_elements)[0]
graph_stack.append(first_adj_node)
node = first_adj_node
return visited_vertices

The while loop body will be executed for as long as the stack is not empty. If the
node does not appear in the list of nodes visited, we must add it. The adj_nodes = graph
[node] collect all adjacent nodes to a node. All adjacent nodes have visited, we will pop the
node from the stack and set graph_stack[-1] to a node. he top node on the stack is
graph_stack[-1]. The continued argument moves back to the start of the test condition of the
while loop.
On the other hand, if not all of the adjacent nodes have been visited, the nodes to be
visited can obtain by finding the difference between
the adj_nodes and the visited vertices with the remaining_elements = set(adj nodes)
statement. difference (set(visited_ vertices)) .

The first element is allocated to the first adj_node within the sorted (remaining_elements)
and moves on the stack. We then point to the node at the top of the pile. When there is a
while loop, we'll return the visited_vertices. When dry-running, the algorithm will prove very
useful. Here is a diagram:

102
CC103- Data Structures and Algorithms Worktext

The list of adjacency of this graph is given as follows:


graph = dict()
graph['A'] = ['B', 'S']
graph['B'] = ['A']
graph['S'] = ['A','G','C']
graph['D'] = ['C']
graph['G'] = ['S','F','H']
graph['H'] = ['G','E']
graph['E'] = ['C','H']
graph['F'] = ['C','G']
graph['C'] = ['D','S','E','F']

Node A is selected as our start node. Node A will be moved onto the stack and added to the
list of visited_vertices.
We are marking it as having been visited in doing so. The graph_stack stack is implemented
in a simple Python array. Our stack has A as its primary item now. We analyze opposite
nodes B and S of the node A. To check if all of A's adjacent nodes were
visited, we use if statement:

if set(adj_nodes).issubset(set(visited_vertices)):
graph_stack.pop()
if len(graph_stack) > 0:
node = graph_stack[-1]
continue

If all of the nodes are visited, we'll pop the stack top. If the stack graph_stack is not empty,
then we allocate the node to the node at the top of the stack and start another execution of the
while loop structure. The set(adj_nodes.issubset(set(visited_vertices)) statement will evaluate
True if all the nodes in adj_nodes are a subset of visited_vertices. When the argument
fails, it implies that those nodes are yet to be visited. We get the list of nodes with
remaining elements = set(adj_nodes).difference(set(visited_vertices)).

Nodes B and S will be placed in remaining elements from the diagram. In alphabetical order
we'll access the list:
first_adj_node = sorted(remaining_elements)[0]

103
CC103- Data Structures and Algorithms Worktext

graph_stack.append(first_adj_node)
node = first_adj_node
We sort out the remaining_elements and return first_adj_node to the first; this returns B.
By adding it to the graph_stack, we move node B onto the stack. By assigning it to a node, we
prepare node B for entry.
We add node B to the list of visited nodes on the next iteration of the while loop. We
discover that the only node adjacent to B, namely A, was already visited. Since all of B's
nearby nodes were visited, we pop it off the stack, leaving node A as the only entity on the
stack. We are returning to node A and analyzing whether any of its adjacent nodes were
visited. Now, node A has S as the only node unvisited. We move S to the stack and then start
the whole cycle again.

The traversal output is A-B-S-C-D-E-H-G-F.

104
CC103- Data Structures and Algorithms Worktext

References

1. http://home.ustc.edu.cn/~huang83/ds/Data%20Structures%20and%20Algorithms%20
Using%20Python.pdf

2. https://www.tutorialspoint.com/python_data_structure/python_graph_algorithms.htm

3. https://jeffe.cs.illinois.edu/teaching/algorithms/book/05-graphs.pdf

4. https://learn.saylor.org/course/view.php?id=39&sectionid=410

5. https://www.geeksforgeeks.org/graph-data-structure-and-algorithms/

105
CC103- Data Structures and Algorithms Worktext

NAME: _____________________________________________ DATE:


_____/_____/2020__
SECTION:_BSIT-______________ SCORE:_______/30_________
EXERCISE # 1:

Direction: Create an algorithm for the following key


1. Given the following list of keys (80, 7, 24, 16, 43, 91, 35, 2, 19, 72), show the contents
of the array after each iteration of the outer loop for the indicated algorithm when
sorting in ascending order.

(a) bubble sort

(b) selection sort

(c) insertion sort

106
CC103- Data Structures and Algorithms Worktext

NAME: ____________________________________________ DATE:


_____/_____/2020__
SECTION:_BSIT-______________________ SCORE:_______/30_________
EXERCISE # 2:

Direction: Create an algorithm for the the following problem

1. Create a linked list version of the indicated algorithm.

(a) bubble sort

(b) selection sort

107
CC103- Data Structures and Algorithms Worktext

NAME: _______________________________________________DATE:
_____/_____/2020__
SECTION:_BSIT-____________________
SCORE:_______/30_________
EXERCISE # 3:

Direction: Write a sorting algorithm for the following.


1. Write a program to read a list of grade point averages (0.0 – 4.0) from a text file and
sort them in descending order. Select the most efficient sorting algorithm for your
program.

108
CC103- Data Structures and Algorithms Worktext

NAME: _______________________________________________DATE:
_____/_____/2020__
SECTION:_BSIT-_____________________
SCORE:_______/30_________
EXERCISE # 4:

Direction: Read each question carefully and provide the answer on the space provided.

1. Draw a simple undirected graph G that has 12 vertices, 18 edges, and three connected
components.

2. If G is a simple undirected graph with 12 vertices and three connected components,


what is the most significant number of edges it might have?

109
CC103- Data Structures and Algorithms Worktext

NAME: ________________________________________________DATE:
_____/_____/2020__
SECTION:_BSIT-_______________________
SCORE:_______/30_________
EXERCISE #5:

Direction: Read each statement carefully and ENCIRCLE the LETTER of the correct answer.

1. Given a rooted tree, one desires to find the shortest path from the root to a given
node.Which algorithm would one use to find this shortest path ?

a. DFS
b. BFS
c. Either BFS or DFS
d. None of the above

2. Consider an undirected graph G. Let T be a depth first search traversal tree. Let u be a
vertex and v be the first unvisited vertex after visiting u. Which of the following
statements is always true ?

a. (u,v) must be an edge in G


b. (u,v) must be an edge and v is a descendant of u in T
c. if (u,v) is not an edge, u and v have the same parent.
d. if (u,v) is not an edge, then u is a leaf.

3. Consider a graph G. Let T be a BFS tree with root r. Let d(u,v) denote the length of the
shortest path between the nodes u and v. If v is visited before u in the breadth first search
traversal, which of the following statements is true ?

a. d(r,v) > d(r,u)


b. d(r,v) = d(r,u)
c. d(r,v) < d(r,u)
d. insufficient information to comment on d(r,v) and d(r,u)

4. Traversal of a graph is different than tree because.

a. There can be a loop in the graph


b. DFS on a graph uses stack, while inorder traversal is recursive
c. Both A and C
d. None of the above

5. Consider the following graph. If we run breadth first search on this graph starting at any
vertex, which one of the following is a possible order for visiting the nodes?

a. MNOPQR

110
CC103- Data Structures and Algorithms Worktext

b. NQMPOR
c. QMNPRO
d. QMNPOR

111

You might also like