Browse code

Add heap sort.

Xavier G authored on 25/08/2016 23:36:43
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,94 @@
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
+#define heap_parent_index(x) (((x) - 1) / 2)
13
+#define heap_lchild_index(x) ((2 * (x)) + 1)
14
+#define heap_rchild_index(x) ((2 * (x)) + 2)
15
+
16
+void sift_down(unsigned int *heap, unsigned int start, unsigned int end) {
17
+	unsigned int root;      /* Root of the heap being inspected. */
18
+	unsigned int child;     /* Child of the heap being inspected. */
19
+	unsigned int swap;      /* Node to be swapped with the root. */
20
+	unsigned int swap_node; /* Used for the actual swap operation. */
21
+	VERBOSE(3, "  sift_down(heap, %u, %u)\n", start, end);
22
+
23
+	/* We want to sift down the provided heap, so we start at its root and
24
+	explore down, looking for anomalies, i.e. for children larger than their
25
+	parent node. */
26
+	root = start;
27
+
28
+	/* While the root being inspected has at least one child: */
29
+	while ((child = heap_lchild_index(root)) <= end) {
30
+		/* By default, we consider everything is fine, nothing needs to be
31
+		swapped: */
32
+		swap = root;
33
+		/* Check the left child: */
34
+		if (heap[child] > heap[root]) {
35
+			/* The left child is larger than the root, it is candidate to be
36
+			swapped with the root: */
37
+			swap = child;
38
+		}
39
+		/* Check the right child (if any) against either its sibling
40
+		or the root: */
41
+		if (child + 1 <= end && heap[child + 1] > heap[swap]) {
42
+			swap = child + 1;
43
+		}
44
+		/* Proceed with the swapping, if necessary: */
45
+		if (swap == root) {
46
+			return;
47
+		}
48
+		else {
49
+			swap_node = heap[swap];
50
+			heap[swap] = heap[root];
51
+			heap[root] = swap_node;
52
+			/* Consider the node we swapped as the new root and keep looping: */
53
+			root = swap;
54
+		}
55
+	}
56
+}
57
+
58
+/*
59
+ * Implementation of heap sort:
60
+ */
61
+void array_sort(unsigned int **array, unsigned int count) {
62
+	unsigned int *src;          /* Unsorted, source array. */
63
+	unsigned int swap;          /* Used to swap values. */
64
+	int heap_end;               /* End of our heap. */
65
+	int i;                      /* Used to iterate over the array. */
66
+
67
+	/* Do nothing unless there are at least two items to sort: */
68
+	if (count < 2) return;
69
+
70
+	/* Heap sort is an in-place algorithm, i.e. we work directly on the
71
+	provided array: */
72
+	src = *array;
73
+	heap_end = count - 1;
74
+
75
+	/* The first step consists in turning the array into a max heap (i.e. into
76
+	a binary tree with the maximum value at the top). */
77
+	for (i = heap_parent_index(heap_end); i >= 0; --i) {
78
+		sift_down(src, i, heap_end);
79
+	}
80
+
81
+	while (heap_end > 0) {
82
+		/* The second step consists in swapping the root of our max heap (i.e.
83
+		the largest value in the whole array) with the last item: */
84
+		swap = src[heap_end];
85
+		src[heap_end] = src[0];
86
+		src[0] = swap;
87
+
88
+		/* The third step consists in fixing our now-smaller but disturbed max
89
+		heap by calling sift_down() again: */
90
+		sift_down(src, 0, -- heap_end);
91
+
92
+		/* Next, we loop until our heap has but a single value. */
93
+	}
94
+}