Model paper

Dean's Office Official Model Question Paper

ITM 252 · Data Structure and Algorithms

examination paper loaded.
Programme
BITM / BIM
Academic year
Semester 4
Paper type
Official Model Question
Sitting
Dean's Office Blueprint
Full marks
60
Duration
180 minutes

Tribhuvan University

Faculty of Management

Office of the Dean

Official Model Question Paper / Dean's Office Blueprint

Course: ITM 252 · Data Structure and Algorithms

Level: Bachelor of Information Technology Management (BITM / BIM) (BITM / BIM) · Semester 4

Full Marks: 60

Time: 3 hrs.

Candidates are required to give their answers in their own words as far as practicable. The figures in the margin indicate full marks.

Group A

Brief Answer Questions. Attempt ALL questions.

[5 × 2 = 10]
  1. Define Big-O (OO), Big-Omega (Ω\Omega), and Big-Theta (Θ\Theta) asymptotic notations with their mathematical definitions.

    [2]
    View model solution

    Answer:

    • Big-O (OO - Asymptotic Upper Bound): f(n)=O(g(n))f(n) = O(g(n)) if there exist positive constants c>0c > 0 and n01n_0 \ge 1 such that:
      0f(n)cg(n)nn00 \le f(n) \le c \cdot g(n) \quad \forall n \ge n_0
      Represents the worst-case ceiling on algorithm running time.
    • Big-Omega (Ω\Omega - Asymptotic Lower Bound): f(n)=Ω(g(n))f(n) = \Omega(g(n)) if there exist positive constants c>0c > 0 and n01n_0 \ge 1 such that:
      0cg(n)f(n)nn00 \le c \cdot g(n) \le f(n) \quad \forall n \ge n_0
      Represents the best-case floor on algorithm running time.
    • Big-Theta (Θ\Theta - Asymptotically Tight Bound): f(n)=Θ(g(n))f(n) = \Theta(g(n)) if there exist positive constants c1,c2>0c_1, c_2 > 0 and n01n_0 \ge 1 such that:
      0c1g(n)f(n)c2g(n)nn00 \le c_1 \cdot g(n) \le f(n) \le c_2 \cdot g(n) \quad \forall n \ge n_0
  2. What is a Circular Queue? State why it is preferred over a linear array queue and write the condition for queue full.

    [2]
    View model solution

    Answer:

    • Circular Queue: A linear FIFO data structure where the last position of the underlying array connects back to the first position, forming a circular ring.
    • Advantage: Overcomes the false overflow problem of linear array queues, where vacated slots at the front after dequeuing cannot be reused even if free memory exists.
    • Queue Full Condition: Using modular arithmetic with array capacity MAX:
      (rear+1)(modMAX)==front\mathbf{(rear + 1) \pmod{MAX} == front}
      Queue empty condition: front==1 and rear==1\text{front} == -1 \text{ and } \text{rear} == -1.
  3. Differentiate between a Singly Linked List (SLL) and a Doubly Linked List (DLL) in terms of memory overhead and operations.

    [2]
    View model solution

    Answer:

    Parameter Singly Linked List (SLL) Doubly Linked List (DLL)
    Node Structure Contains data field and a single pointer (next). Contains data field and two pointers (prev and next).
    Memory Overhead Lower memory overhead (1 pointer per node). Higher memory overhead (2 pointers per node).
    Traversal Strictly unidirectional (forward traversal only). Bidirectional (can traverse both forward and backward).
    Node Deletion Requires traversal from head to locate previous node (O(N)O(N)). Can delete a given node in O(1)O(1) time without needing predecessor pointer.
  4. Define the Balance Factor of an AVL Tree and state the permitted values for a node to remain balanced.

    [2]
    View model solution

    Answer:

    • Balance Factor (BFBF): In an AVL self-balancing binary search tree, the Balance Factor of any node NN is defined as the height difference between its left subtree and right subtree:
      BF(N)=Height(Left Subtree)Height(Right Subtree)BF(N) = \text{Height}(\text{Left Subtree}) - \text{Height}(\text{Right Subtree})
    • Permitted Values: An AVL tree strictly enforces that for every node in the tree:
      BF(N){1,0,+1}BF(N) \in \{-1, 0, +1\}
      If an insertion or deletion causes BF(N)BF(N) to become ±2\pm 2, tree rotations (LL, RR, LR, or RL) are performed immediately to restore balance.
  5. Compare Breadth-First Search (BFS) and Depth-First Search (DFS) graph traversals in terms of underlying data structures and use cases.

    [2]
    View model solution

    Answer:

    Parameter Breadth-First Search (BFS) Depth-First Search (DFS)
    Data Structure Used Queue (FIFO) Stack (LIFO) or Function Call Recursion
    Search Strategy Explores all neighboring vertices at current depth before moving deeper. Explores as deep as possible along each branch before backtracking.
    Shortest Path Guarantees finding the shortest path on unweighted graphs. Does not guarantee finding the shortest path.
    Primary Use Cases Shortest path on unweighted graphs, peer-to-peer networking, crawler level-order. Topological sorting, detecting cycles in directed graphs, maze solving.

