In this article, the complete understanding of **data structures** and algorithms of the Python programming language is explained with practical examples. The understanding of Python **data structures** and algorithms is used for data scientists to design and solve machine learning models easily and effectively.

**Data Structures** of Python deal with the storage of data in the memory when programming is processing them. Python Algorithms of Python is a detailed set of instructions to help data processing for a specific purpose.

Python algorithms are utilizing **data structures** for performing particular problems in data analysis. The **data structures** and algorithm knowledge are important to work on real-world data problems for bringing up accurate solutions.

Explore the detailed data science course syllabus in our Data Science Training Course in Chennai at Softlogic’s.

**Data Structures in Python**

Python **Data Structures** are used to organize and store data and they explain the relationship between data and various operations that are to be performed on the data. **Data Structures** will be categorized into two types namely Primitive and Non-Primitive.

The primitive data types are integers, float, strings, and Boolean, and the non-primitive data types are lists, tuples, arrays, dictionaries, sets, and files. Some of the data types are built-in while others are user-defined.

**Primitive Data Structures**

Primitive **Data Structures** are basic things in Python that contain simple data values to serve as the building blocks for manipulating data. Following are the four major primitive types of variables in Python.

Data Type | Description | Example |

Integer | To represent numerical data that are positive or negative whole numbers without decimal points | -4, 2, 18. |

Float | To represent real numbers or rational numbers that contain a decimal point. In Python, there is no need to state the type of variable explicitly as the object stores are mutable. | 4.9, 7.23. |

String | To represent alphanumeric characters that include a series of characters within a pair of single or double-quotes. The strings can be concatenated using the ‘+’ operation. | ‘One’, ‘Five’ |

Boolean | To represent conditional and comparison expressions. | TRUE or FALSE |

**Built-in Non-Primitive Data Structures**

Non-Primitive Data Types are used not only to store values but used to store a collection of values in various formats in a single variable name. Some of the popular non-primitive data types are in-built in the Python programming language.

**List**

A list contains a mix of various data types and the list is mutable and ordered. This list is defined with square brackets and holds data that is separated by a comma.

**Syntax for the List**

List1 = [1, “hello”, “python”, True]

List2 = list(range(8))

print(List1)

print(List2)

print(List[0]) #index value

print(List[1:3]) # list slicing that send values from index values 1 to 3

print(List[-2]) # negative indexing

**Sample_List.py**

- months = [‘January’, ‘February’, ‘March’, ‘April’, ‘May’, ‘June’, ‘July’, ‘August’, ‘September’, ‘October’, ‘November’, ‘December’]
- print(months[0]) # displays the element which is in the index 0.
- print(months[0:6]) #displays the elements from index 0 to 5
- months[0] = ‘NewYear’ #replaces the value of index 0 with the word NewYear.
- print(months)

**Output**

January

[‘January’, ‘February’, ‘March’, ‘April’, ‘May’, ‘June’]

[‘NewYear’, ‘February’, ‘March’, ‘April’, ‘May’, ‘June’, ‘July’, ‘August’, ‘September’, ‘October’, ‘November’, ‘December’]

**Tuples**

Tuples are similar to list but they are immutable ordered sequences of elements and the tuples are defined within parentheses instead of square brackets. The immutable denotes that once an element has been defined in a tuple, it can’t be deleted, edited, or reassigned and it ensures that the defined values of the data structure are not manipulated or overridden.

**Syntax for Tuple**

Tup = (1,2,3,4,5)

print(Tup)

print(Tup[2]) #indexing to grab the value

**Sample_Tuple.py**

- length, width, height = 8, 4, 1 #multiple variables can be assigned in one shot
- print (“The dimensions are {} x {} x {}”. format (length, width, height))

**Output**

The dimensions are 8 x 4 x 1

**Set**

Set is the mutable and unordered collection of unique elements that can allow users to remove duplicates quickly from a list.

**Sample_Set.py**

