0% found this document useful (0 votes)
5 views26 pages

DSA Assignment 1

This document is an assignment on Data Structures and Algorithms, covering various topics such as arrays, linked lists, stacks, queues, trees, and graphs. It includes definitions, real-life examples, time and space complexities, advantages, disadvantages, and code examples in Python for each data structure. The document serves as a comprehensive guide for students in the AI program at the University of Haripur's Department of Computer Science.

Uploaded by

br727534
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views26 pages

DSA Assignment 1

This document is an assignment on Data Structures and Algorithms, covering various topics such as arrays, linked lists, stacks, queues, trees, and graphs. It includes definitions, real-life examples, time and space complexities, advantages, disadvantages, and code examples in Python for each data structure. The document serves as a comprehensive guide for students in the AI program at the University of Haripur's Department of Computer Science.

Uploaded by

br727534
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

DATA STRUCTURES

AND ALGORITHMS

Assignment No. 1 · Section A · Program: AI

Course: Data Structures and Algorithms

Instructor: Aisha Farid

Student Name : _______________________________

Roll Number : _______________________________

Submission Date : ___________________________

University of Haripur · Department of Computer Science


■ Table of Contents
1. Introduction to Data Structures and Algorithms ...... 3
...................
...................
2. Arrays ........ 4
...................
3. Linked Lists (Singly & Doubly) .. 5
...................
...................
4. Stacks ........ 7
...................
...................
5. Queues ........ 8
...................
6. Trees (Binary Tree & BST) ....... 9
...................
7. Graphs (BFS & DFS) ............. 11
...................
8. Searching Algorithms ............ 13
...................
9. Sorting Algorithms .............. 14
...............
...............
9.1 Bubble Sort .. 14
...............
..............
9.2 Selection Sort 15
...............
..............
9.3 Insertion Sort 16
...............
...............
9.4 Merge Sort ... 17
...............
...............
9.5 Quick Sort ... 18
...................
10. Comparison Tables .............. 19
...................
11. Real-World Applications ........ 20
...................
...................
12. Conclusion .. 21
...................
...................
13. References .. 21
1. Introduction to Data Structures and Algorithms

What is a Data Structure?


A data structure is a systematic way of organising, managing, and storing data in a computer so
that it can be accessed and modified efficiently. Think of it like a filing cabinet: data can be placed in
labelled folders (arrays), chained notebooks (linked lists), or stacked trays (stacks). The choice of
data structure directly affects the speed and memory usage of a program.

What is an Algorithm?
An algorithm is a well-defined, step-by-step procedure for solving a problem or performing a
computation. Algorithms act as recipes: given the same ingredients (input), a correct algorithm
always produces the correct dish (output). Algorithms must be correct, efficient, and unambiguous.

Why Study DSA?


■ Mobile & Web Apps — Maps use graph algorithms; social feeds use queues.
■ Search Engines — Google indexes billions of pages using advanced tree structures.
■ Banking Systems — Transaction histories are maintained using linked lists and stacks.
■ Games — Pathfinding in games like Minecraft uses BFS/DFS on graphs.
■ Artificial Intelligence — Decision trees and priority queues power AI models.
■ Performance — The right data structure can reduce execution time from hours to
milliseconds.

■ Key Insight: A program without an efficient data structure is like a library without a catalogue —
everything exists, but finding or organising it becomes painfully slow.
2. Arrays

Definition
An array is a collection of elements stored in contiguous memory locations. All elements share
the same data type and are accessed via an integer index starting at 0.

Diagram – 1D Array
Index: 0 1 2 3 4

Value: 10 20 30 40 50

Figure 1: A one-dimensional array of 5 integers.

Real-Life Example
Monthly temperatures recorded by a weather station — each month's reading is stored at a specific
index. Temperature[0] = January, Temperature[11] = December.

Time & Space Complexity


Best Average Worst Space

O(1) Access O(n) Search O(n) Insert/Delete O(n)

