Linear Search Visualizer using PyQt5

Understanding data structures and algorithms is essential for any prospective programmer because they are the foundation of computer science. Visualizing these concepts can significantly aid understanding. This article demonstrates how to create a linear search visualizer using Python's PyQt5 library with step-by-step animation of the search process.

Introduction to PyQt5

PyQt5 is a comprehensive set of Python bindings for Qt libraries that enables building complex and feature-rich GUI applications. It is highly versatile and works across various operating systems, making it ideal for creating interactive visualizations.

Understanding Linear Search

Linear search is a straightforward algorithm for finding a specific element in a list or array. It starts at the beginning of the array and sequentially checks each element until it finds the target or reaches the end of the array. The time complexity is O(n) in the worst case.

Setting Up PyQt5

First, ensure PyQt5 is installed in your Python environment ?

pip install pyqt5

Building the Linear Search Visualizer

Example 1: Creating the Basic Window

Let's start by creating a simple window using PyQt5. This code creates an application with a window titled "Linear Search Visualizer" ?

import sys
from PyQt5 import QtWidgets, QtGui, QtCore

class LinearSearchVisualizer(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        
        # Set window properties
        self.setWindowTitle('Linear Search Visualizer')
        self.setGeometry(100, 100, 800, 400)
        
        # Initialize array and search parameters
        self.array = [50, 70, 30, 90, 60, 10, 40, 20, 80]
        self.target = 60
        self.current_index = -1
        self.found = False
        self.searching = False

# Create application instance
app = QtWidgets.QApplication(sys.argv)
visualizer = LinearSearchVisualizer()
visualizer.show()
sys.exit(app.exec_())

Example 2: Drawing the Array Representation

Now we'll add visual representation using rectangles. Each rectangle's height represents the value it contains ?

import sys
from PyQt5 import QtWidgets, QtGui, QtCore

class LinearSearchVisualizer(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        
        self.setWindowTitle('Linear Search Visualizer')
        self.setGeometry(100, 100, 800, 400)
        
        # Initialize array and search parameters
        self.array = [50, 70, 30, 90, 60, 10, 40, 20, 80]
        self.target = 60
        self.current_index = -1
        self.found = False
        self.searching = False

    def paintEvent(self, event):
        painter = QtGui.QPainter()
        painter.begin(self)
        
        # Set background
        painter.fillRect(self.rect(), QtGui.QColor(240, 240, 240))
        
        # Draw array elements
        bar_width = 60
        bar_spacing = 70
        start_x = 50
        base_y = 300
        
        for i in range(len(self.array)):
            x = start_x + i * bar_spacing
            height = self.array[i] * 2
            
            # Choose color based on search state
            if i == self.current_index:
                if self.found:
                    painter.setBrush(QtGui.QColor(0, 255, 0))  # Green for found
                else:
                    painter.setBrush(QtGui.QColor(255, 0, 0))  # Red for current
            else:
                painter.setBrush(QtGui.QColor(100, 150, 200))  # Blue for normal
            
            # Draw rectangle
            painter.drawRect(x, base_y - height, bar_width, height)
            
            # Draw value text
            painter.setPen(QtGui.QColor(0, 0, 0))
            painter.drawText(x + 20, base_y + 20, str(self.array[i]))
        
        # Draw target information
        painter.setPen(QtGui.QColor(0, 0, 0))
        painter.drawText(50, 50, f"Target: {self.target}")
        
        if self.found:
            painter.drawText(50, 70, f"Found at index: {self.current_index}")
        elif self.searching:
            painter.drawText(50, 70, f"Checking index: {self.current_index}")
        
        painter.end()

# Create application instance
app = QtWidgets.QApplication(sys.argv)
visualizer = LinearSearchVisualizer()
visualizer.show()
sys.exit(app.exec_())

Example 3: Adding Animation and Search Logic

This example adds the complete linear search animation with timer-based progression ?

import sys
from PyQt5 import QtWidgets, QtGui, QtCore

class LinearSearchVisualizer(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        
        self.setWindowTitle('Linear Search Visualizer')
        self.setGeometry(100, 100, 800, 500)
        
        # Initialize array and search parameters
        self.array = [50, 70, 30, 90, 60, 10, 40, 20, 80]
        self.target = 60
        self.current_index = -1
        self.found = False
        self.searching = False
        
        # Create start button
        self.start_button = QtWidgets.QPushButton('Start Search', self)
        self.start_button.setGeometry(50, 350, 100, 30)
        self.start_button.clicked.connect(self.start_search)
        
        # Create reset button
        self.reset_button = QtWidgets.QPushButton('Reset', self)
        self.reset_button.setGeometry(160, 350, 100, 30)
        self.reset_button.clicked.connect(self.reset_search)
        
        # Timer for animation
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.advance_search)

    def paintEvent(self, event):
        painter = QtGui.QPainter()
        painter.begin(self)
        
        # Set background
        painter.fillRect(self.rect(), QtGui.QColor(240, 240, 240))
        
        # Draw array elements
        bar_width = 60
        bar_spacing = 70
        start_x = 50
        base_y = 300
        
        for i in range(len(self.array)):
            x = start_x + i * bar_spacing
            height = self.array[i] * 2
            
            # Choose color based on search state
            if i == self.current_index:
                if self.found:
                    painter.setBrush(QtGui.QColor(0, 255, 0))  # Green for found
                else:
                    painter.setBrush(QtGui.QColor(255, 0, 0))  # Red for current
            elif self.searching and i < self.current_index:
                painter.setBrush(QtGui.QColor(150, 150, 150))  # Gray for checked
            else:
                painter.setBrush(QtGui.QColor(100, 150, 200))  # Blue for normal
            
            # Draw rectangle
            painter.drawRect(x, base_y - height, bar_width, height)
            
            # Draw value text
            painter.setPen(QtGui.QColor(0, 0, 0))
            painter.drawText(x + 20, base_y + 20, str(self.array[i]))
        
        # Draw target information
        painter.setPen(QtGui.QColor(0, 0, 0))
        painter.drawText(50, 50, f"Target: {self.target}")
        
        if self.found:
            painter.drawText(50, 70, f"Found at index: {self.current_index}")
        elif self.searching and self.current_index >= 0:
            painter.drawText(50, 70, f"Checking index: {self.current_index}")
        elif self.searching:
            painter.drawText(50, 70, "Search completed - Target not found")
        
        painter.end()

    def start_search(self):
        self.searching = True
        self.current_index = 0
        self.found = False
        self.start_button.setEnabled(False)
        self.timer.start(1000)  # 1 second interval

    def advance_search(self):
        if self.current_index < len(self.array):
            # Check if current element matches target
            if self.array[self.current_index] == self.target:
                self.found = True
                self.timer.stop()
                self.start_button.setEnabled(True)
            else:
                self.current_index += 1
                if self.current_index >= len(self.array):
                    # Search completed, target not found
                    self.timer.stop()
                    self.start_button.setEnabled(True)
                    self.current_index = -1
        
        # Trigger repaint
        self.update()

    def reset_search(self):
        self.timer.stop()
        self.searching = False
        self.current_index = -1
        self.found = False
        self.start_button.setEnabled(True)
        self.update()

# Create application instance
if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    visualizer = LinearSearchVisualizer()
    visualizer.show()
    sys.exit(app.exec_())

Key Features of the Visualizer

Color Coding: Blue rectangles represent unvisited elements, red shows the currently checked element, green indicates the found target, and gray marks previously checked elements.

Interactive Controls: Start and Reset buttons allow users to control the animation and repeat the visualization multiple times.

Real-time Updates: The QTimer creates smooth animation by updating the display every second, making the search process easy to follow.

Conclusion

This linear search visualizer demonstrates how PyQt5 can effectively illustrate algorithmic concepts through interactive graphics. The step-by-step animation helps users understand how linear search systematically examines each element until finding the target or exhausting all possibilities.

---
Updated on: 2026-03-27T08:20:21+05:30

264 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements