A) Define The Following - Terms - (4 Marks) ...
A) Define The Following - Terms - (4 Marks) ...
QUESTION ONE
i) Data structures: A way of organizing and storing data in a computer so that it can
be accessed and modified efficiently. It defines the relationships1 between the data
elements and the operations that can be performed on them.
iii) Queue: A linear data structure that follows the First-In, First-Out (FIFO)
principle. Elements are added to the rear (end) and removed from the front
(beginning).
iv) Abstract Data Type (ADT): A theoretical concept that defines a data type based
on the operations that can be performed on it and the logical properties of these
operations, without specifying the underlying implementation details. It focuses on
what the data type represents and how it behaves.
ii) Justify any three reasons why analysis of algorithms is important (3 marks)
● Efficiency: Analyzing algorithms helps us understand their time and space
complexity, allowing us to choose the most efficient algorithm for a given task,
especially when dealing with large datasets.
● Scalability: By understanding how an algorithm's performance scales with
increasing input size, we can predict its behavior and ensure it remains efficient
as the problem size grows.
● Resource Optimization: Algorithm analysis helps in determining the resources
(CPU time, memory) an algorithm will consume, enabling us to optimize resource
usage and avoid performance bottlenecks.
Iteration: A programming technique that uses loops (like for or while) to repeatedly
execute a block of code until a certain condition is met.
Python Example:
Python
In the recursive example, factorial_recursive calls itself with a smaller value of n until n
becomes 0. In the iterative example, a for loop is used to repeatedly multiply numbers
from 1 to n. Recursion often leads to more concise and elegant code for problems
with self-similar subproblems, but it can have higher overhead due to function call
stack management. Iteration is generally more efficient in terms of memory usage and
speed for simple repetitive tasks.
One disadvantage of a basic Binary Tree is that if it's not balanced, it can become
skewed, resembling a linked list in its worst-case structure. This can lead to a worst-
case time complexity of O(n) for operations like search, insertion, and deletion, where
'n' is the number of nodes, negating the potential for logarithmic time complexity that
balanced binary trees offer.
ii) List any two conditions that should be satisfied when an array type is
appropriate for representing an abstract data type (2 marks)
● Fixed or Predictable Size: When the maximum number of elements in the ADT is
known or can be estimated beforehand, an array with a fixed size can be
efficiently used.
● Frequent Access by Index: If the ADT requires frequent access to elements
based on their position (index), arrays provide constant-time (O(1)) access,
making them suitable.
Algorithm SelectionSort(array)
Input: An unsorted array.
Output: The sorted array.
Steps:
1. For i from 0 to length(array) - 2:
2. min_index = i
3. For j from i + 1 to length(array) - 1:
4. If array[j] < array[min_index]:
5. min_index = j
6. If min_index is not equal to i:
7. Swap array[i] and array[min_index]
Note: Bubble sort is also a sorting algorithm. If you intended a searching algorithm,
perhaps you meant Binary Search (which requires a sorted array). I will provide the
Bubble Sort algorithm as requested.
Algorithm BubbleSort(array)
Input: An unsorted array.
Output: The sorted array.
Steps:
1. n = length(array)
2. For i from 0 to n - 2:
3. swapped = false
4. For j from 0 to n - i - 2:
5. If array[j] > array[j + 1]:
6. Swap array[j] and array[j + 1]
7. swapped = true
8. If swapped is false:
9. Break // Optimization: if no swaps occur, the array is sorted
iii) State the most efficient of the two algorithms, justify your answer (2 marks)
Selection sort is generally more efficient than bubble sort in terms of the number of
swaps. Bubble sort can perform many swaps even if the array is nearly sorted.
Selection sort performs at most n-1 swaps in total.
In terms of time complexity, both selection sort and bubble sort have a time
complexity of O(n²) in the average and worst cases. Therefore, asymptotically, they
are considered to have the same efficiency in terms of growth rate. However, due to
the lower number of swaps, selection sort often performs slightly better in practice,
especially when writes to memory are expensive operations.
QUESTION TWO
A linked list is a linear data structure in which elements are not stored in contiguous memory
locations. Instead, each element (called a node) contains4 two parts: the data itself and a
pointer (or reference) to the next node in the sequence. The first node of the list is called the
head, and the last node's pointer typically points to null or a special end marker. This
structure allows for efficient insertion and deletion of elements at any position without
needing to shift other elements.
ii) Outline the properties of the linked list abstract data type (4 marks)
● Sequential Access: Elements in a linked list are accessed sequentially, starting
from the head and following the pointers to the desired element. Direct access
by index (like in arrays) is not efficient.
● Dynamic Size: Linked lists can grow or shrink dynamically during runtime as
nodes are added or removed, without a predefined size limit (within memory
constraints).
● Efficient Insertion and Deletion: Inserting or deleting an element at any position
in a linked list can be done in O(1) time (after finding the position), as it only
involves updating a few pointers, without shifting other elements.
● Memory Overhead: Linked lists require extra memory to store the pointers
associated with each node, which is an overhead compared to arrays where
elements are stored contiguously.
Steps:
1. If head is null, return null (empty list).
2. If head's data is equal to value:
3. Return head.next // Delete the head node
4. current = head
5. while current.next is not null:
6. if current.next.data is equal to value:
7. current.next = current.next.next // Bypass the node to be deleted
8. return head // Element found and deleted
9. current = current.next
10. return head // Element not found
bi) Write a pseudo code algorithm that prompts the user for three integers,
evaluates the largest and prints the maximum (4 marks)
Algorithm FindMaximum
Input: None (prompts user for input)
Output: The largest of the three entered integers.
Steps:
1. Prompt the user to enter the first integer and store it in variable num1.
2. Prompt the user to enter the second integer and store it in variable num2.
3. Prompt the user to enter the third integer and store it in variable num3.
4. Initialize a variable max_num with the value of num1.
5. If num2 is greater than max_num, set max_num = num2.
6. If num3 is greater than max_num, set max_num = num3.
7. Print the value of max_num as the maximum.
ii) Implement the algorithm above into a program using a high-level language (4
marks)
Python
def find_maximum():
"""Prompts the user for three integers and prints the maximum."""
try:
num1 = int(input("Enter the first integer: "))
num2 = int(input("Enter the second integer: "))
num3 = int(input("Enter the third integer: "))
max_num = num1
if num2 > max_num:
max_num = num2
if num3 > max_num:
max_num = num3
except ValueError:
print("Invalid input. Please enter integers only.")
if __name__ == "__main__":
find_maximum()
QUESTION FOUR
A Stack ADT is a linear data structure that follows the Last-In, First-Out (LIFO)
principle. Elements can only be added to (pushed onto) or removed from (popped off)
the top of the stack.
ii) Write an algorithm that demonstrates the push and pop stack fundamental
operations (8 marks)
Algorithm StackOperationsDemo
Input: None
Output: Demonstrates push and pop operations on a stack.
Steps:
1. Create an empty stack called myStack.
2. Print "Pushing elements onto the stack:"
3. push(myStack, 10)
4. Print "Pushed: 10"
5. push(myStack, 20)
6. Print "Pushed: 20"
7. push(myStack, 30)
8. Print "Pushed: 30"
9. Print "Top element:", peek(myStack)
10. Print "\nPopping elements from the stack:"
11. If not isEmpty(myStack):
12. popped_item = pop(myStack)
13. Print "Popped:", popped_item
14. If not isEmpty(myStack):
15. popped_item = pop(myStack)
16. Print "Popped:", popped_item
17. If not isEmpty(myStack):
18. popped_item = pop(myStack)
19. Print "Popped:", popped_item
20. Print "\nTrying to pop from an empty stack:"
21. If not isEmpty(myStack):
22. popped_item = pop(myStack)
23. Print "Popped:", popped_item
24. Else:
25. Print "Stack is empty, cannot pop."
iii) Briefly explain any two applications of stack in computer science (4 marks)
● Function Call Stack: When a program executes, function calls are managed
using a stack. When a function is called, its information (return address, local
variables, parameters) is pushed onto the stack. When the function finishes, this
information is popped off, allowing the program to return to the correct point.
● Expression Evaluation: Stacks are used in evaluating arithmetic expressions,
particularly for converting infix expressions to postfix (Reverse Polish Notation)
and then evaluating the postfix expressions. They help manage operator
precedence and operands.
bi) Define the term Abstract Data Type (ADT) and hence give its properties (6
marks)
Properties of ADTs:
● Abstraction: Focuses on the "what" (operations and behavior) rather than the
"how" (implementation details).
● Encapsulation: Bundles data and the operations that act on that data, hiding the
internal representation.
● Information Hiding: The internal structure and implementation of the ADT are
hidden from the user, who interacts with it only through the defined interface.
● Modularity: ADTs promote modular design, allowing for the creation of reusable
and independent components.
● Well-defined Interface: ADTs have a clear and consistent set of operations that
users can rely on.
QUESTION FIVE
Steps:
1. If position is less than 1 or greater than length(list) + 1:
2. Print "Invalid insertion position."
3. Return list
4. If the list is implemented using an array (with a fixed maximum size):
5. If length(list) equals maximum_size:
6. Print "List is full, cannot insert."
7. Return list
8. For i from length(list) down to position:
9. list[i] = list[i - 1] // Shift elements to the right
10. list[position - 1] = element // Insert the new element
11. Increment the length of the list
12. Else if the list is implemented using a linked list:
13. Create a new node with the given element.
14. If position is 1:
15. new_node.next = head
16. head = new_node
17. Else:
18. current = head
19. For i from 1 to position - 2:
20. If current is null:
21. Print "Invalid insertion position."
22. Return list
23. current = current.next
24. new_node.next = current.next
25. current.next = new_node
26. Return the (potentially modified) list (or head of the linked list).
c) Write an algorithm that explains the pop and push operations in a stack (8
marks)
Steps:
1. If operation is 'push':
2. Create a new node (if using linked list) or find the next available slot
Sources
1. https://www.fireblazeaischool.in/blogs/mastering-data-analytics-interview-questions-and-
answers-for-zomato/
2. https://github.com/Akotz89/IterationAndRecursion
3. https://www.simplilearn.com/big-o-notation-in-data-structure-article
4. https://fastercapital.com/content/The-Art-of-Efficiency--Mastering-Time-Complexity-at-IOI.html
5. https://www.scribd.com/document/781415549/Linear-data-structures
6. https://github.com/shubham9397/Python-