summaryrefslogtreecommitdiff
path: root/doc/unit/11/README.md
blob: 7e0a37e0dd15693e21b6512b6b7a73f3a27e4869 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# Comparison-Based Sorting

* merge sort O(nlogn)
* quick sort O(nlogn)
* heap sort O(nlogn)

`compare(a,b)`

* -1: a < b
* 0: a == b
* +1: a > b

## Merge-Sort

is a classic recursive divide and conquer.

* if `a` is at most 1 then `a` is sorted.
* else we split `a` into two halves
  * `a0 = a[0...(n/2)-1]`
  * `a1 = a[(n/2)...n-1]`
  * merge a0, a1

```java
void mergeSort(T[] a, Comparator<T> c) {
  if (a.length <= 1) return;

  T[] a0 = Arrays.copyOfRange(a, 0, a.length/2);
  T[] a1 = Arrays.copyOfRange(a, a.length/2, a.length);
  mergeSort(a0, c);
  mergeSort(a1, c);
  merge(a0, a1, a, c);
}
```

## Quicksort

Unlike mergesort which does merging after solving the two subproblems,
quicksort does all of its work upfront.

1. pick a random `pivot` element `x` from `a`
2. partition `a` into the set of elements less than `x`, the set of elements equal to `x` and the set of elements greater than `x`.
3. recursively sort the first and third sets in this partition.

```java
void quickSort(T[] a, Comparator<T> c) {
  quickSort(a, 0, a.length, c);
}
void quickSort(T[] a, int i, int n, Comparator<T> c) {
  if (n <= 1) return;
  T x = a[i + rand.nextInt(n)];
  int p = i - 1, j = i, q = i+n;

  while (j < q) {
    int comp = compare(a[j], x);
    if (comp < 0) {
      swap(a, j++,  ++p);
    } else if (comp > 0) {
      swap(a, j, --q);
    } else {
      j++;
    }
  }
  quickSort(a, i, p-i+1, c);
  quickSort(a, q, n-(q-i), c);
}
```