Group B

Descriptive Answer Questions. Attempt any THREE questions.

[3 × 10 = 30]
  1. Analyze the application of stacks in expression conversion: a) Convert the following Infix Expression into Postfix Notation using a stack:

    (A+B)(CD)/(E+FG)(A + B) * (C - D) / (E + F \uparrow G)
    where \uparrow denotes exponentiation. Provide a complete step-by-step tabular trace showing Token, Operator Stack, and Output String. (6 Marks) b) Write a complete algorithm in pseudocode/C to evaluate a postfix expression containing multi-digit integers. (4 Marks)

    [10]
    View model solution

    Stack-Based Infix to Postfix Conversion and Evaluation

    a) Tabular Trace of Infix to Postfix Conversion

    • Expression: (A+B)(CD)/(E+FG)(A + B) * (C - D) / (E + F \uparrow G)
    • Precedence Hierarchy: \uparrow (Exponentiation, Right-to-Left, highest) >> ,/*, / (Left-to-Right) >> +,+,- (Left-to-Right) >> (( (lowest inside stack).
    Step Current Token Action Taken Operator Stack Postfix Output Expression
    1 ( Push to stack (
    2 A Append to output ( A
    3 + Push to stack ( + A
    4 B Append to output ( + A B
    5 ) Pop until ( A B +
    6 * Push to stack * A B +
    7 ( Push to stack * ( A B +
    8 C Append to output * ( A B + C
    9 - Push to stack * ( - A B + C
    10 D Append to output * ( - A B + C D
    11 ) Pop until ( * A B + C D -
    12 / Same precedence as *, pop *, push / / A B + C D - *
    13 ( Push to stack / ( A B + C D - *
    14 E Append to output / ( A B + C D - * E
    15 + Push to stack / ( + A B + C D - * E
    16 F Append to output / ( + A B + C D - * E F
    17 ^ Higher precedence than +, push / ( + ^ A B + C D - * E F
    18 G Append to output / ( + ^ A B + C D - * E F G
    19 ) Pop until ( (pop ^, then +) / A B + C D - * E F G ^ +
    20 End Pop remaining operators (pop /) [Empty] A B + C D - * E F G ^ + /
    • Final Postfix String: AB+CDEFG+/\mathbf{A B + C D - * E F G \uparrow + /}

    b) Postfix Evaluation Algorithm in C

    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <math.h>
    
    #define STACK_SIZE 100
    
    typedef struct {
        int data[STACK_SIZE];
        int top;
    } OperandStack;
    
    void push(OperandStack *s, int val) { s->data[++(s->top)] = val; }
    int pop(OperandStack *s) { return s->data[(s->top)--]; }
    
    int evaluate_postfix(const char *exp) {
        OperandStack stack;
        stack.top = -1;
    
        for (int i = 0; exp[i] != '\0'; i++) {
            if (isspace(exp[i])) continue;
    
            // Multi-digit operand parsing
            if (isdigit(exp[i])) {
                int val = 0;
                while (isdigit(exp[i])) {
                    val = (val * 10) + (exp[i] - '0');
                    i++;
                }
                i--; // adjust loop increment
                push(&stack, val);
            } else {
                // Operator: pop two operands
                int op2 = pop(&stack);
                int op1 = pop(&stack);
                switch (exp[i]) {
                    case '+': push(&stack, op1 + op2); break;
                    case '-': push(&stack, op1 - op2); break;
                    case '*': push(&stack, op1 * op2); break;
                    case '/': push(&stack, op1 / op2); break;
                    case '^': push(&stack, (int)pow(op1, op2)); break;
                }
            }
        }
        return pop(&stack);
    }
    
  2. Examine Binary Search Trees (BST) and AVL Trees: a) Detail the three cases of node deletion in a standard BST (leaf node, single child, and two children replaced by in-order successor). (4 Marks) b) Construct an AVL Tree by inserting the following key sequence into an initially empty tree: [50, 20, 60, 10, 8, 15, 30, 25] Illustrate every intermediate unbalance, identify the rotation type (LL, RR, LR, RL), and draw the resulting balanced tree after each rotation. (6 Marks)

    [10]
    View model solution

    BST Deletion and AVL Tree Construction Step-by-Step

    a) Three Cases of BST Node Deletion

    1. Case 1 (Node is a Leaf): The node has no children. Deletion is trivial: the parent pointer to this node is set to NULL, and the node’s memory is deallocated (O(1)O(1) pointer update).
    2. Case 2 (Node has Exactly One Child): The node has either a left child or a right child. The parent’s pointer is updated to point directly to the node’s single child, bypassing the deleted node.
    3. Case 3 (Node has Two Children):
      • Find the node’s In-order Successor (the smallest node in its right subtree) OR In-order Predecessor (largest node in its left subtree).
      • Copy the value of the in-order successor into the target node.
      • Recursively delete the in-order successor from the right subtree (which falls into Case 1 or Case 2, since the successor can have at most one child).

    b) AVL Tree Construction: Sequence [50, 20, 60, 10, 8, 15, 30, 25]

    1. Insert 50, 20, 60:
      • Balanced. Root 50 (BF=0BF = 0), left child 20 (BF=0BF=0), right child 60 (BF=0BF=0).
    2. Insert 10:
      • Inserted at 20left20 \to \text{left}.
      • BF(20)=+1,BF(50)=+1BF(20) = +1, BF(50) = +1. Balanced.
    3. Insert 8 (Triggers LL Rotation):
      • Inserted at 10left10 \to \text{left}.
      • Tree path: 2010820 \to 10 \to 8.
      • BF(20)=2BF(20) = 2 (unbalanced at node 20, Left-Left violation).
      • Perform LL Rotation at Node 20:
        • Node 10 becomes parent of 20 and 8.
        • Subtree at 50 left becomes: 10 (root), 8 (left), 20 (right).
        • Tree is balanced.
    4. Insert 15 (Triggers LR Rotation):
      • Inserted at 20left20 \to \text{left}.
      • BF(10)=1,BF(50)=31=+2BF(10) = -1, BF(50) = 3 - 1 = +2 (Node 50 is unbalanced).
      • Path from 50: Left child is 10, right child of 10 is 20     \implies LR Violation.
      • Perform LR Rotation at Node 50:
        • First, rotate Left on 10: 20 becomes left child of 50, 10 becomes left child of 20, 15 becomes right child of 10.
        • Second, rotate Right on 50: 20 becomes new root of entire tree!
        • Left child of 20 is 10 (with children 8, 15); Right child of 20 is 50 (with child 60).
        • Tree is balanced!
    5. Insert 30:
      • Inserted at 50left    BF(50)=150 \to \text{left} \implies BF(50) = 1. Balanced.
    6. Insert 25 (Triggers RL Rotation):
      • Inserted at 30left30 \to \text{left}.
      • Path from 50: Left child is 30, left child of 30 is 25.
      • Node 30 has BF=+1BF = +1. Node 50 has left height 2, right height 1     BF(50)=+1\implies BF(50) = +1.
      • Let’s check Root 20: Left subtree height is 2 (nodes 10, 8, 15). Right subtree height is 3 (nodes 50, 30, 25).
      • BF(20)=23=1BF(20) = 2 - 3 = -1. Balanced!
      • Node 50 has BF=21=+1BF = 2 - 1 = +1.
      • Complete balanced tree!
    Final Balanced AVL Structure
                20 (BF = -1)
              /      \
          10 (BF=0)    50 (BF = +1)
          /   \        /     \
         8     15     30      60
                     /
                    25
    

    Every node satisfies BF{1,0,+1}BF \in \{-1, 0, +1\}. Search complexity guaranteed O(logN)O(\log N).

  3. Compare MergeSort and HeapSort: a) Formulate the MergeSort divide-and-conquer recurrence relation and prove its time complexity O(NlogN)O(N \log N) using the Master Theorem. (5 Marks) b) Define the Max-Heap Property. Detail the max_heapify() procedure, explain how a heap is built in O(N)O(N) linear time, and trace HeapSort sorting an array in-place. (5 Marks)

    [10]
    View model solution

    MergeSort vs. HeapSort: Recurrences and Heap Mechanics

    a) MergeSort Divide-and-Conquer Recurrence and Master Theorem Proof

    1. Recurrence Formulation

    MergeSort divides an array of size nn into two equal subproblems of size n/2n/2, recursively sorts each half, and merges the two sorted lists in linear time cnc \cdot n:

    T(n)=2T(n2)+Θ(n)T(n) = 2T\left(\frac{n}{2}\right) + \Theta(n)

    2. Proof via Master Theorem

    The generalized Master Theorem recurrence has the form:

    T(n)=aT(nb)+f(n)T(n) = a T\left(\frac{n}{b}\right) + f(n)
    where a=2a = 2 (number of subproblems), b=2b = 2 (subproblem reduction factor), and f(n)=Θ(n1)    d=1f(n) = \Theta(n^1) \implies d = 1.

    • Evaluate the critical ratio:
      logba=log22=1\log_b a = \log_2 2 = 1
    • Compare logba\log_b a with dd:
      logba=1=d\log_b a = 1 = d
    • This satisfies Case 2 of the Master Theorem (f(n)=Θ(nlogba)f(n) = \Theta(n^{\log_b a})):
      T(n)=Θ(nlogbalogn)=Θ(nlogn)T(n) = \Theta(n^{\log_b a} \log n) = \mathbf{\Theta(n \log n)}
      MergeSort runs in Θ(nlogn)\Theta(n \log n) time across all cases (best, average, and worst).

    b) HeapSort and Max-Heap Mechanics

    1. Max-Heap Property

    A complete binary tree where for every non-root node ii with parent p=(i1)/2p = \lfloor(i - 1)/2\rfloor:

    Arr[p]Arr[i]\text{Arr}[p] \ge \text{Arr}[i]
    The maximum element in the dataset is always stored at the root (Arr[0]).

    2. max_heapify(Arr, n, i) Procedure
    1. Identify left child l=2i+1l = 2i + 1 and right child r=2i+2r = 2i + 2.
    2. Find the largest among Arr[i], Arr[l], and Arr[r].
    3. If largest i\ne i, swap Arr[i] with Arr[largest] and recursively call max_heapify(Arr, n, largest) down the tree (O(logn)O(\log n) height).
    3. Why build_max_heap runs in O(n)O(n) Linear Time

    Calling max_heapify on all internal nodes from n/21\lfloor n/2 \rfloor - 1 down to 0:

    h=0lognn2h+1O(h)=O(nh=0h2h)=O(n×2)=O(n)\sum_{h=0}^{\lfloor\log n\rfloor} \left\lceil \frac{n}{2^{h+1}} \right\rceil O(h) = O\left( n \sum_{h=0}^{\infty} \frac{h}{2^h} \right) = O(n \times 2) = \mathbf{O(n)}

    4. In-Place HeapSort Routine
    1. Build Max-Heap from unsorted input (O(n)O(n)).
    2. For i=n1i = n - 1 down to 1:
      • Swap root Arr[0] (maximum) with last leaf Arr[i].
      • Reduce heap size by 1 (nin \leftarrow i).
      • Run max_heapify(Arr, i, 0) on the new root to restore max-heap property (O(logn)O(\log n)).
    3. Resulting array is sorted in ascending order in O(nlogn)\mathbf{O(n \log n)} time and O(1)\mathbf{O(1)} auxiliary space.
  4. Examine Shortest Path and Minimum Spanning Tree (MST) Graph Algorithms: a) Detail Dijkstra’s Single-Source Shortest Path Algorithm. Trace the algorithm step-by-step to find the shortest path from source vertex AA to all vertices in a directed weighted graph with vertices {A,B,C,D,E}\{A, B, C, D, E\} and edges: (A,B,4),(A,C,2),(C,B,1),(B,D,5),(C,D,8),(C,E,10),(D,E,2)(A, B, 4), (A, C, 2), (C, B, 1), (B, D, 5), (C, D, 8), (C, E, 10), (D, E, 2). Show the distance array after each vertex extraction. (6 Marks) b) Compare Prim’s Algorithm and Kruskal’s Algorithm for constructing a Minimum Spanning Tree. (4 Marks)

    [10]
    View model solution

    Dijkstra Shortest Path Algorithm and MST Comparison

    a) Dijkstra Single-Source Shortest Path Trace

    1. Graph Specification
    • Vertices: V={A,B,C,D,E}V = \{A, B, C, D, E\}, Source = AA.
    • Directed Weighted Edges:
      • From AA: (AB,4),(AC,2)(A \to B, 4), (A \to C, 2)
      • From CC: (CB,1),(CD,8),(CE,10)(C \to B, 1), (C \to D, 8), (C \to E, 10)
      • From BB: (BD,5)(B \to D, 5)
      • From DD: (DE,2)(D \to E, 2)
    2. Step-by-Step Algorithm Execution Trace
    Step Visited Vertex Relaxed Outgoing Edges Tentative Distances [A,B,C,D,E][A, B, C, D, E] Predecessors
    0 (Init) None Initialize source distance d[A]=0d[A]=0, others \infty [0,,,,][0, \infty, \infty, \infty, \infty] [,,,,][-, -, -, -, -]
    1 AA (dist 0) Relax (AB,4)    d[B]=4(A \to B, 4) \implies d[B] = 4<br>Relax (AC,2)    d[C]=2(A \to C, 2) \implies d[C] = 2 [0,4,2,,][0, 4, 2, \infty, \infty] [,A,A,,][-, A, A, -, -]
    2 CC (dist 2) Relax (CB,1)    d[B]=min(4,2+1)=3(C \to B, 1) \implies d[B] = \min(4, 2+1) = \mathbf{3}<br>Relax (CD,8)    d[D]=min(,2+8)=10(C \to D, 8) \implies d[D] = \min(\infty, 2+8) = \mathbf{10}<br>Relax (CE,10)    d[E]=min(,2+10)=12(C \to E, 10) \implies d[E] = \min(\infty, 2+10) = \mathbf{12} [0,3,2,10,12][0, 3, 2, 10, 12] [,C,A,C,C][-, C, A, C, C]
    3 BB (dist 3) Relax (BD,5)    d[D]=min(10,3+5)=8(B \to D, 5) \implies d[D] = \min(10, 3+5) = \mathbf{8} [0,3,2,8,12][0, 3, 2, 8, 12] [,C,A,B,C][-, C, A, B, C]
    4 DD (dist 8) Relax (DE,2)    d[E]=min(12,8+2)=10(D \to E, 2) \implies d[E] = \min(12, 8+2) = \mathbf{10} [0,3,2,8,10][0, 3, 2, 8, 10] [,C,A,B,D][-, C, A, B, D]
    5 EE (dist 10) No unvisited outgoing edges [0,3,2,8,10][0, 3, 2, 8, 10] Finalized
    3. Final Shortest Paths from Source AA
    • To AA: Distance = 0 | Path: AA
    • To BB: Distance = 3 | Path: ACBA \to C \to B
    • To CC: Distance = 2 | Path: ACA \to C
    • To DD: Distance = 8 | Path: ACBDA \to C \to B \to D
    • To EE: Distance = 10 | Path: ACBDEA \to C \to B \to D \to E

    b) Prim’s vs. Kruskal’s Minimum Spanning Tree Algorithms

    Parameter Prim’s Algorithm Kruskal’s Algorithm
    Growth Strategy Vertex-based: Grows a single continuous tree outward from an arbitrary start vertex. Edge-based: Adds lowest-weight edge across the entire graph that does not form a cycle.
    Data Structures Priority Queue / Min-Heap for vertex distance keys. Disjoint Set Union (DSU / Union-Find) with path compression.
    Graph Density Preference Preferred for Dense Graphs (EV2E \approx V^2), running in O(V2)O(V^2) or O(E+VlogV)O(E + V \log V). Preferred for Sparse Graphs (EV2E \ll V^2), running in O(ElogE)O(E \log E).
    Intermediate State Always forms a valid single connected tree at every step. May form a disconnected forest of trees that merges at the final steps.

Group C

Comprehensive Answer / Case Analysis Question. Attempt ALL questions.

[1 × 20 = 20]
  1. Systems Engineering Case Study: Tribhuvan International Airport (TIA) Real-Time Baggage Routing, Flight Scheduling, and Passenger Dispatch Engine

    Civil Aviation Authority of Nepal (CAAN) is replacing the automated flight operations and baggage logistics management systems at TIA Kathmandu:

    • Operational Requirements:
      1. VIP & Emergency Boarding Dispatch: Emergency humanitarian flights and VIP diplomatic aircraft must be dispatched dynamically based on priority score, where highest-priority flights preempt lower-priority departures.
      2. Passenger Boarding Pass Verification: High-throughput security gates scan passport numbers to verify passenger identity, check flight status, and assign gates in sub-millisecond time.
      3. Automated Inter-Terminal Baggage Conveyor System: Luggage containers must be routed across a network of 25 conveyor junctions and transfer chutes to find the least transit-time path from check-in counters to aircraft cargo holds.
    • Performance Criteria: During festive peak seasons (Dashain/Tihar), system load spikes to 120,000 passenger lookups and 45,000 routed bags daily without database stalls.

    Questions: a) Formulate the Abstract Data Type (ADT) and data structure design: Select and justify the optimal data structures for: (i) Emergency Flight Dispatch, (ii) Passenger Verification by Passport, and (iii) Conveyor Baggage Routing. Analyze the time and space complexity of each. (6 Marks) b) Implement the real-time luggage pathfinding routing engine in Java or C using Dijkstra’s algorithm. Write complete, robust code implementing the graph node structure, adjacency list representation, priority queue edge relaxations, and destination route reconstruction. (7 Marks) c) Analyze Hash Table engineering and collision resolution for passenger lookups: Contrast Separate Chaining versus Open Addressing with Double Hashing. Formulate the load factor threshold (α=N/M0.75\alpha = N/M \le 0.75), detail dynamic rehashing overhead, and explain how to prevent worst-case O(N)O(N) hash degradation. (7 Marks)

    [20]
    View model solution

    Systems Engineering Solution: TIA Airport Logistics and Flight Dispatch Engine

    a) Data Structure Selection and Complexity Justification

    1. VIP & Emergency Flight Dispatch: Max-Heap Priority Queue
    • Justification: Aircraft departures require dynamic priority management where emergency relief and VIP aircraft can arrive at arbitrary times with higher priority scores than scheduled flights. A binary Max-Heap allows extracting the highest priority flight in O(logN)O(\log N) time and inserting newly scheduled flights in O(logN)O(\log N) time (O(1)O(1) amortized).
    • Complexity: Time: Insert O(logN)O(\log N), Extract-Max O(logN)O(\log N), Peek O(1)O(1). Space: O(N)O(N) contiguous array.
    2. Passenger Boarding Pass Verification: Hash Table with Separate Chaining
    • Justification: Security turnstiles require instantaneous, near-constant-time passport lookups (O(1)O(1) average time) to prevent passenger bottlenecks. Keys are hashed 9-character passport numbers.
    • Complexity: Time: Search/Insert O(1)O(1) average, O(N)O(N) worst-case. Space: O(N+M)O(N + M) where MM is bucket capacity.
    3. Inter-Terminal Baggage Conveyor Routing: Directed Weighted Graph with Adjacency List
    • Justification: Conveyor junctions and chutes form a network with unidirectional belt segments and variable transit times (weights). An adjacency list representation is space-optimal for sparse transportation graphs (EV2|E| \ll |V|^2).
    • Complexity: Space: O(V+E)O(V + E). Pathfinding (Dijkstra): Time O((V+E)logV)O((V + E) \log V) with Min-Heap.

    b) Real-Time Conveyor Routing Implementation in Java (Dijkstra)

    import java.util.*;
    
    class Edge {
        int target;
        int weightSeconds;
    
        public Edge(int target, int weightSeconds) {
            this.target = target;
            this.weightSeconds = weightSeconds;
        }
    }
    
    class NodeEntry implements Comparable<NodeEntry> {
        int node;
        int cost;
    
        public NodeEntry(int node, int cost) {
            this.node = node;
            this.cost = cost;
        }
    
        @Override
        public int compareTo(NodeEntry other) {
            return Integer.compare(this.cost, other.cost);
        }
    }
    
    public class BaggageRoutingEngine {
        private int numJunctions;
        private List<List<Edge>> adjList;
    
        public BaggageRoutingEngine(int numJunctions) {
            this.numJunctions = numJunctions;
            adjList = new ArrayList<>(numJunctions);
            for (int i = 0; i < numJunctions; i++) {
                adjList.add(new ArrayList<>());
            }
        }
    
        public void addConveyorSegment(int u, int v, int transitSeconds) {
            adjList.get(u).add(new Edge(v, transitSeconds));
        }
    
        public List<Integer> findFastestBaggageRoute(int startJunction, int destinationHold) {
            int[] dist = new int[numJunctions];
            int[] parent = new int[numJunctions];
            Arrays.fill(dist, Integer.MAX_VALUE);
            Arrays.fill(parent, -1);
    
            PriorityQueue<NodeEntry> pq = new PriorityQueue<>();
            dist[startJunction] = 0;
            pq.offer(new NodeEntry(startJunction, 0));
    
            while (!pq.isEmpty()) {
                NodeEntry current = pq.poll();
                int u = current.node;
    
                if (current.cost > dist[u]) continue; // Stale queue entry
                if (u == destinationHold) break;       // Reached destination
    
                for (Edge edge : adjList.get(u)) {
                    int v = edge.target;
                    int weight = edge.weightSeconds;
    
                    if (dist[u] + weight < dist[v]) {
                        dist[v] = dist[u] + weight;
                        parent[v] = u;
                        pq.offer(new NodeEntry(v, dist[v]));
                    }
                }
            }
    
            // Reconstruct Optimal Conveyor Path
            List<Integer> path = new ArrayList<>();
            if (dist[destinationHold] == Integer.MAX_VALUE) {
                return path; // Unreachable
            }
    
            for (int curr = destinationHold; curr != -1; curr = parent[curr]) {
                path.add(curr);
            }
            Collections.reverse(path);
            return path;
        }
    }
    

    c) Hash Table Engineering, Collision Resolution, and Load Factors

    1. Separate Chaining vs. Open Addressing with Double Hashing
    • Separate Chaining: Each hash table slot contains a linked list or balanced red-black tree (as in Java 8+ HashMap). If collision occurs, the element is appended to the bucket chain.
      • Advantage for Airport: Never runs out of slots; performance degrades gracefully even if load factor momentarily exceeds 1.0.
    • Open Addressing (Double Hashing): All elements reside directly within the array. On collision, probe sequence uses a secondary hash function: h(k,i)=(h1(k)+ih2(k))(modM)h(k, i) = (h_1(k) + i \cdot h_2(k)) \pmod M.
      • Disadvantage: Sensitive to clustering; table cannot exceed 100% capacity; deletion requires tombstone markers.
    2. Load Factor Threshold (α\alpha) and Dynamic Rehashing
    • Load Factor:
      α=NM=Total Stored PassengersTotal Bucket Capacity\alpha = \frac{N}{M} = \frac{\text{Total Stored Passengers}}{\text{Total Bucket Capacity}}
    • When α>0.75\alpha > 0.75, probability of hash collisions increases exponentially, causing lookup times to degrade from O(1)O(1) toward O(N)O(N).
    • Dynamic Rehashing: When α\alpha reaches 0.75, the engine allocates a new bucket array of size 2×M2 \times M, recalculates hash indices, and migrates all existing records into the new table. The O(N)O(N) resizing cost is amortized across thousands of subsequent fast insertions (O(1)O(1) amortized).
    3. Preventing Worst-Case O(N)O(N) Hash Flooding Attacks

    If malicious actors submit forged passport numbers that collide on the exact same hash bucket (algorithmic complexity attack):

    • Implement Universal Hashing (choosing random hash multipliers at startup).
    • Convert buckets with >8> 8 elements from linked lists into Red-Black balanced trees, guaranteeing worst-case lookup latency of O(logN)\mathbf{O(\log N)} rather than O(N)O(N).