Advantages Disadvantages
✔ Constant-time access by index ✘ Fixed size (static arrays)
✔ Simple and easy to implement ✘ Costly insertion/deletion in middle
✔ Cache-friendly (contiguous memory) ✘ Wasted memory if not full
✔ Low memory overhead ✘ Homogeneous — one data type only

Code Example (Python)


# Declare and initialize an array
arr = [10, 20, 30, 40, 50]

# Access element
print(arr[2]) # Output: 30

# Insert at end
[Link](60) # [10, 20, 30, 40, 50, 60]

# Delete element
[Link](20) # [10, 30, 40, 50, 60]

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

print(linear_search(arr, 40)) # Output: 2


3. Linked Lists

3.1 Singly Linked List


A singly linked list is a linear data structure where each element (called a node) contains a data
field and a pointer to the next node. Unlike arrays, nodes are not stored in contiguous memory;
they are connected by pointers.

Diagram – Singly Linked List


[10 | [20 | [30 |
[HEAD] → *] → *] → NULL]

Figure 2: Singly linked list with 3 nodes. Each node stores data and a pointer.

Real-Life Example
A music playlist — each song knows the next song to play, but you cannot go back without
restarting from the head (in a singly linked list).

Time & Space Complexity


Best Average Worst Space

O(1) Insert at Head O(n) Search O(n) Delete O(n)

Advantages Disadvantages
✔ Dynamic size — grows/shrinks at runtime ✘ O(n) access — no random access by
✔ Efficient insertion/deletion at head index
✔ No memory wastage (allocates as ✘ Extra memory for storing pointers
needed) ✘ Not cache-friendly
✔ Foundation for stacks and queues ✘ Reverse traversal not possible

Code Example (Python)


class Node:
def __init__(self, data):
[Link] = data
[Link] = None

class SinglyLinkedList:
def __init__(self):
[Link] = None

def insert_at_head(self, data):


new_node = Node(data)
new_node.next = [Link]
[Link] = new_node

def display(self):
curr = [Link]
while curr:
print([Link], end=' -> ')
curr = [Link]
print('NULL')

ll = SinglyLinkedList()
ll.insert_at_head(30)
ll.insert_at_head(20)
ll.insert_at_head(10)
[Link]() # 10 -> 20 -> 30 -> NULL

3.2 Doubly Linked List


A doubly linked list extends the singly linked list by adding a previous pointer to each node,
enabling traversal in both directions.

Diagram – Doubly Linked List


[* | [* | [* |
NULL 10 | 20 | 30 | →
← *] ■ *] ■ *] NULL

Figure 3: Doubly linked list — each node has two pointers.

Best Average Worst Space

O(1) Insert/Delete at
ends O(n) Search O(n) Worst O(n)

Advantages Disadvantages
✔ Bidirectional traversal ✘ Extra memory for prev pointer
✔ Easy deletion of a given node ✘ More complex implementation
✔ Can be used as deque ✘ Slightly slower due to extra pointer
✔ Better for certain algorithms updates
✘ Higher pointer management overhead
4. Stacks

Definition
A stack is a linear data structure that follows the LIFO (Last In, First Out) principle — the last
element inserted is the first to be removed. Operations are performed only from one end called the
top.

Diagram – Stack Operations


PUSH 10 PUSH 20 PUSH 30 POP

[10] [20] [30]

[10] [20] [20]

[10] [10]

■■■■■ ■■■■■ ■■■■■ ■■■■■

BASE BASE BASE BASE

Figure 4: Stack operations – PUSH adds to top, POP removes from top.

Real-Life Example
The Undo feature in text editors — every action is pushed onto a stack. Pressing Ctrl+Z pops the
last action and reverts it. Browser back-button history also uses a stack.

Time & Space Complexity


Best Average Worst Space

O(1) Push O(1) Pop O(1) Peek O(n)

