Skip to main content

Data Structures and Algorithms in Python

Data Structures and Algorithms in Python

This guide provides sample Python programs for fundamental data structures and algorithms tailored to manage student-related data. Each experiment includes the problem statement, complete code with detailed comments, example input/output, and explanations suitable for beginners to experts.


Table of Contents

  1. Stack Operations
  2. Queue Operations
  3. Circular Queue Operations
  4. Linked List Insertion, Deletion & Copy
  5. Sorting and Searching
  6. References and Further Reading

1. Stack Operations

Problem Statement

Write a Python program to perform PUSH, POP, PEEP (Peek), and CHANGE operations on a stack that manages student records.

Description

A stack is a linear data structure that follows the Last-In-First-Out (LIFO) principle. In this experiment, each element in the stack represents a student record containing Student ID, Name, and Grade. The primary operations are:

  • PUSH: Add a student record to the top of the stack.
  • POP: Remove the top student record from the stack.
  • PEEP (Peek): View the top student record without removing it.
  • CHANGE: Modify the value of a student record at a specific position from the top.

1.1. Implementation Using a List

class Student:

    def __init__(self, student_id, name, grade):

        self.student_id = student_id

        self.name = name

        self.grade = grade

 

    def __str__(self):

        return f"ID: {self.student_id}, Name: {self.name}, Grade: {self.grade}"

 

class Stack:

    def __init__(self, max_size=100):

        self.stack = []

        self.max_size = max_size

 

    def is_empty(self):

        return len(self.stack) == 0

 

    def is_full(self):

        return len(self.stack) >= self.max_size

 

    def push(self, student):

        if self.is_full():

            print("Stack Overflow! Cannot push the student record.")

            return

        self.stack.append(student)

        print(f"Pushed: {student}")

 

    def pop(self):

        if self.is_empty():

            print("Stack Underflow! Cannot pop.")

            return None

        student = self.stack.pop()

        print(f"Popped: {student}")

        return student

 

    def peek(self):

        if self.is_empty():

            print("Stack is empty. Nothing to peek.")

            return None

        student = self.stack[-1]

        print(f"Top Student: {student}")

        return student

 

    def change(self, position, new_student):

        if position < 1 or position > len(self.stack):

            print("Invalid position!")

            return

        index = -position

        print(f"Changing position {position} from {self.stack[index]} to {new_student}")

        self.stack[index] = new_student

 

    def display(self):

        if self.is_empty():

            print("Stack is empty.")

            return

        print("Stack elements (top to bottom):")

        for student in reversed(self.stack):

            print(student)

 

def main():

    stack = Stack()

    while True:

        print("\n--- Stack Operations Menu ---")

        print("1. Push")

        print("2. Pop")

        print("3. Peek (Peep)")

        print("4. Change")

        print("5. Display")

        print("6. Exit")

        choice = input("Enter your choice: ")

 

        if choice == '1':

            student_id = input("Enter Student ID: ")

            name = input("Enter Student Name: ")

            grade = input("Enter Student Grade: ")

            student = Student(student_id, name, grade)

            stack.push(student)

        elif choice == '2':

            stack.pop()

        elif choice == '3':

            stack.peek()

        elif choice == '4':

            position = int(input("Enter position to change (1 for top): "))

            student_id = input("Enter new Student ID: ")

            name = input("Enter new Student Name: ")

            grade = input("Enter new Student Grade: ")

            new_student = Student(student_id, name, grade)

            stack.change(position, new_student)

        elif choice == '5':

            stack.display()

        elif choice == '6':

            print("Exiting...")

            break

        else:

            print("Invalid choice! Please try again.")

 

if __name__ == "__main__":

    main()

1.2. Explanation

  • Student Class:
    • Represents a student record with student_id, name, and grade.
    • The __str__ method provides a readable string representation of the student.
  • Stack Class:
    • Utilizes a Python list to store student records.
    • is_empty and is_full methods check the stack's status.
    • push adds a student to the top, ensuring the stack isn't full.
    • pop removes the top student, ensuring the stack isn't empty.
    • peek views the top student without removing it.
    • change modifies a student at a specified position from the top.
    • display prints all student records from top to bottom.
  • Main Function:
    • Provides a menu-driven interface for performing stack operations.
    • Continuously prompts the user until they choose to exit.

1.3. Example Run

--- Stack Operations Menu ---

1. Push

2. Pop

3. Peek (Peep)

4. Change

5. Display

6. Exit

Enter your choice: 1

Enter Student ID: S001

Enter Student Name: Alice

Enter Student Grade: A

Pushed: ID: S001, Name: Alice, Grade: A

 

--- Stack Operations Menu ---

1. Push

2. Pop

3. Peek (Peep)

4. Change

5. Display

6. Exit

Enter your choice: 1

Enter Student ID: S002

Enter Student Name: Bob

Enter Student Grade: B

Pushed: ID: S002, Name: Bob, Grade: B

 

--- Stack Operations Menu ---

1. Push

2. Pop

3. Peek (Peep)

4. Change

5. Display

6. Exit

Enter your choice: 5

Stack elements (top to bottom):

ID: S002, Name: Bob, Grade: B

ID: S001, Name: Alice, Grade: A

 

--- Stack Operations Menu ---

1. Push

2. Pop

3. Peek (Peep)

4. Change

5. Display

6. Exit

Enter your choice: 3

Top Student: ID: S002, Name: Bob, Grade: B

 

--- Stack Operations Menu ---

1. Push

2. Pop

3. Peek (Peep)

4. Change

