A Comprehensive Study Guide
Mergesort is a classic divide-and-conquer sorting algorithm that was one of the first algorithms to achieve O(N log N) time complexity. It's considered one of the top 10 algorithms of the 20th century in science and engineering.
Input:
M E R G E S O R T E X A M P L Eβ¬οΈ After sorting left half β¬οΈ
β¬οΈ After sorting right half β¬οΈ
β¬οΈ After merging β¬οΈ
Goal: Given two sorted subarrays a[lo] to a[mid] and a[mid+1] to a[hi], replace with a single sorted subarray a[lo] to a[hi].
Two sorted subarrays:
β¬οΈ After merging β¬οΈ
private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {
// Copy elements to auxiliary array
for (int k = lo; k <= hi; k++)
aux[k] = a[k];
// Merge back to original array
int i = lo, j = mid + 1;
for (int k = lo; k <= hi; k++) {
if (i > mid) a[k] = aux[j++]; // left exhausted
else if (j > hi) a[k] = aux[i++]; // right exhausted
else if (less(aux[j], aux[i])) a[k] = aux[j++]; // right smaller
else a[k] = aux[i++]; // left smaller or equal
}
}
public class Merge {
private static void merge(...) { /* as above */ }
private static void sort(Comparable[] a, Comparable[] aux,
int lo, int hi) {
if (hi <= lo) return; // base case
int mid = lo + (hi - lo) / 2; // find midpoint
sort(a, aux, lo, mid); // sort left half
sort(a, aux, mid + 1, hi); // sort right half
merge(a, aux, lo, mid, hi); // merge results
}
public static void sort(Comparable[] a) {
Comparable[] aux = new Comparable[a.length];
sort(a, aux, 0, a.length - 1);
}
}
Best, Average, and Worst Case
For auxiliary array
Upper bound
Upper bound
Recurrence Relation:
T(N) = 2T(N/2) + N
| Computer | Thousand (10Β³) | Million (10βΆ) | Billion (10βΉ) |
|---|---|---|---|
| Home (10βΈ compares/sec) | instant | 1 second | 18 minutes |
| Super (10ΒΉΒ² compares/sec) | instant | instant | instant |
Good algorithms are better than supercomputers!
Mergesort on a home computer beats Insertion Sort (O(NΒ²)) on a supercomputer for large datasets.
Instead of recursively dividing the array, start with small subarrays and iteratively merge them.
public static void sort(Comparable[] a) {
int N = a.length;
Comparable[] aux = new Comparable[N];
// sz: size of subarrays to merge (1, 2, 4, 8, ...)
for (int sz = 1; sz < N; sz = sz + sz) {
// lo: start of left subarray
for (int lo = 0; lo < N - sz; lo += sz + sz) {
merge(a, aux, lo, lo + sz - 1,
Math.min(lo + sz + sz - 1, N - 1));
}
}
}
A sorting algorithm is stable if it preserves the relative order of items with equal keys.
Typical Use Case: Sort by multiple criteria
With a stable sort, students in the same section remain sorted by name!
| Name | Section | After Sorting by Section (Stable) |
|---|---|---|
| Andrews | 3 | Andrews (3) β Still in order! |
| Chen | 3 | Chen (3) β Still in order! |
| Fox | 3 | Fox (3) β Still in order! |
Key insight: The merge operation takes from the left subarray when keys are equal.
if (less(aux[j], aux[i])) a[k] = aux[j++];
else a[k] = aux[i++]; // Takes from left if equal
| Algorithm | Stable? | Reason |
|---|---|---|
| Insertion Sort | β Yes | Equal items never move past each other |
| Selection Sort | β No | Long-distance exchanges can move equal items |
| Mergesort | β Yes | Merge operation preserves order |
| Shell Sort | β No | Long-distance exchanges |
A Comparator is a Java interface that allows you to define custom comparison logic, separate from the natural ordering of a type.
| Comparable | Comparator |
|---|---|
| Natural order (part of class) | Alternative order (separate class) |
compareTo() method |
compare() method |
| One ordering per class | Multiple orderings possible |
Arrays.sort(array) |
Arrays.sort(array, comparator) |
public class Student {
private final String name;
private final int section;
// Comparator for sorting by name
public static class ByName implements Comparator<Student> {
public int compare(Student v, Student w) {
return v.name.compareTo(w.name);
}
}
// Comparator for sorting by section
public static class BySection implements Comparator<Student> {
public int compare(Student v, Student w) {
return v.section - w.section;
}
}
}
// Usage:
Arrays.sort(students, new Student.ByName());
Arrays.sort(students, new Student.BySection());
| Order Type | Example |
|---|---|
| Natural | Now is the time |
| Case Insensitive | is Now the time |
| Spanish | cafΓ© cafetero churro cuarto nube Γ±oΓ±o |
| British Phone Book | McKinley Mackintosh |
| Algorithm | In-Place? | Stable? | Best | Average | Worst | Remarks |
|---|---|---|---|---|---|---|
| Selection Sort | β | β | Β½NΒ² | Β½NΒ² | Β½NΒ² | N exchanges |
| Insertion Sort | β | β | N | ΒΌNΒ² | Β½NΒ² | Use for small N or partially ordered |
| Shell Sort | β | β | N log N | ? | N^(3/2) | Tight code; subquadratic |
| Mergesort | β | β | Β½N log N | N log N | N log N | N log N guarantee; stable |
Arrays.sort() for objects