Searching Algorithms in Data Structures and Algorithms

g286d291660abd6b78020607fac4234bd1d26c7af1efd56210efc5d2d040f7df2abc78c1ff206a71834bad472e7037f4b3adb1f7c1f3ac5adf8821f0004d6378e_1280-1614234.jpg

Searching is one of the core operations in computer science. Efficient searching algorithms are crucial for retrieving data quickly and accurately from various data structures. This blog will explore different types of searching algorithms, their time complexities, and use cases.

Why Searching?

Searching allows us to find specific elements within a data structure. It is essential for various applications, including database queries, information retrieval systems, and even basic functions like looking up a contact on your phone.

Types of Searching Algorithms

Searching algorithms can be broadly categorized based on their approach and the data structure they operate on. Here some common searching algorithms”

  1. Linear Search
  2. Binary Search
  3. Depth-First Search (DFS)
  4. Breadth-First Search (BFS)
  5. Hashing

Linear Search

Description: Linear search is the simplest searching algorithm. It sequentially checks each element of the data structure until it finds the target element or reaches the end.

Time complexity: O(N), where N is the number of elements in the data structure/

Use Case: Linear search is useful for small or unsorted datatsets.

def linear_search(arr, target):
    for i in range(len(arr)):
        if arr[i] == target:
            return i
    return -1

# Example usage
array = [2, 4, 0, 1, 9]
target = 1
result = linear_search(array, target)
print(f"Element found at index: {result}")

Binary Search

Binary search is highly efficient algorithm that works on sorted arrays. It repeatedly divides the search interval in half. If the target value is less than the middle element, the search continues in the lower half; otherwise, it continues in the upper half.

Time complexity: O(LogN)

def binary_search(arr, target):
    left, right = 0, len(arr) - 1

    while left <= right:
        mid = left + (right - left) // 2

        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1

    return -1

# Example usage
array = [1, 2, 3, 4, 5, 6, 7, 8, 9]
target = 4
result = binary_search(array, target)
print(f"Element found at index: {result}")

Depth-First Search (DFS)

DFS is a recursive algorithm used for traversing or searching tree or graph data structures. It stats at the root (or an arbitrary node) and explores as far as possible along each branch before backtracking.

Time Complexity: O(V+E) where V is the number of vertices and E is the number of edges.

class Graph:
    def __init__(self):
        self.graph = {}

    def add_edge(self, v, w):
        if v not in self.graph:
            self.graph[v] = []
        self.graph[v].append(w)

    def dfs_util(self, v, visited):
        visited.add(v)
        print(v, end=' ')

        for neighbour in self.graph[v]:
            if neighbour not in visited:
                self.dfs_util(neighbour, visited)

    def dfs(self, v):
        visited = set()
        self.dfs_util(v, visited)

# Example usage
g = Graph()
g.add_edge(0, 1)
g.add_edge(0, 2)
g.add_edge(1, 2)
g.add_edge(2, 0)
g.add_edge(2, 3)
g.add_edge(3, 3)

print("Following is Depth First Traversal (starting from vertex 2)")
g.dfs(2)

Breadth-First Search (BFS)

BFS is an iterative algorithm used for traversing or searching tree or graph data structures. It starts at the root (or an arbitrary node) and explores all its neighbors at the present depth level before moving on to nodes at the next depth level.

Time Complexity: O(V + E)

from collections import deque

class Graph:
    def __init__(self):
        self.graph = {}

    def add_edge(self, v, w):
        if v not in self.graph:
            self.graph[v] = []
        self.graph[v].append(w)

    def bfs(self, s):
        visited = set()
        queue = deque([s])
        visited.add(s)

        while queue:
            s = queue.popleft()
            print(s, end=' ')

            for neighbour in self.graph[s]:
                if neighbour not in visited:
                    queue.append(neighbour)
                    visited.add(neighbour)

# Example usage
g = Graph()
g.add_edge(0, 1)
g.add_edge(0, 2)
g.add_edge(1, 2)
g.add_edge(2, 0)
g.add_edge(2, 3)
g.add_edge(3, 3)

print("Following is Breadth First Traversal (starting from vertex 2)")
g.bfs(2)

Source Code : https://github.com/hongquan080799/data-structure-and-algorithms.git

Conclusion

Searching algorithms are crucial for efficient data retrieval in various applications. Understanding the different types of searching algorithms and their use cases can help you choose the right algorithm for you specific needs. Whether you are not working with small datasets or large, complex data structures, there is a searching algorithm that fits yours requirements.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top