5. Display

6. Exit

Enter your choice: 4

Enter position to change (1 for top): 2

Enter new Student ID: S003

Enter new Student Name: Charlie

Enter new Student Grade: A+

Changing position 2 from ID: S001, Name: Alice, Grade: A to ID: S003, Name: Charlie, Grade: A+

 

2. Queue Operations

Problem Statement

Write a Python program to implement insertion (enqueue) and deletion (dequeue) in a queue that manages student records.

Description

A queue is a linear data structure that follows the First-In-First-Out (FIFO) principle. In this experiment, each element in the queue represents a student record containing Student ID, Name, and Grade. The primary operations are:

  • Enqueue: Add a student record to the rear of the queue.
  • Dequeue: Remove a student record from the front of the queue.

2.1. Implementation Using collections.deque

from collections import deque

 

class Student:

    def __init__(self, student_id, name, grade):

        self.student_id = student_id

        self.name = name

        self.grade = grade

 

    def __str__(self):

        return f"ID: {self.student_id}, Name: {self.name}, Grade: {self.grade}"

 

class Queue:

    def __init__(self, max_size=100):

        self.queue = deque()

        self.max_size = max_size

 

    def is_empty(self):

        return len(self.queue) == 0

 

    def is_full(self):

        return len(self.queue) >= self.max_size

 

    def enqueue(self, student):

        if self.is_full():

            print("Queue Overflow! Cannot enqueue the student record.")

            return

        self.queue.append(student)

        print(f"Enqueued: {student}")

 

    def dequeue(self):

        if self.is_empty():

            print("Queue Underflow! Cannot dequeue.")

            return None

        student = self.queue.popleft()

        print(f"Dequeued: {student}")

        return student

 

    def display(self):

        if self.is_empty():

            print("Queue is empty.")

            return

        print("Queue elements (front to rear):")

        for student in self.queue:

            print(student)

 

def main():

    queue = Queue()

    while True:

        print("\n--- Queue Operations Menu ---")

        print("1. Enqueue")

        print("2. Dequeue")

        print("3. Display")

        print("4. Exit")

        choice = input("Enter your choice: ")

 

        if choice == '1':

            student_id = input("Enter Student ID: ")

            name = input("Enter Student Name: ")

            grade = input("Enter Student Grade: ")

            student = Student(student_id, name, grade)

            queue.enqueue(student)

        elif choice == '2':

            queue.dequeue()

        elif choice == '3':

            queue.display()

        elif choice == '4':

            print("Exiting...")

            break

        else:

            print("Invalid choice! Please try again.")

 

if __name__ == "__main__":

    main()

2.2. Explanation

  • Student Class:
    • Represents a student record with student_id, name, and grade.
    • The __str__ method provides a readable string representation of the student.
  • Queue Class:
    • Utilizes collections.deque for efficient queue operations.
    • is_empty and is_full methods check the queue's status.
    • enqueue adds a student to the rear, ensuring the queue isn't full.
    • dequeue removes a student from the front, ensuring the queue isn't empty.
    • display prints all student records from front to rear.
  • Main Function:
    • Provides a menu-driven interface for performing queue operations.
    • Continuously prompts the user until they choose to exit.

2.3. Example Run

--- Queue Operations Menu ---

1. Enqueue

2. Dequeue

3. Display

4. Exit

Enter your choice: 1

Enter Student ID: S101

Enter Student Name: David

Enter Student Grade: B+

Enqueued: ID: S101, Name: David, Grade: B+

 

--- Queue Operations Menu ---

1. Enqueue

2. Dequeue

3. Display

4. Exit

Enter your choice: 1

Enter Student ID: S102

Enter Student Name: Eva

Enter Student Grade: A

Enqueued: ID: S102, Name: Eva, Grade: A

 

--- Queue Operations Menu ---

1. Enqueue

2. Dequeue

3. Display

4. Exit

Enter your choice: 3

Queue elements (front to rear):

ID: S101, Name: David, Grade: B+

ID: S102, Name: Eva, Grade: A

 

--- Queue Operations Menu ---

1. Enqueue

2. Dequeue

3. Display

4. Exit

Enter your choice: 2

Dequeued: ID: S101, Name: David, Grade: B+

 

--- Queue Operations Menu ---

1. Enqueue

2. Dequeue

3. Display

4. Exit

Enter your choice: 3

Queue elements (front to rear):

ID: S102, Name: Eva, Grade: A

 

--- Queue Operations Menu ---

1. Enqueue

2. Dequeue

3. Display

4. Exit

Enter your choice: 4

Exiting...

 

3. Circular Queue Operations

Problem Statement

Write a Python program to implement insertion (enqueue) and deletion (dequeue) in a circular queue that manages student records.

Description

A circular queue is a linear data structure that connects the end back to the front to utilize space efficiently. This implementation ensures that the queue can wrap around to the beginning when there's available space after dequeue operations. Each element in the circular queue represents a student record containing Student ID, Name, and Grade.

3.1. Implementation Using a List

class Student:

    def __init__(self, student_id, name, grade):

        self.student_id = student_id

        self.name = name

        self.grade = grade

 

    def __str__(self):

        return f"ID: {self.student_id}, Name: {self.name}, Grade: {self.grade}"

 