Advantages Disadvantages
✔ Very fast O(1) operations ✘ Limited access — only top element
✔ Simple implementation ✘ Can cause stack overflow if unbounded
✔ Useful for recursion and backtracking ✘ Not suitable for random access
✔ Memory-efficient for LIFO scenarios ✘ Inflexible ordering

Code Example (Python)


class Stack:
def __init__(self):
[Link] = []

def push(self, item): # Add to top


[Link](item)

def pop(self): # Remove from top


if not self.is_empty():
return [Link]()
return 'Stack Underflow'

def peek(self): # View top


return [Link][-1] if [Link] else None

def is_empty(self):
return len([Link]) == 0

s = Stack()
[Link](10); [Link](20); [Link](30)
print([Link]()) # 30
print([Link]()) # 20
5. Queues

Definition
A queue is a linear data structure that follows the FIFO (First In, First Out) principle — the first
element inserted is the first to be removed. Insertion (enqueue) occurs at the rear and removal
(dequeue) at the front.

Diagram – Queue Operations


FRONT → [10] [20] [30] ← REAR

DEQUEUE: [20] [30]

Figure 5: Queue — elements enter at rear and leave at front.

Real-Life Example
A ticket booking queue at a cinema — the first person who arrives is the first served. Similarly, print
spoolers, CPU task scheduling, and network packet handling all use queues.

Time & Space Complexity


Best Average Worst Space

O(1) Enqueue O(1) Dequeue O(1) Peek O(n)

Advantages Disadvantages
✔ FIFO ensures fairness ✘ No random access
✔ Fast O(1) operations ✘ Fixed-size queues may overflow
✔ Ideal for scheduling tasks ✘ Inefficient for priority-based ordering
✔ Foundation of BFS graph algorithm ✘ Requires extra pointers for linked
implementation

Code Example (Python)


from collections import deque

class Queue:
def __init__(self):
self.q = deque()

def enqueue(self, item): # Add to rear


[Link](item)

def dequeue(self): # Remove from front


if self.q:
return [Link]()
return 'Queue Empty'

def front(self):
return self.q[0] if self.q else None

q = Queue()
[Link](10); [Link](20); [Link](30)
print([Link]()) # 10
print([Link]()) # 20
6. Trees (Binary Tree & BST)

6.1 Binary Tree


A binary tree is a hierarchical data structure where each node has at most two children, referred
to as the left child and right child. The topmost node is the root. Nodes with no children are called
leaves.

Diagram – Binary Tree

[50] ← Root
/ \
[30] [70] ← Internal Nodes
/ \ / \
[20] [40][60] [80] ← Leaf Nodes

Figure 6: A binary tree with height 2.

Key Terminology
Root: Topmost node of the tree.
Height: Number of edges on the longest root-to-leaf path.
Depth: Number of edges from root to a given node.
Leaf: Node with no children.
Subtree: A node and all its descendants.

6.2 Binary Search Tree (BST)


A Binary Search Tree is a binary tree with an ordering property: for every node, all values in its left
subtree are less than the node's value, and all values in its right subtree are greater. This enables
efficient search.

Diagram – BST

[50]
/ \
[30] [70] BST Property:
/ \ \ Left < Node < Right
[20] [40] [80]

Figure 7: Binary Search Tree. Search 40: 50→30→40 (found in 3 steps).

BST Operations
Best Average Worst Space

O(log n) Search* O(log n) Insert* O(log n) Delete* O(n)


*O(n) in worst case (skewed tree).
Advantages Disadvantages
✔ Efficient O(log n) average operations ✘ Can become unbalanced (skewed)
✔ Sorted traversal via inorder ✘ O(n) worst-case for sorted input
✔ Dynamic insertion and deletion ✘ Complex deletion logic
✔ Foundation of many advanced structures ✘ Requires balancing (AVL, Red-Black) for
guarantees

Code Example – BST Search (Python)

class BSTNode:
def __init__(self, key):
[Link] = key
[Link] = None
[Link] = None

def insert(root, key):


if root is None:
return BSTNode(key)
if key < [Link]:
[Link] = insert([Link], key)
else:
[Link] = insert([Link], key)
return root

