Browse code

Add quick sort.

Xavier G authored on 27/08/2016 03:31:37
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,84 @@
1
+/**
2
+ * Copyright © 2016 Xavier G. <xavier@kindwolf.org>
3
+ * This work is free. You can redistribute it and/or modify it under the
4
+ * terms of the Do What The Fuck You Want To Public License, Version 2,
5
+ * as published by Sam Hocevar. See the COPYING file for more details.
6
+ */
7
+
8
+void array_sort(unsigned int **array, unsigned int count);
9
+#define ARRAY_SORT 1
10
+#include "common.c"
11
+
12
+/* Threshold under which Sedgewick's recommendation feels overkill: */
13
+#define TRIVIAL_ARRAY_THRESHOLD 5
14
+
15
+/*
16
+ * Implementation of quick sort:
17
+ */
18
+void quick_sort(unsigned int *array, unsigned int start, unsigned int end) {
19
+	unsigned int count;       /* Size of the array being treated. */
20
+	unsigned int a, b, c;     /* Used for the median-of-three computation. */
21
+	unsigned int pivot_value; /* Value used to determine where to split. */
22
+	unsigned int i;           /* Iterator from the start of the array to the pivot index. */
23
+	unsigned int j;           /* Iterator from the end of the array to the pivot index. */
24
+	unsigned int swap;        /* Used to swap values. */
25
+
26
+	if (start >= end) return;
27
+	count = end - start + 1;
28
+
29
+	/* Pick a pivot value: */
30
+	if (count < TRIVIAL_ARRAY_THRESHOLD) {
31
+		/* Do not bother for really trivial arrays: */
32
+		pivot_value = array[start];
33
+	}
34
+	else {
35
+		/* Otherwise, follow Sedgewick's recommendation of choosing the median
36
+		of the first, middle and last element of the array: */
37
+		a = array[start]; b = array[start + (count / 2)]; c = array[end];
38
+		if ((a >= b && a <= c) || (a >= c && a <= b)) {
39
+			pivot_value = a;
40
+		}
41
+		else if ((b >= a && b <= c) || (b >= c && b <= a)) {
42
+			pivot_value = b;
43
+		}
44
+		else {
45
+			pivot_value = c;
46
+		}
47
+	}
48
+
49
+	/* Determine where to split the array, following Hoare's partition scheme: */
50
+	i = start - 1;
51
+	j = end + 1;
52
+	while (1) {
53
+		do { ++ i; } while (array[i] < pivot_value);
54
+		/* array[i] is now larger than or equal to pivot_value despite being on
55
+		the left side of the pivot. */
56
+
57
+		do { -- j; } while (array[j] > pivot_value);
58
+		/* array[j] is now less than or equal to pivot_value despite being on
59
+		the right side of the pivot. */
60
+
61
+		if (i >= j) {
62
+			/* i and j passed each other: it is time to split the array at index j: */
63
+			break;
64
+		}
65
+
66
+		/* Swap array[i] and array[j] to respect the pivot: */
67
+		swap = array[i];
68
+		array[i] = array[j];
69
+		array[j] = swap;
70
+	}
71
+
72
+	/* Sort the sub-arrays on each side of the pivot: */
73
+	quick_sort(array, start, j);
74
+	quick_sort(array, j + 1, end);
75
+}
76
+
77
+void array_sort(unsigned int **array, unsigned int count) {
78
+	/* Do nothing unless there are at least two items to sort: */
79
+	if (count < 2) return;
80
+
81
+	/* Quick sort is an in-place algorithm, i.e. we work directly on the
82
+	provided array: */
83
+	quick_sort(*array, 0, count - 1);
84
+}