class CircularQueue:

    def __init__(self, max_size=5):

        self.queue = [None] * max_size

        self.max_size = max_size

        self.front = -1

        self.rear = -1

 

    def is_empty(self):

        return self.front == -1

 

    def is_full(self):

        return (self.rear + 1) % self.max_size == self.front

 

    def enqueue(self, student):

        if self.is_full():

            print("Circular Queue Overflow! Cannot enqueue the student record.")

            return

        if self.is_empty():

            self.front = 0

        self.rear = (self.rear + 1) % self.max_size

        self.queue[self.rear] = student

        print(f"Enqueued: {student}")

 

    def dequeue(self):

        if self.is_empty():

            print("Circular Queue Underflow! Cannot dequeue.")

            return None

        student = self.queue[self.front]

        self.queue[self.front] = None  # Optional: Clear the spot

        if self.front == self.rear:

            # Queue becomes empty

            self.front = -1

            self.rear = -1

        else:

            self.front = (self.front + 1) % self.max_size

        print(f"Dequeued: {student}")

        return student

 

    def display(self):

        if self.is_empty():

            print("Circular Queue is empty.")

            return

        print("Circular Queue elements (front to rear):")

        index = self.front

        while True:

            print(self.queue[index])

            if index == self.rear:

                break

            index = (index + 1) % self.max_size

 

def main():

    cq = CircularQueue(max_size=5)

    while True:

        print("\n--- Circular Queue Operations Menu ---")

        print("1. Enqueue")

        print("2. Dequeue")

        print("3. Display")

        print("4. Exit")

        choice = input("Enter your choice: ")

 

        if choice == '1':

            student_id = input("Enter Student ID: ")

            name = input("Enter Student Name: ")

            grade = input("Enter Student Grade: ")

            student = Student(student_id, name, grade)

            cq.enqueue(student)

        elif choice == '2':

            cq.dequeue()

        elif choice == '3':

            cq.display()

        elif choice == '4':

            print("Exiting...")

            break

        else:

            print("Invalid choice! Please try again.")

 

if __name__ == "__main__":

    main()

3.2. Explanation

  • Student Class:
    • Represents a student record with student_id, name, and grade.
    • The __str__ method provides a readable string representation of the student.
  • CircularQueue Class:
    • Uses a fixed-size list to represent the circular queue.
    • front and rear pointers track the start and end of the queue.
    • is_empty checks if the queue is empty.
    • is_full checks if the queue is full based on the circular condition.
    • enqueue adds a student to the rear, ensuring the queue isn't full. If the queue is empty, it initializes front.
    • dequeue removes a student from the front, ensuring the queue isn't empty. Adjusts pointers accordingly.
    • display prints all student records from front to rear, handling the circular nature.
  • Main Function:
    • Provides a menu-driven interface for performing circular queue operations.
    • Continuously prompts the user until they choose to exit.

3.3. Example Run

--- Circular Queue Operations Menu ---

1. Enqueue

2. Dequeue

3. Display

4. Exit

Enter your choice: 1

Enter Student ID: S201

Enter Student Name: Frank

Enter Student Grade: B

Enqueued: ID: S201, Name: Frank, Grade: B

 

--- Circular Queue Operations Menu ---

1. Enqueue

2. Dequeue

3. Display

4. Exit

Enter your choice: 1

Enter Student ID: S202

Enter Student Name: Grace

Enter Student Grade: A-

Enqueued: ID: S202, Name: Grace, Grade: A-

 

--- Circular Queue Operations Menu ---

1. Enqueue

2. Dequeue

3. Display

4. Exit

Enter your choice: 1

Enter Student ID: S203

Enter Student Name: Hannah

Enter Student Grade: B+

Enqueued: ID: S203, Name: Hannah, Grade: B+

 

--- Circular Queue Operations Menu ---

1. Enqueue

2. Dequeue

3. Display

4. Exit

Enter your choice: 3

Circular Queue elements (front to rear):

ID: S201, Name: Frank, Grade: B

ID: S202, Name: Grace, Grade: A-

ID: S203, Name: Hannah, Grade: B+

 

--- Circular Queue Operations Menu ---

1. Enqueue

2. Dequeue

3. Display

4. Exit

Enter your choice: 2

Dequeued: ID: S201, Name: Frank, Grade: B

 

--- Circular Queue Operations Menu ---

1. Enqueue

2. Dequeue

3. Display

4. Exit

Enter your choice: 1

Enter Student ID: S204

Enter Student Name: Ian

Enter Student Grade: A

Enqueued: ID: S204, Name: Ian, Grade: A

 

--- Circular Queue Operations Menu ---

1. Enqueue

2. Dequeue

3. Display

4. Exit

Enter your choice: 1

Enter Student ID: S205

Enter Student Name: Jane

Enter Student Grade: B-

Enqueued: ID: S205, Name: Jane, Grade: B-

 

--- Circular Queue Operations Menu ---

1. Enqueue

2. Dequeue

3. Display

4. Exit

Enter your choice: 1

Enter Student ID: S206

Enter Student Name: Kyle

Enter Student Grade: A+

Circular Queue Overflow! Cannot enqueue the student record.

 

--- Circular Queue Operations Menu ---

1. Enqueue

2. Dequeue

3. Display

4. Exit

Enter your choice: 3

Circular Queue elements (front to rear):

ID: S202, Name: Grace, Grade: A-

ID: S203, Name: Hannah, Grade: B+

ID: S204, Name: Ian, Grade: A

ID: S205, Name: Jane, Grade: B-

 

--- Circular Queue Operations Menu ---

1. Enqueue

2. Dequeue

3. Display

4. Exit

Enter your choice: 4

Exiting...

4. Linked List Insertion, Deletion & Copy

Problem Statement

Write a Python program for linked list insertion, deletion, and copy operations to manage student records.

