GROUP 5B
CAT 2
COM 211: DATA STRUCTURE AND ALGORITHMS
GROUP MEMBERS
1.IAN KIBIWOT. P100/4229G/23 9. MOSES MUSA P100/4241G/23
2.OSCAR OPEMBE. P100/4230G/23 10. JOSHUA MUKAYA. P100/4242G/23
3.KELVIN WANJALA. P100/4231G/23 11. GILBERT OMWATA. P100/4243G/23
4.JUSTIN ODHIAMBO P100/4234G/23 12. OLIVER OOKO P100/4245G/23
5.BIYAKI ABIGAEL P100/4236G/23 13. SHEKINAH GLORY. P100/4247G/23
6.GABRIEL KUBAI. P100/4237G/23 14. PATIENCE LUSENO P100/4248G/23
7.ODONGO EMMANUEL. P100/4239G/23 15. DOMINIC MORANGA. P100/4250G/23
8. KORIR ABIUD P100/4240G/23
Question 5: Write a program that uses a stack to check if a given string
of parentheses is balanced (e.g., "((()))" is balanced,
but "(()" is not).
Explanation
A string is considered balanced if:
• Every opening parenthesis has a corresponding closing parenthesis.
• Parentheses are properly nested (e.g., (()()) is valid, but ())( is not).
Approach Using a Stack
• A stack is a Last In, First Out (LIFO) data structure, making it ideal for tracking matching pairs like
parentheses.
• Steps:
1. Initialize a stack:
• Push ( onto the stack when encountered.
• Pop from the stack when a ) is encountered.
2. Validate the string:
If the stack is empty when trying to pop, it means there’s a closing parenthesis without a matching opening
parenthesis → Not balanced.
If the stack is not empty at the end of the string, there are unmatched opening parentheses → Not balanced.
3. If the stack is empty at the end and all parentheses are properly matched → Balanced.
Pseudocode
Create an empty stack.
Loop through each character in the string:
If it’s (, push it onto the stack.
If it’s ), check:
If the stack is empty → Not balanced.
Otherwise, pop the top of the stack (remove a matching ().
After the loop:
If the stack is empty → Balanced.
Otherwise → Not balanced.
Code: s.pop(); // Match found, remove one opening parenthesis
#include <iostream>
}
#include <stack>
} return s.empty(); // If stack is empty, parentheses
#include <string> balanced
bool isBalanced(const std::string &str) { }
int main() {
std::stack<char> s; std::string input;
for (char ch : str) { std::cout << "Enter a string of parentheses: ";
std::cin >> input;
if (ch == '(') {
if (isBalanced(input)) {
s.push(ch); std::cout << "The string is balanced.\n";
} else {
} else if (ch == ')') {
std::cout << "The string is not balanced.\n";
if (s.empty()) { }
return false; // Unmatched closing parenthesis} return 0;
}
Question 7: Binary Search Tree (BST) for Managing Student IDs
• A Binary Search Tree is a type of binary tree in which each node has at most two children (left and right). For any
node:
Left child: The left child’s value is less than the node's value.
Right child: The right child’s value is greater than the node's value.
This property makes BSTs ideal for efficient searching, insertion, and deletion.
Operations on the BST
1. Insert Operation:
• To insert a new student ID, you start at the root and compare the new ID with the current node.
• If the ID is less than the current node’s value, move to the left child.
• If the ID is greater, move to the right child.
• Repeat this process until you find an empty spot (where the child is nullptr).
2. Search Operation:
• To search for a student ID, start at the root and compare the ID with the current node's value.
• If the ID is less than the current node’s value, move to the left child.
• If the ID is greater, move to the right child.
• If the ID matches the current node’s value, return true (ID found).
• If you reach a nullptr, the ID does not exist in the tree.
3. Delete Operation:
• If the node to be deleted has no children (a leaf node), simply remove it.
• If the node has one child, replace the node with its child.
• If the node has two children, find the in-order successor (the smallest node in the right subtree), replace the node with
the in-order successor, and delete the successor.
4. In-order Traversal:
• Traverse the left subtree, visit the node, and then traverse the right subtree. This guarantees that the nodes are visited in
ascending order because of the BST property.
Example
• Let's insert the IDs 1023, 1005, 1089, 1044, 1001 in the BST:
• Insert 1023 as the root.
• Insert 1005: It’s less than 1023, so insert it to the left of 1023.
• Insert 1089: It’s greater than 1023, so insert it to the right of 1023.
• Insert 1044: It’s greater than 1023 but less than 1089, so insert it to
the left of 1089.
• Insert 1001: It’s less than 1023 and also less than 1005, so insert it to
the left of 1005.
• After all insertions, the tree structure will look like this:
Time Complexity
1. Height of the Tree:
• The height of the tree directly affects the time complexity for search, insert, and delete operations. The height is the
number of edges from the root to the deepest leaf.
• If the tree is balanced, the height is , where is the number of nodes.
• If the tree is unbalanced (like a linked list), the height can be as large as .
2. Worst-Case Time Complexity:
• Search: In the worst case, you may have to traverse the entire height of the tree. Therefore, the worst-case time
complexity for searching in a BST is . 0(n)
• Insert: Similar to search, the worst-case time complexity for insertion is also in an unbalanced tree.
• Delete: Deletion operation may also take time in the worst case if the tree is unbalanced.
3. Balanced vs. Unbalanced Tree:
•If the tree is balanced (e.g., through a self-balancing tree like AVL or Red-Black Tree), the height
remains , leading to more efficient operations.
•In an unbalanced tree (e.g., a tree that degenerates into a linked list), the operations degrade to ,
which is inefficient.