- numbers = [1, 6, 3, 1, 2, 5, 4]
- unique_numbers = set(numbers)
- Print(unique_numbers)
- players = {‘Rohit’, ‘Bumrah’, ‘Hardhik’, ‘Kohli’, ‘Raina’, ‘Dhoni’, ‘Dawan’}
- print(‘Chahal’ in players) # check if there is Chahal in the set players
- players.add(‘Chahal’)
- print(players.pop()) #remove the last item

**Output**

{1, 2, 3, 4, 5, 6}

False

Dawan

**Dictionary**

Dictionary is a mutable and unordered data structure that allows storing a pair of items like keys and values. It is possible to include containers into other containers to create compound **data structures**.

Dictionaries contain key-value pairs in that, the key identifies an item, and the value stores the value of the item. The key and the value will be separated by a colon. The items will be separated by commas, and the entire thing closed within curly brackets.

**Syntax for Dictionary **

dict_1 = {“key1”:”value1”, “key2”:”value2”, “key3”:”value”, “key4”:”value4”}

print(dict_1)

**Sample_Dict.py**

- fruits = {‘always’: {“Banana”: “Yellow in Color”,
- “Apple”: “Red in Color”,
- “Orange”:”Orange in Color”},
- ‘seasonal’: {“Avacado”: Green in Color”,
- {“Grapes”:”Purple in Color”,
- {“Strawberry”: “Red in Color”}}
- print(fruits[“always”][“Orange”]) #value of the key orange
- print(fruits[“seasonal”][“Strawberry”}) # value of the key Strawberry

**Output**

Orange in Color

Red in Color

In python, there is no built-in concept for using Arrays but it can be imported from the NumPy Package before initializing them. Arrays are similar to List with one difference that the arrays are collections of homogeneous or similar types of elements but the list can be both homogeneous and heterogeneous. Learn more about libraries of Python in our Python Course in Chennai at Softlogic.

**User-defined Data Structures**

There are user-defined **data structures** in Python programming language such as Queues, Stack, and Tree. If you are having fundamental knowledge in classes and functions, these concepts will be understood easily.

**Stack with Arrays**

The stack is the linear data structure that the elements are arranged sequentially and it follows the LIFO (Last in First out) mechanism. The last element will be removed as the first and the operations are,

Push is for inserting an element into the stack

Pop is for deleting an element from the stack

There are two conditions to check such as the overflow condition that occurs when we try to give one more element into a stack which is already having maximum elements and the underflow elements that occurs when we try to delete an element from an empty stack.

**Sample_Stack.py**

- class samplestack
- def _init_(self):
- self.data = []
- def length(self): #length of the list
- return len(self.data)
- def is_full(self): #check if the stack is full or not
- If len(self.data) = = 4:
- return True
- else:
- return False
- def push(self, element): #insert a new element
- If len(self.data) < 4:
- self.data.append(element)
- else:
- return “overflow”
- def pop(self): #remove the last element from a stack
- If len(self.data) = = 0;
- return “underflow”
- else:
- return self.data.pop()
- a = samplestack() #creating an object for samplestack
- a.push(10) # inserting elements one by one
- a.push(20)
- a.push(30)
- a.push(40)
- print(a.length())
- print(a.is_full())
- print(a.data)
- print(a.push(31)) #inserting one more element in a stack and the output will be overflow
- print(a.pop())
- print(a.pop())
- print(a.pop())
- print(a.pop())
- print(a.pop()) #trying to delete an element from an empty stack and the result will be underflow

**Output**

4

True

[10, 20, 30, 40]

Overflow

40

30

20

10

Underflow

**Queue with Arrays**

The Queue is the linear data structure where the elements are in a sequential manner and it follows the FIFO (First In First Out) mechanism. The Queue has two major ends such as the front that points to starting element and the rear that points to the last element. Queue has two operations such as enque and deque.

The enque is for inserting an element into the queue at the rear end and the dequeue for removing an element from the queue and it will be done at the front. The Queue has two conditions like in Stack such as overflow that insert an element into a queue that is full and the underflow is to delete from the empty queue.

**Sample_Queue.py**

- class SampleQueue:
- def _init_(self):
- self.data = []
- def length(self):
- return len(self.data)
- def enqueue (self, element): # put the element in the queue
- if len(self.data) < 5:
- return self.data.append(element)
- else:
- return “overflow”
- def deque(self): #removing the first element of the queue
- if len(self.data) = = 0:
- return “underflow”
- else:
- self.data.pop(0)
- b = samplequeue()
- b.enque(2)
- b.enque(3)
- b.enque(4)
- print(b.data)
- b.deque ()
- print(b.data)

**Output**

[2, 3, 4]

[3, 4]

**Tree (General Tree)**

Trees are used to define a hierarchy that starts from the root node and goes further down to the last nodes known as child nodes. Here, we are going to explain the binary tree data structure that each node has at least two children that are referred to as the left and right child. The representation of the binary tree is as follows

**Sample_Tree.py**

- class Node:
- def _init_(self, letter):
- self.childleft = None
- self.childright = None
- self.nodedata = letter
- root = Node(‘A’) # creating the nodes for the binary tree
- root.childleft = Node (‘B’)
- root.childright = Node(‘C’)
- root.childleft.childleft = Node(‘D’)
- root.childleft.childright = Node(‘E’)
- root.childright.childleft = Node(‘F’)

**Algorithms in Python**

Algorithms are used by ancient Egyptians to solve any real-time problems and they taught this approach to Greek. The word algorithm is derived from the Persian Mathematician of the 9th Century whose name was Latinized as Algorithmi. He was a geographer, a scholar, and an astronomer who lived in the House of Wisdom in Baghdad.

The Algorithm is a set of instructions that are formulated in a finite and sequential order to solve mathematic and scientific problems. Before we should write or discover an algorithm, we need to know the exact problem for starting and stopping to formulate the intermediate steps. Following are the three main approaches to solving algorithms.

- Divide et Impera (Divide and Conquer) divides the problem into sub-parts and solves it one by one separately.
- Dynamic Programming that divides the problem into sub-parts to remember the results of the sub-parts to implement for similar problems.
- Greedy Algorithms are involved in taking the easiest step while solving a problem without considering the complexity of the future steps.

**Python Algorithms**

Algorithms are not language-specific, and they can be implemented in any programming language. There are no standard guides to write algorithms in Python. They are resource and problem-dependent that share some common code construction such as flow-control (if-else) and loops (do-while-for).

Here are the top four python algorithms used widely in Python namely tree traversal, sorting, searching, and graph algorithms.

**Tree Traversal Algorithms**

Trees in Python are non-linear **data structures** and they will be categorized by roots and nodes. Traversal refers to the process of visiting all the nodes of the tree that starts from the root in the following three different ways.

Sample TreeTraversal

class Node:

def __init__(self, letter):

self.childleft = None

self.childright = None

self.nodedata = letter

root = Node(‘A’) # create the nodes for the tree

root.childleft = Node(‘B’)

root.childright = Node(‘C’)

root.childleft.childleft = Node(‘D’)

root.childleft.childright = Node(‘E’)

- In-Order Traversal is visiting the subtree on the left first and the root, then the right subtree. That means it refers to the visiting of the left node followed by the root and the right nodes.

def InOrd(root):

if root:

InOrd(root.childleft)

print(root.nodedata)

InOrd(root.childright)

InOrd(root)

**Output**

D

B

E

A

C

- Pre-order Traversal, the first to be visited is the root node followed by the left sub-node, then the right sub-node.

def PreOrd(root):

if root:

print(root.nodedata)

PreOrd(root.childleft)

PreOrd(root.childright)

PreOrd(root)

**Output**

A B D E C

- Post-order Traversal refers to visiting the left sub-nodes followed by the right sub-nodes and then finally to the root node.

def PostOrd(root):

if root:

PostOrd(root.childleft)

PostOrd(root.childright)

print(root.nodedata)

PostOrd(root)

Output

D E B C A

**Sorting Algorithms**

Sorting Algorithms are defining the ways to arrange data in a specific format, and it ensures that the data searching is optimized to a high level and that the data is presented in a readable format. Following are the various types of Sorting Algorithms in Python

**Bubble Sort:** It is based on comparison of which is repeated swapping of adjacent elements if they are in an incorrect order.

**Merge Sort:** It is based on the divide and conquer algorithm, and the merge sort divides the array into two halves for soring them and combining them back.

**Insertion Sort:** It begins with comparing and sorting the first two elements and then the third element is compared with the two previously sorted elements and so on.

**Shell Sort:** It is like Insertion Sort, but far away elements are sorted. A large sub-list of as given list is sorted and the size of the list is progressively reduced until all the elements are sorted.

**Selection Sort:** It is based on finding the minimum value from a list of elements and putting it into a sorted list. The process will be repeated for every element in the list that is unsorted. The new element entering the sorted list will be compared with the existing elements for placing them in the correct position. This process will go until all the elements are sorted.

Sample Insertion Sort

def ins_sort(ourlist):

for x in range(1, len(ourlist)): # loop for each element starting from 1 to the length of our list

k = ourlist[x] # element with the index x

j = x-1 # j is the index previus the index x

while j >=0 and k < ourlist[j]: # until each element of the list is less than their previous element

ourlist[j+1] = ourlist[j] # the element indexed before the element considered is set to the next one index

j -= 1 # I decrement index j by 1

ourlist[j+1] = k # now k is the element in the index j+1

return ourlist

ourlist = [15, 1, 9, 3]

ins_sort(ourlist)

**Output**

[1, 3, 9, 15]

**Searching Algorithms**

Searching Algorithms are widely used to search for some elements that are present in a given dataset. Search Algorithms are in many types such as Linear Search, Binary Search, Exponential Search, Interpolation Search, and so on. In this article, we are going to explain linear and binary searches with sample codes.

**Linear Search**

In a one-dimensional array, we have to search a particular key element, and the input is the group of elements to find the key element. We need to compare the key element with every element of the group. In short, every item is sequentially searched one by one.

def lin_search(ourlist, key)

for index in range (0, len(ourlist)):

if (ourlist [index] == key):

return index

else:

return “not found”

ourlist = [15, 13, 1, 3]

lin_search(ourlist, 26)

**Output**

Not Found

**Binary Search **

If the list is in ascending order, if the value of the search key is less than the element in the middle of the list, the search interval should be repeatedly divided into half.

**Sample Binary Search**

def bin_search(ourlist, key):

left = 0 # I assign left position to zero

right = len(ourlist)-1 # assigning the right position by defining the length of ourlist minus one matched = False

while (left<=right and not matched): # the loop will continue until the left element is less or equal to the right element and the matched is True

mid = (left+right)//2 # I find the position of the middle element

if ourlist[mid] == key: # if the middle element corresponds to the key element

matched = True

else: #otherwise

If key < ourlist[mid]: # if key element is less than the middle element

right = mid – 1 #I assign the position of the right element as mid – 1

else: #otherwise

left = mid + 1 #left position will become the middle position plus 1

return matched

print(bin_search([1, 3, 9, 15], 17))

print(bin_search([1, 3, 9, 15], 3))

**Output**

False

True

**Graph Algorithms**

Following are the two methods of traversing graphs using their edges.

**Depth-first Traversal:** Here, a graph is traversed in a depthward motion and when any iteration faces a dead end, the stack is used to go to the next vertex for starting the search. DFS is applied in Python using the set data types.

**Breadth-first Traversal:** Here, a graph is traversed in a breadthward motion. When any iteration meets the dead end, the queue is used to go to the next vertex for beginning the search. BFS is applied in Python using Queue data structure.

**Conclusion**

The comprehensive knowledge of Python **data structures** and algorithms is useful for beginners as well as professionals to complete the programming in easiest and simple way. It requires when performing operations on data and optimizing data processing.

When **Data Structures** help in organizing the data, Algorithms are offering an efficient way to solve the problem of data analysis.

They both provide data scientists for processing knowledge of the data effectively. Learn data science with a specialization certificate by enrolling in our Data Science with Python Training in Chennai.