Description

A linked list is a dynamic data structure consisting of nodes where each node contains data and a reference to the next node. This implementation covers:

  • Insertion: At the beginning, end, and specific positions.
  • Deletion: From the beginning, end, and specific positions.
  • Copying: Creating a duplicate of the existing linked list.

Each node in the linked list represents a student record containing Student ID, Name, and Grade.

4.1. Implementation Using Singly Linked List

class Student:

    def __init__(self, student_id, name, grade):

        self.student_id = student_id

        self.name = name

        self.grade = grade

 

    def __str__(self):

        return f"ID: {self.student_id}, Name: {self.name}, Grade: {self.grade}"

 

class Node:

    def __init__(self, student):

        self.student = student

        self.next = None

 

class LinkedList:

    def __init__(self):

        self.head = None

 

    # Insert at the beginning

    def insert_at_beginning(self, student):

        new_node = Node(student)

        new_node.next = self.head

        self.head = new_node

        print(f"Inserted at beginning: {student}")

 

    # Insert at the end

    def insert_at_end(self, student):

        new_node = Node(student)

        if not self.head:

            self.head = new_node

            print(f"Inserted as the first node: {student}")

            return

        last = self.head

        while last.next:

            last = last.next

        last.next = new_node

        print(f"Inserted at end: {student}")

 

    # Insert after a given position

    def insert_after_position(self, position, student):

        if position < 1:

            print("Invalid position!")

            return

        current = self.head

        for _ in range(position - 1):

            if not current:

                print("Position exceeds list length.")

                return

            current = current.next

        if not current:

            print("Position exceeds list length.")

            return

        new_node = Node(student)

        new_node.next = current.next

        current.next = new_node

        print(f"Inserted after position {position}: {student}")

 

    # Delete from the beginning

    def delete_from_beginning(self):

        if not self.head:

            print("List is empty. Cannot delete.")

            return

        removed = self.head.student

        self.head = self.head.next

        print(f"Deleted from beginning: {removed}")

 

    # Delete from the end

    def delete_from_end(self):

        if not self.head:

            print("List is empty. Cannot delete.")

            return

        if not self.head.next:

            removed = self.head.student

            self.head = None

            print(f"Deleted from end: {removed}")

            return

        current = self.head

        while current.next.next:

            current = current.next

        removed = current.next.student

        current.next = None

        print(f"Deleted from end: {removed}")

 

    # Delete at a specific position

    def delete_at_position(self, position):

        if not self.head or position < 1:

            print("Invalid position or empty list.")

            return

        if position == 1:

            self.delete_from_beginning()

            return

        current = self.head

        for _ in range(position - 2):

            if not current.next:

                print("Position exceeds list length.")

                return

            current = current.next

        if not current.next:

            print("Position exceeds list length.")

            return

        removed = current.next.student

        current.next = current.next.next

        print(f"Deleted at position {position}: {removed}")

 

    # Display the linked list

    def display(self):

        if not self.head:

            print("Linked List is empty.")

            return

        print("Linked List elements:")

        current = self.head

        position = 1

        while current:

            print(f"Position {position}: {current.student}")

            current = current.next

            position += 1

 

    # Copy the linked list

    def copy_list(self):

        if not self.head:

            print("Original list is empty. Cannot copy.")

            return None

        copied_list = LinkedList()

        current_original = self.head

        while current_original:

            copied_student = Student(current_original.student.student_id,

                                     current_original.student.name,

                                     current_original.student.grade)

            copied_list.insert_at_end(copied_student)

            current_original = current_original.next

        print("Linked List copied successfully.")

        return copied_list

 

def main():

    ll = LinkedList()

    copied_ll = None

    while True:

        print("\n--- Linked List Operations Menu ---")

        print("1. Insert at Beginning")

        print("2. Insert at End")

        print("3. Insert after Position")

        print("4. Delete from Beginning")

        print("5. Delete from End")

        print("6. Delete at Position")

        print("7. Display Linked List")

        print("8. Copy Linked List")

        print("9. Display Copied Linked List")

        print("10. Exit")

        choice = input("Enter your choice: ")

 

        if choice == '1':

            student_id = input("Enter Student ID: ")

            name = input("Enter Student Name: ")

            grade = input("Enter Student Grade: ")

            student = Student(student_id, name, grade)

            ll.insert_at_beginning(student)

        elif choice == '2':

            student_id = input("Enter Student ID: ")

            name = input("Enter Student Name: ")

            grade = input("Enter Student Grade: ")

            student = Student(student_id, name, grade)

            ll.insert_at_end(student)

        elif choice == '3':

            position = int(input("Enter position after which to insert: "))

            student_id = input("Enter Student ID: ")

            name = input("Enter Student Name: ")

            grade = input("Enter Student Grade: ")

            student = Student(student_id, name, grade)

            ll.insert_after_position(position, student)

        elif choice == '4':

            ll.delete_from_beginning()

        elif choice == '5':

            ll.delete_from_end()

        elif choice == '6':

            position = int(input("Enter position to delete: "))

            ll.delete_at_position(position)

        elif choice == '7':

            ll.display()

        elif choice == '8':

            copied_ll = ll.copy_list()

        elif choice == '9':

            if copied_ll:

                copied_ll.display()

            else:

                print("No copied list available.")

        elif choice == '10':

            print("Exiting...")

            break

        else:

            print("Invalid choice! Please try again.")

 

if __name__ == "__main__":

    main()

