Unit 1: Introduction, Arrays, Sorting and Searching
1. Executive Summary & Foundational Concepts
A Data Structure is a systematic mathematical and logical arrangement for organizing, managing, and storing data within a digital computer to enable efficient access and modification. The choice of appropriate data structures directly dictates the algorithmic efficiency, memory footprint, and architectural scalability of computational software.
Primary Classifications of Data Structures:
- Primitive vs. Non-Primitive:
- Primitive Data Structures: Basic atomic types natively supported by hardware architecture and machine instructions (e.g.,
int,float,char,pointer). - Non-Primitive Data Structures: Complex composite structures constructed from primitive types to model relationships (e.g., arrays, linked lists, trees, graphs).
- Primitive Data Structures: Basic atomic types natively supported by hardware architecture and machine instructions (e.g.,
- Linear vs. Non-Linear:
- Linear Data Structures: Elements form a sequential sequence where each element (except first and last) has a unique predecessor and successor (e.g., Arrays, Stacks, Queues, Linked Lists). Traversal is single-level and sequential.
- Non-Linear Data Structures: Elements are organized hierarchically or interconnected arbitrarily across multi-level relationships (e.g., Trees, Graphs). Traversal requires branching paths.
- Static vs. Dynamic:
- Static Data Structures: Fixed size allocated at compile time; memory bounds cannot expand or contract during program execution (e.g., standard fixed-size arrays).
- Dynamic Data Structures: Flexible size allocated from heap storage during runtime; capacity expands and shrinks as elements are added or removed (e.g., linked lists, dynamic arrays/vectors).
2. Asymptotic Notations & Algorithmic Complexity
Algorithmic efficiency is measured in two dimensions:
- Time Complexity: The mathematical relationship quantifying the number of fundamental operations executed as a function of input size .
- Space Complexity: The total memory storage (fixed instruction space + dynamic variable space) required as a function of input size .
- Time-Space Trade-off: The design compromise where execution speed is accelerated by consuming additional memory storage (e.g., lookup tables, hash maps), or memory usage is conserved at the expense of higher CPU computation cycles.
Formal Asymptotic Notations:
Growth Order: O(1) < O(log N) < O(N) < O(N log N) < O(N^2) < O(2^N) < O(N!)
- Big-O Notation () - Asymptotic Upper Bound:
Represents the worst-case ceiling. Formally, if there exist positive constants and such that:
- Omega Notation () - Asymptotic Lower Bound:
Represents the best-case floor. Formally, if there exist positive constants and such that:
- Theta Notation () - Asymptotically Tight Bound:
Binds the function from both above and below. Formally, if and only if and :
- Little-o () and Little-omega ():
- denotes a strict upper bound: .
- denotes a strict lower bound: .
3. Linear Arrays: Memory Organization & Address Calculations
A Linear Array is a homogeneous, contiguous collection of elements identified by consecutive integer index bounds where is the Lower Bound and is the Upper Bound. The total number of elements (Length) is:
A. One-Dimensional (1D) Array Address Mapping
Because elements occupy contiguous physical RAM addresses, the memory location of element is calculated in time using the Base Address () and element width ( in bytes):
Example: For an array with and element size bytes, the address of is:
B. Two-Dimensional (2D) Array Address Mapping
A 2D array of dimensions (rows , columns ) can be linearized in RAM using two canonical conventions:
-
Row-Major Order (RMO):
Elements are stored row after row in contiguous physical memory.
where is the total number of columns (). -
Column-Major Order (CMO):
Elements are stored column after column in contiguous physical memory.
where is the total number of rows ().
4. Fundamental Array Operations
- Traversal: Visiting each element exactly once to inspect, display, or transform values. Time complexity: .
- Insertion:
- At the end (with available capacity): operations.
- At index / beginning: Requires shifting elements from index up to one position to the right. Worst-case time complexity: .
- Deletion:
- At the end: operations.
- At index / beginning: Requires shifting elements from index down to one position to the left. Worst-case time complexity: .
- Merging:
- Unsorted Arrays: Appending elements of array (size ) to array (size ): time.
- Sorted Arrays (Two-Pointer Technique): Concurrently traversing both sorted sequences and selecting the smaller candidate element yields a merged sorted array of size in linear time: comparisons and space.
5. Searching Algorithms
A. Linear Search (Sequential Search)
Sequentially evaluates each item in an array from index to until a target key match occurs or the collection is exhausted.
- Preconditions: None; operates on both sorted and unsorted sequences.
- Best-Case Complexity: (target matches the very first element).
- Worst-Case Complexity: (target is at the final index or absent).
- Average-Case Complexity: (approximately comparisons).
- Space Complexity: auxiliary memory.
B. Binary Search (Logarithmic Search)
Operates on the divide-and-conquer paradigm by continuously dividing a sorted search interval in half.
- Preconditions: The array MUST be in sorted order with random-access indexing.
- Algorithm:
- Initialize
low = 0andhigh = N - 1. - Compute
mid = low + (high - low) / 2(preventing arithmetic integer overflow). - If
A[mid] == target, returnmid. - If
target < A[mid], narrow search space:high = mid - 1. - If
target > A[mid], narrow search space:low = mid + 1. - Terminate when
low > high(target absent).
- Initialize
- Recurrence Relation: . By Master Theorem: .
- Best-Case Complexity: (target located at initial midpoint).
- Worst-Case & Average Complexity: .
- Space Complexity: Iterative version: ; Recursive version: call stack depth.
6. Elementary Sorting Algorithms
A. Bubble Sort (Sinking Sort)
Repeatedly steps through the array, compares adjacent adjacent elements ( and ), and swaps them if they are in the wrong order. With each outer pass , the largest unsorted element "bubbles up" to its correct terminal position.
- Optimization: An early-exit boolean flag (
swapped) stops passes if zero swaps occurred, achieving best-case time on already-sorted arrays. - Comparisons: In standard version: comparisons.
- Time Complexity: Best: (optimized); Worst: ; Average: .
- Space Complexity: auxiliary (in-place).
- Stability: Stable (does not swap identical elements).
B. Selection Sort
Divides the array into a sorted prefix and unsorted suffix. In each pass , it systematically scans the unsorted subarray to find the minimum element, and executes exactly one swap to place it at index .
- Key Characteristic: Minimizes the total number of write operations: executes at most swaps across all passes.
- Comparisons: Exactly comparisons under all initial orderings.
- Time Complexity: Best: ; Worst: ; Average: .
- Space Complexity: auxiliary (in-place).
- Stability: Unstable (long-distance swaps can reorder identical elements, e.g., sorting
[4a, 4b, 2]swaps4awith2, placing4aafter4b).
C. Insertion Sort
Incrementally builds a sorted array one item at a time. For each pass from to , the element (the key) is extracted, and preceding elements greater than the key are shifted one slot to the right, inserting the key into its sorted slot.
- Online Property: Can sort streaming inputs as elements arrive dynamically.
- Adaptive Performance: Highly efficient for small inputs () or nearly-sorted datasets.
- Time Complexity: Best: (already sorted; 1 comparison per element, 0 shifts); Worst: (reverse sorted); Average: .
- Space Complexity: auxiliary (in-place).
- Stability: Stable (equal elements are not shifted past each other).
7. Comparative Analysis Table of Algorithms
| Algorithm | Best-Case Time | Average-Case Time | Worst-Case Time | Space Complexity | Stable? | In-Place? | Key Trait |
|---|---|---|---|---|---|---|---|
| Linear Search | N/A | Yes | Unsorted data | ||||
| Binary Search | iter | N/A | Yes | Requires sorted array | |||
| Bubble Sort | (opt) | Yes | Yes | Adjacent swaps | |||
| Selection Sort | No | Yes | Minimum swaps () | ||||
| Insertion Sort | Yes | Yes | Adaptive; fast on nearly-sorted |
8. Summary & Key Review Takeaways
- Linear data structures arrange elements sequentially; non-linear structures represent hierarchical or networked topologies.
- Big-O () defines asymptotic upper bounds; Omega () defines lower bounds; Theta () denotes asymptotically tight bounds.
- 1D array addresses follow . 2D array row-major and column-major address calculations depend on column count and row count .
- Array insertions and deletions require element shifting, exhibiting worst-case time complexity.
- Binary search operates in by halving sorted ranges, avoiding linear scans.
- Selection Sort performs comparisons but guarantees swaps. Insertion Sort is adaptive and stable, exhibiting linear runtime on nearly-sorted arrays.