Skip to content

Commit ffd44fb

Browse files
authored
Add Heap Sort implementation with tests (#35)
* Add Heap Sort implementation with tests * add more tests with duplicate values and negative values. rename the parameter "arr" to "A".
1 parent fe4fa6c commit ffd44fb

4 files changed

Lines changed: 142 additions & 0 deletions

File tree

CONTRIBUTING.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ Every project is managed by the `build.zig` file.
4444
│ └── redBlackTrees.zig
4545
├── sort
4646
│ ├── bubbleSort.zig
47+
│ ├── heapSort.zig
4748
│ ├── insertionSort.zig
4849
│ ├── selectionSort.zig
4950
│ ├── mergeSort.zig

build.zig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ pub fn build(b: *std.Build) void {
4949
.name = "selectionSort.zig",
5050
.category = "sort",
5151
});
52+
if (std.mem.eql(u8, op, "sort/heapSort"))
53+
buildAlgorithm(b, .{
54+
.optimize = optimize,
55+
.target = target,
56+
.name = "heapSort.zig",
57+
.category = "sort",
58+
});
5259

5360
// Search algorithms
5461
if (std.mem.eql(u8, op, "search/bSearchTree"))

runall.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub fn main() !void {
3535
try runTest(allocator, "sort/mergesort");
3636
try runTest(allocator, "sort/insertsort");
3737
try runTest(allocator, "sort/selectionSort");
38+
try runTest(allocator, "sort/heapSort");
3839

3940
// Search
4041
try runTest(allocator, "search/bSearchTree");

sort/heapSort.zig

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
const std = @import("std");
2+
const expect = std.testing.expect;
3+
4+
pub fn sort(A: []i32) void {
5+
const n = A.len;
6+
if (n <= 1) return;
7+
8+
// Build heap (rearrange array)
9+
var i: usize = n / 2;
10+
while (i > 0) {
11+
i -= 1;
12+
heapify(A, n, i);
13+
}
14+
15+
// One by one extract an element from heap
16+
var end = n - 1;
17+
while (end > 0) : (end -= 1) {
18+
// Move current root to end
19+
std.mem.swap(i32, &A[0], &A[end]);
20+
21+
// Call max heapify on the reduced heap
22+
heapify(A, end, 0);
23+
}
24+
}
25+
26+
// To heapify a subtree rooted with node i which is
27+
// an index in arr[]. n is size of heap
28+
fn heapify(A: []i32, n: usize, start_index: usize) void {
29+
var i = start_index;
30+
31+
while (true) {
32+
var largest = i; // Initialize largest as root
33+
const l = 2 * i + 1; // left = 2*i + 1
34+
const r = 2 * i + 2; // right = 2*i + 2
35+
36+
// If left child is larger than root
37+
if (l < n and A[l] > A[largest])
38+
largest = l;
39+
40+
// If right child is larger than largest so far
41+
if (r < n and A[r] > A[largest])
42+
largest = r;
43+
44+
// If largest is not root
45+
if (largest != i) {
46+
std.mem.swap(i32, &A[i], &A[largest]);
47+
i = largest;
48+
} else {
49+
break;
50+
}
51+
}
52+
}
53+
54+
test "empty array" {
55+
const array: []i32 = &.{};
56+
sort(array);
57+
try expect(array.len == 0);
58+
}
59+
60+
test "array with one element" {
61+
var array: [1]i32 = .{5};
62+
sort(&array);
63+
try expect(array.len == 1);
64+
try expect(array[0] == 5);
65+
}
66+
67+
test "sorted array" {
68+
var array: [10]i32 = .{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
69+
sort(&array);
70+
for (array, 0..) |value, i| {
71+
try expect(value == (i + 1));
72+
}
73+
}
74+
75+
test "reverse order" {
76+
var array: [10]i32 = .{ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
77+
sort(&array);
78+
for (array, 0..) |value, i| {
79+
try expect(value == (i + 1));
80+
}
81+
}
82+
83+
test "unsorted array" {
84+
var array: [5]i32 = .{ 5, 3, 4, 1, 2 };
85+
sort(&array);
86+
for (array, 0..) |value, i| {
87+
try expect(value == (i + 1));
88+
}
89+
}
90+
91+
test "two last unordered" {
92+
var array: [10]i32 = .{ 1, 2, 3, 4, 5, 6, 7, 8, 10, 9 };
93+
sort(&array);
94+
for (array, 0..) |value, i| {
95+
try expect(value == (i + 1));
96+
}
97+
}
98+
99+
test "two first unordered" {
100+
var array: [10]i32 = .{ 2, 1, 3, 4, 5, 6, 7, 8, 9, 10 };
101+
sort(&array);
102+
for (array, 0..) |value, i| {
103+
try expect(value == (i + 1));
104+
}
105+
}
106+
107+
test "duplicates" {
108+
var array: [10]i32 = .{ 5, 3, 4, 1, 2, 5, 3, 4, 1, 2 };
109+
sort(&array);
110+
const expected: [10]i32 = .{ 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 };
111+
try std.testing.expectEqual(expected, array);
112+
}
113+
114+
test "all duplicates" {
115+
var array: [10]i32 = .{ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };
116+
sort(&array);
117+
const expected: [10]i32 = .{ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };
118+
try std.testing.expectEqual(expected, array);
119+
}
120+
121+
test "negative numbers" {
122+
var array: [10]i32 = .{ -1, -3, -2, -5, -4, -1, -3, -2, -5, -4 };
123+
sort(&array);
124+
const expected: [10]i32 = .{ -5, -5, -4, -4, -3, -3, -2, -2, -1, -1 };
125+
try std.testing.expectEqual(expected, array);
126+
}
127+
128+
test "mixed positive and negative" {
129+
var array: [10]i32 = .{ -1, 3, -2, 5, -4, -1, 3, -2, 5, -4 };
130+
sort(&array);
131+
const expected: [10]i32 = .{ -4, -4, -2, -2, -1, -1, 3, 3, 5, 5 };
132+
try std.testing.expectEqual(expected, array);
133+
}

0 commit comments

Comments
 (0)