def search(root, key):


if root is None or [Link] == key:
return root
if key < [Link]:
return search([Link], key)
return search([Link], key)

root = None
for v in [50, 30, 70, 20, 40, 80]:
root = insert(root, v)
result = search(root, 40)
print([Link]) # 40
7. Graphs (BFS & DFS)

Definition
A graph is a non-linear data structure consisting of a set of vertices (nodes) connected by edges.
Graphs can be directed (edges have direction) or undirected. They can be weighted (edges have
costs) or unweighted.

Diagram – Undirected Graph

A ■■■■ B ■■■■ C
| |
D ■■■■ E

Vertices: {A, B, C, D, E}
Edges: {A-B, B-C, A-D, D-E, B-E}

Figure 8: An undirected graph with 5 vertices and 5 edges.

7.1 Breadth-First Search (BFS)


BFS explores a graph level by level, starting from a source vertex and visiting all neighbours before
moving to their neighbours. It uses a queue. Starting from A in Figure 8: A → B → D → C → E.

7.2 Depth-First Search (DFS)


DFS explores a graph by going as deep as possible along each branch before backtracking. It
uses a stack (or recursion). Starting from A in Figure 8: A → B → C → E → D.

BFS vs DFS Comparison


Feature BFS DFS

Data Structure Used Queue Stack / Recursion

Traversal Order Level by level Deep branch first

Shortest Path Yes (unweighted) No

Memory Usage More (stores all neighbours) Less (one path at a time)

Time Complexity O(V + E) O(V + E)

Best For Shortest path, Level order Cycle detection, Topological sort

Code Example – BFS & DFS (Python)


from collections import deque

graph = {
'A': ['B', 'D'],
'B': ['A', 'C', 'E'],
'C': ['B'],
'D': ['A', 'E'],
'E': ['B', 'D']
}

# BFS – uses a queue


def bfs(graph, start):
visited, queue = set(), deque([start])
[Link](start)
while queue:
node = [Link]()
print(node, end=' ')
for nb in graph[node]:
if nb not in visited:
[Link](nb); [Link](nb)

# DFS – uses recursion


def dfs(graph, node, visited=None):
if visited is None: visited = set()
[Link](node); print(node, end=' ')
for nb in graph[node]:
if nb not in visited:
dfs(graph, nb, visited)

print('BFS:', end=' '); bfs(graph, 'A') # A B D C E


print('\nDFS:', end=' '); dfs(graph, 'A') # A B C E D

Real-Life Example
BFS: Finding the shortest route between two cities on Google Maps. DFS: Solving a maze or puzzle
by exploring each path fully before backtracking.

Best Average Worst Space

O(V2) Adjacency
O(V+E) BFS O(V+E) DFS Matrix O(V+E)
8. Searching Algorithms

8.1 Linear Search


Linear search checks each element one by one from the beginning until the target is found or the
list is exhausted. It works on both sorted and unsorted data.

Best Average Worst Space

O(1) O(n) O(n) O(1)

8.2 Binary Search


Binary search works on a sorted array by repeatedly dividing the search interval in half. If the target
is less than the middle, search the left half; otherwise search the right half.

Diagram – Binary Search

Array: [2, 5, 8, 12, 16, 23, 38, 56, 72, 91] Target: 23

Step 1: low=0, high=9, mid=4 → arr[4]=16 < 23 → search RIGHT


Step 2: low=5, high=9, mid=7 → arr[7]=56 > 23 → search LEFT
Step 3: low=5, high=6, mid=5 → arr[5]=23 = 23 → FOUND at index 5!

Figure 9: Binary search reduces the search space by half each step.

Best Average Worst Space

O(1) iterative / O(log


O(1) O(log n) O(log n) n) recursive

Feature Linear Search Binary Search

Input Requirement Unsorted or sorted Must be sorted

Time Complexity O(n) O(log n)

Space Complexity O(1) O(1) iterative