4.2. Explanation

  • Student Class:
    • Represents a student record with student_id, name, and grade.
    • The __str__ method provides a readable string representation of the student.
  • Node Class:
    • Represents a node in the linked list containing a Student object and a reference to the next node.
  • LinkedList Class:
    • Manages the linked list operations.
    • Insertion Methods:
      • insert_at_beginning: Inserts a student at the start of the list.
      • insert_at_end: Inserts a student at the end of the list.
      • insert_after_position: Inserts a student after a specified position.
    • Deletion Methods:
      • delete_from_beginning: Removes the first student in the list.
      • delete_from_end: Removes the last student in the list.
      • delete_at_position: Removes a student from a specified position.
    • Display Method:
      • display: Prints all student records with their positions.
    • Copy Method:
      • copy_list: Creates a deep copy of the current linked list by creating new Student and Node instances.
  • Main Function:
    • Provides a menu-driven interface for performing linked list operations.
    • Allows the user to copy the linked list and display the copied list separately.

4.3. Example Run

--- Linked List Operations Menu ---

1. Insert at Beginning

2. Insert at End

3. Insert after Position

4. Delete from Beginning

5. Delete from End

6. Delete at Position

7. Display Linked List

8. Copy Linked List

9. Display Copied Linked List

10. Exit

Enter your choice: 1

Enter Student ID: S301

Enter Student Name: Liam

Enter Student Grade: A

Inserted at beginning: ID: S301, Name: Liam, Grade: A

 

--- Linked List Operations Menu ---

1. Insert at Beginning

2. Insert at End

3. Insert after Position

4. Delete from Beginning

5. Delete from End

6. Delete at Position

7. Display Linked List

8. Copy Linked List

9. Display Copied Linked List

10. Exit

Enter your choice: 2

Enter Student ID: S302

Enter Student Name: Mia

Enter Student Grade: B

Inserted at end: ID: S302, Name: Mia, Grade: B

 

--- Linked List Operations Menu ---

1. Insert at Beginning

2. Insert at End

3. Insert after Position

4. Delete from Beginning

5. Delete from End

6. Delete at Position

7. Display Linked List

8. Copy Linked List

9. Display Copied Linked List

10. Exit

Enter your choice: 3

Enter position after which to insert: 1

Enter Student ID: S303

Enter Student Name: Noah

Enter Student Grade: A-

Inserted after position 1: ID: S303, Name: Noah, Grade: A-

 

--- Linked List Operations Menu ---

1. Insert at Beginning

2. Insert at End

3. Insert after Position

4. Delete from Beginning

5. Delete from End

6. Delete at Position

7. Display Linked List

8. Copy Linked List

9. Display Copied Linked List

10. Exit

Enter your choice: 7

Linked List elements:

Position 1: ID: S301, Name: Liam, Grade: A

Position 2: ID: S303, Name: Noah, Grade: A-

Position 3: ID: S302, Name: Mia, Grade: B

 

--- Linked List Operations Menu ---

1. Insert at Beginning

2. Insert at End

3. Insert after Position

4. Delete from Beginning

5. Delete from End

6. Delete at Position

7. Display Linked List

8. Copy Linked List

9. Display Copied Linked List

10. Exit

Enter your choice: 4

Deleted from beginning: ID: S301, Name: Liam, Grade: A

 

--- Linked List Operations Menu ---

1. Insert at Beginning

2. Insert at End

3. Insert after Position

4. Delete from Beginning

5. Delete from End

6. Delete at Position

7. Display Linked List

8. Copy Linked List

9. Display Copied Linked List

10. Exit

Enter your choice: 7

Linked List elements:

Position 1: ID: S303, Name: Noah, Grade: A-

Position 2: ID: S302, Name: Mia, Grade: B

 

--- Linked List Operations Menu ---

1. Insert at Beginning

2. Insert at End

3. Insert after Position

4. Delete from Beginning

5. Delete from End

6. Delete at Position

7. Display Linked List

8. Copy Linked List

9. Display Copied Linked List

10. Exit

Enter your choice: 8

Inserted at end: ID: S303, Name: Noah, Grade: A-

Inserted at end: ID: S302, Name: Mia, Grade: B

Linked List copied successfully.

 

--- Linked List Operations Menu ---

1. Insert at Beginning

2. Insert at End

3. Insert after Position

4. Delete from Beginning

5. Delete from End

6. Delete at Position

7. Display Linked List

8. Copy Linked List

9. Display Copied Linked List

10. Exit

Enter your choice: 9

Linked List elements:

Position 1: ID: S303, Name: Noah, Grade: A-

Position 2: ID: S302, Name: Mia, Grade: B

 

--- Linked List Operations Menu ---

1. Insert at Beginning

2. Insert at End

3. Insert after Position

4. Delete from Beginning

5. Delete from End

6. Delete at Position

7. Display Linked List

8. Copy Linked List

9. Display Copied Linked List

10. Exit

Enter your choice: 10

Exiting...

5. Sorting and Searching

Problem Statement

Write Python programs to perform Sequential (Linear) and Binary searches, as well as Quick Sort, Merge Sort, Bubble Sort, and Selection Sort on student records.

Description

This section includes implementations of fundamental searching and sorting algorithms applied to student records. Each algorithm includes a Python program with comments and explanations. The student records consist of Student ID, Name, and Grade.


5.1. Searching Algorithms

5.1.1. Linear (Sequential) Search

Description: Linear search traverses the list sequentially to find the target student based on Student ID.

Implementation:

class Student:

    def __init__(self, student_id, name, grade):

        self.student_id = student_id

        self.name = name

        self.grade = grade

 

    def __str__(self):

        return f"ID: {self.student_id}, Name: {self.name}, Grade: {self.grade}"

 

def linear_search(students, target_id):

    for index, student in enumerate(students):

        if student.student_id == target_id:

            return index

    return -1

 

def main():

    print("Linear Search for Student Records")

    n = int(input("Enter number of students: "))

    students = []

    for _ in range(n):

        student_id = input("Enter Student ID: ")

        name = input("Enter Student Name: ")

        grade = input("Enter Student Grade: ")

        students.append(Student(student_id, name, grade))

   

    target_id = input("Enter Student ID to search: ")

    index = linear_search(students, target_id)

    if index != -1:

        print(f"Student found at index {index}: {students[index]}")

    else:

        print(f"Student with ID {target_id} not found.")

 

if __name__ == "__main__":

    main()

Example Run:

Linear Search for Student Records

Enter number of students: 3

Enter Student ID: S401

Enter Student Name: Olivia

Enter Student Grade: A

Enter Student ID: S402

Enter Student Name: Liam

Enter Student Grade: B+

Enter Student ID: S403

Enter Student Name: Emma

Enter Student Grade: A-

Enter Student ID to search: S402

Student found at index 1: ID: S402, Name: Liam, Grade: B+

5.1.2. Binary Search

Description: Binary search efficiently finds the target student based on Student ID by repeatedly dividing the sorted list in half. Note: The list must be sorted by Student ID before performing binary search.

Implementation:

class Student:

    def __init__(self, student_id, name, grade):

        self.student_id = student_id

        self.name = name

        self.grade = grade

 

    def __str__(self):

        return f"ID: {self.student_id}, Name: {self.name}, Grade: {self.grade}"

 

def binary_search(students, target_id):

    left = 0

    right = len(students) - 1

    while left <= right:

        mid = left + (right - left) // 2

        if students[mid].student_id == target_id:

            return mid

        elif students[mid].student_id < target_id:

            left = mid + 1

        else:

            right = mid - 1

    return -1

 

def main():

    print("Binary Search for Student Records (List must be sorted by Student ID)")

    n = int(input("Enter number of students: "))

    students = []

    for _ in range(n):

        student_id = input("Enter Student ID: ")

        name = input("Enter Student Name: ")

        grade = input("Enter Student Grade: ")

        students.append(Student(student_id, name, grade))

   

    # Sorting the list by Student ID to prepare for binary search

    students.sort(key=lambda x: x.student_id)

    print("\nStudents sorted by Student ID:")

    for student in students:

        print(student)

   

    target_id = input("\nEnter Student ID to search: ")

    index = binary_search(students, target_id)

    if index != -1:

        print(f"Student found at index {index}: {students[index]}")

    else:

        print(f"Student with ID {target_id} not found.")

 

if __name__ == "__main__":

    main()

Example Run:

Binary Search for Student Records (List must be sorted by Student ID)

Enter number of students: 3

Enter Student ID: S501

Enter Student Name: Sophia

Enter Student Grade: A

Enter Student ID: S503

Enter Student Name: Jackson

Enter Student Grade: B

Enter Student ID: S502

Enter Student Name: Ava

Enter Student Grade: A-

 

Students sorted by Student ID:

ID: S501, Name: Sophia, Grade: A

ID: S502, Name: Ava, Grade: A-

ID: S503, Name: Jackson, Grade: B

 

Enter Student ID to search: S502

Student found at index 1: ID: S502, Name: Ava, Grade: A-

5.2. Sorting Algorithms

5.2.1. Bubble Sort

Description: Bubble Sort repeatedly steps through the list, compares adjacent elements, and swaps them if they are in the wrong order based on Student ID.

Implementation:

class Student:

    def __init__(self, student_id, name, grade):

        self.student_id = student_id

        self.name = name

        self.grade = grade

 

    def __str__(self):

        return f"ID: {self.student_id}, Name: {self.name}, Grade: {self.grade}"

 

def bubble_sort(students):

    n = len(students)

    for i in range(n):

        swapped = False

        for j in range(0, n-i-1):

            if students[j].student_id > students[j+1].student_id:

                students[j], students[j+1] = students[j+1], students[j]

                swapped = True

        if not swapped:

            break

 

def display_students(students):

    for student in students:

        print(student)

 

def main():

    print("Bubble Sort for Student Records")

    n = int(input("Enter number of students: "))

    students = []

    for _ in range(n):

        student_id = input("Enter Student ID: ")

        name = input("Enter Student Name: ")

        grade = input("Enter Student Grade: ")

        students.append(Student(student_id, name, grade))

   

    print("\nStudents before sorting:")

    display_students(students)

   

    bubble_sort(students)

   

    print("\nStudents after Bubble Sort by Student ID:")

    display_students(students)

 

if __name__ == "__main__":

    main()

Example Run:

Bubble Sort for Student Records

Enter number of students: 3

Enter Student ID: S601

Enter Student Name: Isabella

Enter Student Grade: A

Enter Student ID: S603

Enter Student Name: Ethan

Enter Student Grade: B+

Enter Student ID: S602

Enter Student Name: Mia

Enter Student Grade: A-

 

Students before sorting:

ID: S601, Name: Isabella, Grade: A

ID: S603, Name: Ethan, Grade: B+

ID: S602, Name: Mia, Grade: A-

 

Students after Bubble Sort by Student ID:

ID: S601, Name: Isabella, Grade: A

ID: S602, Name: Mia, Grade: A-

ID: S603, Name: Ethan, Grade: B+

 

5.2.2. Selection Sort

Description: Selection Sort divides the list into a sorted and unsorted region. It repeatedly selects the smallest Student ID from the unsorted region and moves it to the end of the sorted region.

Implementation:

class Student:

    def __init__(self, student_id, name, grade):

        self.student_id = student_id

        self.name = name

        self.grade = grade

 

    def __str__(self):

        return f"ID: {self.student_id}, Name: {self.name}, Grade: {self.grade}"

 

def selection_sort(students):

    n = len(students)

    for i in range(n):

        min_idx = i

        for j in range(i+1, n):

            if students[j].student_id < students[min_idx].student_id:

                min_idx = j

        if min_idx != i:

            students[i], students[min_idx] = students[min_idx], students[i]

 

def display_students(students):

    for student in students:

        print(student)

 

def main():

    print("Selection Sort for Student Records")

    n = int(input("Enter number of students: "))

    students = []

    for _ in range(n):

        student_id = input("Enter Student ID: ")

        name = input("Enter Student Name: ")

        grade = input("Enter Student Grade: ")

        students.append(Student(student_id, name, grade))

   

    print("\nStudents before sorting:")

    display_students(students)

   

    selection_sort(students)

   

    print("\nStudents after Selection Sort by Student ID:")

    display_students(students)

 

if __name__ == "__main__":

    main()

 

Example Run:

Selection Sort for Student Records

Enter number of students: 3

Enter Student ID: S701

Enter Student Name: Lucas

Enter Student Grade: B

Enter Student ID: S703

Enter Student Name: Charlotte

Enter Student Grade: A

Enter Student ID: S702

Enter Student Name: Amelia

Enter Student Grade: A-

 

Students before sorting:

ID: S701, Name: Lucas, Grade: B

ID: S703, Name: Charlotte, Grade: A

ID: S702, Name: Amelia, Grade: A-

 

Students after Selection Sort by Student ID:

ID: S701, Name: Lucas, Grade: B

ID: S702, Name: Amelia, Grade: A-

ID: S703, Name: Charlotte, Grade: A

 

5.2.3. Insertion Sort

Description: Insertion Sort builds the sorted list one student at a time by repeatedly picking the next student and inserting it into the correct position based on Student ID.

Implementation:

 

class Student:

    def __init__(self, student_id, name, grade):

        self.student_id = student_id

        self.name = name

        self.grade = grade

 

    def __str__(self):

        return f"ID: {self.student_id}, Name: {self.name}, Grade: {self.grade}"

 

def insertion_sort(students):

    for i in range(1, len(students)):

        key_student = students[i]

        j = i - 1

        while j >= 0 and students[j].student_id > key_student.student_id:

            students[j + 1] = students[j]

            j -= 1

        students[j + 1] = key_student

 

def display_students(students):

    for student in students:

        print(student)

 

def main():

    print("Insertion Sort for Student Records")

    n = int(input("Enter number of students: "))

    students = []

    for _ in range(n):

        student_id = input("Enter Student ID: ")

        name = input("Enter Student Name: ")

        grade = input("Enter Student Grade: ")

        students.append(Student(student_id, name, grade))

   

    print("\nStudents before sorting:")

    display_students(students)

   

    insertion_sort(students)

   

    print("\nStudents after Insertion Sort by Student ID:")

    display_students(students)

 

if __name__ == "__main__":

    main()

Example Run:

Insertion Sort for Student Records

Enter number of students: 3

Enter Student ID: S801

Enter Student Name: Mason

Enter Student Grade: B+

Enter Student ID: S803

Enter Student Name: Harper

Enter Student Grade: A

Enter Student ID: S802

Enter Student Name: Ella

Enter Student Grade: A-

 

Students before sorting:

ID: S801, Name: Mason, Grade: B+

ID: S803, Name: Harper, Grade: A

ID: S802, Name: Ella, Grade: A-

 

Students after Insertion Sort by Student ID:

ID: S801, Name: Mason, Grade: B+

ID: S802, Name: Ella, Grade: A-

ID: S803, Name: Harper, Grade: A

 

5.2.4. Quick Sort

Description: Quick Sort is a divide-and-conquer algorithm that selects a 'pivot' student and partitions the list into sublists of students with Student ID less than and greater than the pivot, then recursively sorts the sublists.

Implementation:

 

class Student:

    def __init__(self, student_id, name, grade):

        self.student_id = student_id

        self.name = name

        self.grade = grade

 

    def __str__(self):

        return f"ID: {self.student_id}, Name: {self.name}, Grade: {self.grade}"

 

def partition(students, low, high):

    pivot = students[high].student_id

    i = low - 1

    for j in range(low, high):

        if students[j].student_id < pivot:

            i += 1

            students[i], students[j] = students[j], students[i]

    students[i + 1], students[high] = students[high], students[i + 1]

    return i + 1

 

def quick_sort(students, low, high):

    if low < high:

        pi = partition(students, low, high)

        quick_sort(students, low, pi - 1)

        quick_sort(students, pi + 1, high)

 

def display_students(students):

    for student in students:

        print(student)

 

def main():

    print("Quick Sort for Student Records")

    n = int(input("Enter number of students: "))

    students = []

    for _ in range(n):

        student_id = input("Enter Student ID: ")

        name = input("Enter Student Name: ")

        grade = input("Enter Student Grade: ")

        students.append(Student(student_id, name, grade))

   

    print("\nStudents before sorting:")

    display_students(students)

   

    quick_sort(students, 0, len(students) - 1)

   

    print("\nStudents after Quick Sort by Student ID:")

    display_students(students)

 

