Algorithms in Python

An algorithm goes further than computational thinking. It is a step-by-step process that specifies a list of commands to be carried out in a specific order to get the intended result. In simple words, an algorithm is any piece of code designed to solve a particular problem. We can write a single algorithm in many programming languages because algorithms are typically constructed irrespective of the supporting languages.

In this article, we will deep dive into the world of algorithms in Python. This article will provide you with a solid foundation for understanding and implementing algorithms.

What is an Algorithm?

An algorithm is a finite line of code developed to be executed in the defined sequence to solve problems and produce the desired outcomes. An algorithm is generally written in a common language (pseudo-code) and then implemented in any programming language. It is recommended to write the pseudo-code of the algorithm on paper and test using some test cases before the implementation.

Steps to write an efficient Algorithm:

• Understand the Problem - Before writing an algorithm, analyse the requirements, constraints, and expected inputs and outputs.
• Choose the right data structure - It is important to select the right data structure to design an efficient algorithm.
• Analyse the time and space complexities - Aim for algorithms with the best possible time and space complexity for your problem.
• Design and Test the Algorithm - Based on your understanding of the problem, design the algorithm using pseudocode or a flowchart and thoroughly test it with various inputs.
• Optimize the Algorithm and Test Again - Look for potential optimizations and reduce redundant computations and unnecessary steps.
• Document the Algorithm - Finally, document the algorithm and provide a clear explanation of its logic, inputs, outputs, space and time complexities.

Let us now move forward with searching algorithms.

Searching Algorithms

Searching algorithms are used to find a specific element or value within a sequence of data.

Let's explore two popular searching algorithms: linear search and binary search.

1. Binary Search

• The binary search algorithm is based on the divide and conquer principle. It is used to find a value in a sorted sequence of data.
• It repeatedly divides the space in half by comparing the middle element with the target value.
• If the target value is greater than the middle value, it searches in the right half of the subarray. And if the target value is smaller than the middle value, it searches in the left half of the subarray.

Steps to Write Binary Search Algorithm:

1. Calculate Middle index, mid = (end - start + 1) // 2
2. the middle element with x.
3. If x == arr[mid], we return the middle element's index.
4. elif x > arr[mid], meaning the target value x can only be located in the right half of the subarray (where elements are larger). The method is then used once more for the right side iteratively or recursively.
5. Else, the target value x must be located on the left half of the subarray (where elements are smaller). The method is then used for the left side.

The working of binary search is clearly explained in this article -> Binary Search

Code: The iterative implementation of the binary search is given below:

Output:

```Array = [5, 8, 16, 37, 59, 80]
The given element 59 is present at the index 4
The given element 35 is not present in the array
```

2. Linear Search

• Linear search is the simplest searching algorithm, often used when the data is unsorted or when the search space is small.
• It sequentially checks each element in the data structure until a match is found or no match is found.

Steps to Write Linear Search Algorithm:

• Sequentially check each element in the array using a for-loop or while-loop.
• Return the index, if x is found.
• Else, return -1 stating that x is not present in the array.

The working of linear search is clearly explained in this article -> Linear Search

Code: Python Implementation of Linear Search

Output:

```Array = [5, 8, 16, 37, 59, 80]
The given element 59 is present at the index 4
The given element 35 is not present in the array
```

Let us now deep dive into the world of sorting algorithms in Python.

Sorting Algorithms

Sorting algorithms arrange elements in a specific order, such as ascending or descending. We will discuss some fundamental sorting algorithms: insertion sort, bubble sort, selection sort, merger sort, and quick sort.

1. Insertion Sort

• A straightforward sorting algorithm called insertion sort operates similarly to how we arrange playing cards.
• It iterates through the unsorted portion of the list and inserts each element into its correct position in the sorted section.

Steps to Write Insertion Sort Algorithm:

def insertion_sort(arr, n):

• Consider the arr[0] is sorted
• Start a for loop from i = 1 to n-1
• key = arr[i]
• Compare the key with each element in the left sorted subarray
• Shift the element to the right if it is greater than the key
• Insert the key at its right position in the left subarray.

The working of the insertion sort is clearly explained in this article -> Insertion Sort

Code: Python Implementation of Insertion Sort

Output:

```Unsorted array: [23, 42, 3, 83, 36, 49, 19]
Sorted array: [3, 19, 23, 36, 42, 49, 83]
```

2. Selection Sort

• Selection Sort is a simple comparison-based sorting algorithm. It divides the input into two parts: the sorted portion at the beginning and the unsorted portion at the end.
• The selection sort technique sorts any given array by repeatedly picking the element with the lowest value out of the unsorted segment and swapping it with the element at the current position in the sorted portion.

Steps to Write Selection Sort Algorithm:

def selection_sort(arr, n):

• Traverse each element in the array i = 0 to n-2
• Start a for loop from i = i+1 to n-1
• Select the minimum element from the right subarray
• Swap the minimum element with the first element of the right subarray (unsorted part)
• Repeat the steps until all elements are sorted

Code: Python implementation of Selection Sort

Output:

```The sorted array is: [3, 19, 23, 36, 42, 49, 83]
```

3. Bubble Sort

Bubble sort is the simplest and most inefficient sorting algorithm. It repeatedly compares adjacent elements and swaps them if they are in the wrong order, gradually moving the largest elements toward the end of the list.

Steps to Write Bubble Sort Algorithm:

def bubble_sort(arr, n):

• Traverse each element from i = 0 to the second last element using a for-loop
• Start another for-loop from j = 0 to len(arr)-i-1
• Compare arr[j] and arr[j+1] - Swap both of them if they are in the wrong order
• Repeat the process until all elements are sorted

Code: Python implementation of Bubble Sort

Output:

```The sorted array is: [3, 19, 23, 36, 42, 49, 83]
```

4. Merge Sort

• Merge Sort is a divide-and-conquer sorting algorithm. It recursively divides the input array into two halves, sorts each half independently, and then merges them back together.
• It repeatedly compares the elements from the two sorted halves and combines them in the correct order.

Steps to Write Merge Sort Algorithm:

def merge_sort(arr, n, left, right):

• Define the base case - if size(arr) = 1 return the array # a single element in an array is always sorted.
• Calculate the mid of the array and divide it into two halves
• Call the merge sort again on the left subarray and right subarray
• Call Merge(arr, left, mid, right) function

def merge(arr, left, mid, right):

• Create two copies of arr1 = arr[left, mid] and arr2 = arr[mid+1, right]
• Compare elements of both newly created subarrays
• Insert the element in the array in the right order.
• Check if there are elements remaining either in arr1 or arr2
• Repeat the task until all elements are inserted back into the main array

Code: Python Implementation of Merge Sort

Output:

```The given array is: [23, 42, 3, 83, 36, 49, 19]
The sorted array is: [3, 19, 23, 36, 42, 49, 83]
```

5. Quick Sort

• Quick Sort is also based on the Divide-and-conquer principle, just like Merge Sort.
• Quicksort is a highly efficient sorting algorithm.
• It recursively partitions the array into smaller subarrays based on a chosen pivot element, then sorts the subarrays independently.

Steps to Write Quick Sort Algorithm:

def quick_sort(arr, low, high)

• Partition the array and get the pivot index - pivot_index = partition(arr, low, high)
• Recursively sort the left and right subarrays:
• quick_sort(arr, low, pivot_index - 1)
• quick_sort(arr, pivot_index + 1, high)

def partition(arr, low, high):

• Choose the rightmost element as the pivot - pivot = arr[high]
• Initialize the pivot index as the lowest index - pivot_index = low
• Select all elements smaller than the pivot and move them to the left using a for-loop.
• Place the pivot at its right position in the array.
• Return the pivot_index to the quick_sort function.

Code: Python Implementation of Quick Sort

Output:

```The unsorted array is: [23, 42, 3, 83, 36, 49, 19]
The sorted array is: [3, 19, 23, 36, 42, 49, 83]
```

CONCLUSION:

In this article, we covered two searching algorithms (linear search and binary search) and five sorting algorithms (bubble sort, insertion sort, selection sort, merge sort, and quicksort) in Python. These algorithms will help you in writing efficient code and give you a strong foundation for solving problems.

Next TopicPython descriptors