Best For Small or unsorted data Large sorted datasets

Code Example (Python)


# Binary Search – Iterative
def binary_search(arr, target):
low, high = 0, len(arr) - 1
while low <= high:
mid = (low + high) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
low = mid + 1
else:
high = mid - 1
return -1

arr = [2, 5, 8, 12, 16, 23, 38, 56, 72, 91]


print(binary_search(arr, 23)) # Output: 5
print(binary_search(arr, 99)) # Output: -1
9. Sorting Algorithms

9.1 Bubble Sort


Bubble sort repeatedly compares adjacent elements and swaps them if they are in the wrong
order. Each pass 'bubbles up' the largest unsorted element to its correct position.

Trace – Bubble Sort on [64, 34, 25, 12, 22]

Pass 1: [34, 25, 12, 22, 64] (64 bubbled to end)


Pass 2: [25, 12, 22, 34, 64] (34 bubbled)
Pass 3: [12, 22, 25, 34, 64] (25 bubbled)
Pass 4: [12, 22, 25, 34, 64] (no swaps → sorted!)

Best Average Worst Space

O(n) O(n2) O(n2) O(1)

Advantages Disadvantages
✔ Simple to understand and implement ✘ Very slow for large datasets O(n²)
✔ In-place (no extra memory) ✘ Too many comparisons
✔ Stable sort ✘ Not used in practice

def bubble_sort(arr):
n = len(arr)
for i in range(n):
swapped = False
for j in range(0, n - i - 1):
if arr[j] > arr[j+1]:
arr[j], arr[j+1] = arr[j+1], arr[j]
swapped = True
if not swapped: # Early exit if already sorted
break
return arr

print(bubble_sort([64, 34, 25, 12, 22])) # [12, 22, 25, 34, 64]

9.2 Selection Sort


Selection sort divides the array into sorted and unsorted regions. It repeatedly finds the minimum
element in the unsorted region and swaps it to the beginning of the unsorted region.

Array: [29, 10, 14, 37, 13]


Pass 1: find min=10, swap with 29 → [10, 29, 14, 37, 13]
Pass 2: find min=13, swap with 29 → [10, 13, 14, 37, 29]
Pass 3: find min=14, already in place → [10, 13, 14, 37, 29]
Pass 4: find min=29, swap with 37 → [10, 13, 14, 29, 37]

Best Average Worst Space


O(n2) O(n2) O(n2) O(1)

Advantages Disadvantages
✔ In-place — O(1) extra space ✘ Always O(n²) — no early exit
✔ Fewer swaps than bubble sort ✘ Not stable (can disrupt equal elements)
✔ Simple logic ✘ Slow on large inputs
✔ Works on small datasets ✘ Not adaptive

def selection_sort(arr):
n = len(arr)
for i in range(n):
min_idx = i
for j in range(i+1, n):
if arr[j] < arr[min_idx]:
min_idx = j
arr[i], arr[min_idx] = arr[min_idx], arr[i]
return arr

9.3 Insertion Sort


Insertion sort builds a sorted array one element at a time by inserting each new element into its
correct position within the already-sorted portion. Similar to sorting playing cards in hand.

Best Average Worst Space

O(n) O(n2) O(n2) O(1)

Advantages Disadvantages
✔ O(n) on nearly sorted data ✘ O(n²) on reverse-sorted data
✔ Stable and in-place ✘ Not suitable for large datasets
✔ Simple to implement ✘ More shifts than comparisons
✔ Online — can sort a stream of data ✘ Slower than merge/quick for large n

def insertion_sort(arr):
for i in range(1, len(arr)):
key = arr[i]
j = i - 1
while j >= 0 and arr[j] > key:
arr[j+1] = arr[j]
j -= 1
arr[j+1] = key
return arr

print(insertion_sort([5, 3, 8, 1, 2])) # [1, 2, 3, 5, 8]