if __name__ == "__main__":

    main()

Example Run:

Quick Sort for Student Records

Enter number of students: 3

Enter Student ID: S901

Enter Student Name: Benjamin

Enter Student Grade: A-

Enter Student ID: S903

Enter Student Name: Abigail

Enter Student Grade: B

Enter Student ID: S902

Enter Student Name: Lucas

Enter Student Grade: A

 

Students before sorting:

ID: S901, Name: Benjamin, Grade: A-

ID: S903, Name: Abigail, Grade: B

ID: S902, Name: Lucas, Grade: A

 

Students after Quick Sort by Student ID:

ID: S901, Name: Benjamin, Grade: A-

ID: S902, Name: Lucas, Grade: A

ID: S903, Name: Abigail, Grade: B

 

5.2.5. Merge Sort

Description: Merge Sort is a divide-and-conquer algorithm that divides the list into halves, recursively sorts each half, and then merges the sorted halves.

Implementation:

 

class Student:

    def __init__(self, student_id, name, grade):

        self.student_id = student_id

        self.name = name

        self.grade = grade

 

    def __str__(self):

        return f"ID: {self.student_id}, Name: {self.name}, Grade: {self.grade}"

 

def merge(left, right):

    merged = []

    i = j = 0

    while i < len(left) and j < len(right):

        if left[i].student_id <= right[j].student_id:

            merged.append(left[i])

            i += 1

        else:

            merged.append(right[j])

            j += 1

    # Append remaining elements

    merged.extend(left[i:])

    merged.extend(right[j:])

    return merged

 

def merge_sort(students):

    if len(students) <= 1:

        return students

    mid = len(students) // 2

    left = merge_sort(students[:mid])

    right = merge_sort(students[mid:])

    return merge(left, right)

 

def display_students(students):

    for student in students:

        print(student)

 

def main():

    print("Merge Sort for Student Records")

    n = int(input("Enter number of students: "))

    students = []

    for _ in range(n):

        student_id = input("Enter Student ID: ")

        name = input("Enter Student Name: ")

        grade = input("Enter Student Grade: ")

        students.append(Student(student_id, name, grade))

   

    print("\nStudents before sorting:")

    display_students(students)

   

    sorted_students = merge_sort(students)

   

    print("\nStudents after Merge Sort by Student ID:")

    display_students(sorted_students)

 

if __name__ == "__main__":

    main()

 

Example Run:

Merge Sort for Student Records

Enter number of students: 3

Enter Student ID: S1001

Enter Student Name: Sophia

Enter Student Grade: A

Enter Student ID: S1003

Enter Student Name: Jackson

Enter Student Grade: B

Enter Student ID: S1002

Enter Student Name: Ava

Enter Student Grade: A-

 

Students before sorting:

ID: S1001, Name: Sophia, Grade: A

ID: S1003, Name: Jackson, Grade: B

ID: S1002, Name: Ava, Grade: A-

 

Students after Merge Sort by Student ID:

ID: S1001, Name: Sophia, Grade: A

ID: S1002, Name: Ava, Grade: A-

ID: S1003, Name: Jackson, Grade: B

5.3. Summary of Sorting Algorithms

Algorithm

Time Complexity (Average)

Space Complexity

Stability

Bubble Sort

O(n²)

O(1)

Yes

Selection Sort

O(n²)

O(1)

No

Insertion Sort

O(n²)

O(1)

Yes

Quick Sort

O(n log n)

O(log n)

No

Merge Sort

O(n log n)

O(n)

Yes


6. References and Further Reading

  1. Books:
    • "Introduction to Algorithms" by Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein.
    • "Data Structures and Algorithms in Python" by Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser.
    • "Algorithms in Python" by Robert Sedgewick.
  2. Online Resources:
    • GeeksforGeeks: www.geeksforgeeks.org
    • TutorialsPoint: www.tutorialspoint.com
    • Coursera: Courses on Data Structures and Algorithms.
    • MIT OpenCourseWare: ocw.mit.edu offers free courses and materials.
  3. Interactive Platforms:
  4. Documentation:
    • Wikipedia: Comprehensive articles on all data structures and algorithms.
    • Official Python Documentation: docs.python.org for language-specific details.

 

Comments

Popular posts from this blog

Gujarati Keyboard layout (terafont-varun), Computer Short cut key, Tally short cut key

Word , Excel , Power Point Shortcut Key in Gujarati

Terafont-Varun (Gujarati Typing) Keyboard Layout by "Sama Soyab"

  For Gujarati Typing : Required : Terafont-Varun Font  After Successfully Installed Terafont Varun Open Any Text Editor or any program. Select Font Terafont-Varun -> Ok For more detail please watch below video. Search Topics : Learn terafont varun, Learn terafont chandan, Learn terafont gujarati to english translation, Learn terafont varun keyboard, Learn terafont converter, Learn terafont varun zip, Learn terafont keyboard, Learn terafont kinnari, Learn terafont akash, Learn terafont aakash, Learn terafont akash ttf, Learn terafont aakash gujarati download, Learn terafont akash keyboard, Learn terafont akash download for windows 10, Learn terafont akash font download, Learn terafont arun, Learn terafont border, Learn terafont chandan keyboard, Learn terafont-chandan font, Learn tera font chandana, Learn convert terafont to shruti, Learn convert terafont varun to shruti, Learn terafont varun chart, Learn terafont download, Learn terafont download for windows 10, Learn tera...