9.4 Merge Sort
Merge sort uses the divide-and-conquer technique: it recursively splits the array into halves, sorts
each half, and then merges the two sorted halves into a single sorted array.

[38, 27, 43, 3, 9, 82, 10]


/ \
[38, 27, 43] [3, 9, 82, 10]
/ \ / \
[38] [27, 43] [3, 9] [82, 10]
/ \ / \ / \
[27] [43] [3] [9] [82] [10]
\ / \ / \ /
[27, 43] [3, 9] [10, 82]
\ / /
[27, 38, 43] [3, 9, 10, 82]
\ /
[3, 9, 10, 27, 38, 43, 82]

Figure 10: Merge sort splits and merges recursively.

Best Average Worst Space

O(n log n) O(n log n) O(n log n) O(n)

Advantages Disadvantages
✔ Guaranteed O(n log n) ✘ O(n) extra space needed
✔ Stable sort ✘ Slower for small arrays than insertion sort
✔ Excellent for linked lists ✘ Recursive overhead
✔ Parallelisable — divide independently ✘ Not in-place

def merge_sort(arr):
if len(arr) <= 1:
return arr
mid = len(arr) // 2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
return merge(left, right)

def merge(left, right):


result, i, j = [], 0, 0
while i < len(left) and j < len(right):
if left[i] <= right[j]:
[Link](left[i]); i += 1
else:
[Link](right[j]); j += 1
[Link](left[i:]); [Link](right[j:])
return result

print(merge_sort([38, 27, 43, 3])) # [3, 27, 38, 43]

9.5 Quick Sort


Quick sort selects a pivot element and partitions the array into two subarrays: elements smaller
than the pivot (left) and elements greater (right). It then recursively sorts both subarrays.

Array: [10, 80, 30, 90, 40, 50, 70] Pivot = 70 (last element)

Partition: [10, 30, 40, 50] | 70 | [80, 90]


Recurse LEFT: [10, 30, 40, 50] Pivot=50 → [10,30,40]|50|[]
Recurse RIGHT: [80, 90] Pivot=90 → [80]|90|[]
Result: [10, 30, 40, 50, 70, 80, 90]

Best Average Worst Space

O(n log n) O(n log n) O(n2) bad pivot O(log n)

Advantages Disadvantages
✔ Very fast in practice O(n log n) ✘ O(n²) worst case (sorted input, bad pivot)
✔ In-place — minimal extra memory ✘ Not stable
✔ Cache-friendly ✘ Recursive — risk of stack overflow
✔ Widely used in system libraries (e.g., C++ ✘ Performance depends on pivot selection
std::sort)

def quick_sort(arr):
if len(arr) <= 1:
return arr
pivot = arr[-1]
left = [x for x in arr[:-1] if x <= pivot]
right = [x for x in arr[:-1] if x > pivot]
return quick_sort(left) + [pivot] + quick_sort(right)

print(quick_sort([10, 80, 30, 90, 40, 50, 70]))


# [10, 30, 40, 50, 70, 80, 90]
10. Comparison Tables

10.1 Sorting Algorithms Comparison


Algorithm Best Average Worst Space Stable?

Bubble Sort O(n) O(n²) O(n²) O(1) Yes

Selection Sort O(n²) O(n²) O(n²) O(1) No

Insertion Sort O(n) O(n²) O(n²) O(1) Yes

Merge Sort O(n log n) O(n log n) O(n log n) O(n) Yes

Quick Sort O(n log n) O(n log n) O(n²) O(log n) No

10.2 Data Structures Comparison


Structure Access Search Insertion Deletion Space

Array O(1) O(n) O(n) O(n) O(n)

Linked List O(n) O(n) O(1)* O(1)* O(n)

Stack O(n) O(n) O(1) O(1) O(n)

Queue O(n) O(n) O(1) O(1) O(n)

BST (avg) O(log n) O(log n) O(log n) O(log n) O(n)

Graph (adj list) O(V+E) O(V+E) O(1) O(E) O(V+E)

* At head/tail with pointer; O(n) for arbitrary position.

10.3 Stack vs Queue


Feature Stack Queue

Principle LIFO FIFO

Insert End Top Rear

Remove End Top Front

Use Case Undo, Recursion Scheduling, BFS

Real Example Browser Back Printer Queue


11. Real-World Applications of DSA

■■ Navigation (Maps) Google Maps models roads as a weighted graph. Dijkstra's


Tech: Graphs + algorithm finds the shortest path between two locations by
Dijkstra/BFS exploring vertices with minimum cumulative cost first.

Search engines use Trie data structures (a prefix tree) for


■ Search Engines
auto-complete suggestions and inverted index hash maps to
Tech: Trees + Hashing
retrieve pages containing search terms in milliseconds.

Facebook's friend-of-friend recommendations use BFS on a


■ Social Networks
graph where users are vertices and friendships are edges.
Tech: Graphs + BFS
LinkedIn uses similar techniques for '2nd-degree connections'.

ATM transaction processing uses queues (FIFO) to serve


■ Banking Systems
customers fairly. Undo features in banking apps use stacks to
Tech: Queues + Stacks
roll back recent transactions.

■ Databases Relational databases (MySQL, PostgreSQL) use B-Tree


Tech: B-Trees + indexes to support fast range queries in O(log n) time. Hash
Hashing indexes are used for exact-match lookups in O(1).

■ Artificial Intelligence A* search algorithm — used in robot navigation and game AI —


Tech: Graphs + Priority is a graph traversal algorithm that uses a priority queue
Queues (min-heap) to always explore the most promising path.

■ Bioinformatics DNA sequence alignment uses dynamic programming (similar


Tech: Dynamic to merge sort's divide approach) to find the best match between
Programming + Arrays genetic sequences efficiently.

■ Operating Systems CPU schedulers use priority queues to determine which


Tech: Queues + Linked process runs next. Memory management uses linked lists to
Lists track free and allocated memory blocks.
12. Conclusion
Data Structures and Algorithms form the intellectual backbone of all software engineering. The
choice of an appropriate data structure and algorithm can be the difference between an application
that scales to millions of users and one that crawls to a halt.

Key Takeaways
✔ Arrays give fast random access but are inflexible in size — best for fixed-size, indexed data.
✔ Linked Lists offer dynamic sizing and fast insertion/deletion at the cost of random access.
✔ Stacks and Queues are specialised structures that enforce access order — LIFO and FIFO
respectively.
✔ Trees, particularly BSTs, provide efficient ordered storage and O(log n) operations on
average.
✔ Graphs model relationships in the real world; BFS and DFS are fundamental traversal
strategies.
✔ Searching: Binary search is exponentially faster than linear search on sorted data.
✔ Sorting: For large datasets, always prefer O(n log n) algorithms (Merge Sort, Quick Sort).
✔ No single data structure or algorithm is universally best — the right choice depends on the
problem constraints.

■ Final Thought: Mastering DSA is not about memorising code — it is about developing the
ability to analyse a problem, identify its computational constraints, and select the most efficient
tool from your algorithmic toolkit.
13. References

[1] Cormen, T. H., Leiserson, C. E., Rivest, R. L., & Stein, C. (2022). Introduction to
Algorithms (4th ed.). MIT Press.

[2] Sedgewick, R., & Wayne, K. (2011). Algorithms (4th ed.). Addison-Wesley Professional.

[3] Goodrich, M. T., Tamassia, R., & Goldwasser, M. H. (2014). Data Structures and
Algorithms in Python. Wiley.

[4] GeeksforGeeks. (2024). Data Structures and Algorithms. Retrieved from


[Link]

[5] Khan Academy. (2024). Algorithms. Retrieved from


[Link]

[6] Skiena, S. S. (2020). The Algorithm Design Manual (3rd ed.). Springer.

This assignment was prepared for the Data Structures and Algorithms course — University of Haripur. All code
examples are for educational purposes. Submission Date: _______________

You might also like