Skip to content

Commit de99ee7

Browse files
committed
merge sort
1 parent a4e95b1 commit de99ee7

File tree

1 file changed

+105
-0
lines changed

1 file changed

+105
-0
lines changed

zig/src/sorting.zig

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
const std = @import("std");
22
const testing = std.testing;
33

4+
/// Sort an array using insertion sort.
5+
///
46
pub fn insertion_sort(comptime T: type, array: []T) void {
57
if (array.len == 0) {
68
return;
@@ -19,6 +21,89 @@ pub fn insertion_sort(comptime T: type, array: []T) void {
1921
}
2022
}
2123

24+
// merge 2 sorted sub-arrays
25+
//
26+
fn merge(comptime T: type, array: []T, comptime left: usize, comptime middle: usize, comptime right: usize) void {
27+
const length_left = middle - left + 1;
28+
const length_right = right - middle;
29+
30+
// create copies of the left and right arrays in-memory
31+
//
32+
// left: array[0 .. middle]
33+
// right: array[middle + 1 .. right]
34+
//
35+
var left_array = [_]T{0} ** length_left;
36+
var right_array = [_]T{0} ** length_right;
37+
{
38+
var index: usize = 0;
39+
while (index < length_left) : (index += 1) {
40+
left_array[index] = array[left + index];
41+
}
42+
43+
index = 0;
44+
while (index < length_right) : (index += 1) {
45+
right_array[index] = array[middle + 1 + index];
46+
}
47+
}
48+
49+
var left_index: usize = 0;
50+
var right_index: usize = 0;
51+
var array_index: usize = left;
52+
53+
// scan through the left and right arrays, inserting the smaller of either
54+
// into the correct position in the main array
55+
//
56+
while (left_index < length_left and right_index < length_right) {
57+
if (left_array[left_index] <= right_array[right_index]) {
58+
array[array_index] = left_array[left_index];
59+
left_index += 1;
60+
} else {
61+
array[array_index] = right_array[right_index];
62+
right_index += 1;
63+
}
64+
array_index += 1;
65+
}
66+
67+
// insert the remainder of left array into the main array
68+
while (left_index < length_left) {
69+
array[array_index] = left_array[left_index];
70+
left_index += 1;
71+
array_index += 1;
72+
}
73+
74+
// insert the remainder of right array into the main array
75+
while (right_index < length_right) {
76+
array[array_index] = right_array[right_index];
77+
right_index += 1;
78+
array_index += 1;
79+
}
80+
}
81+
82+
// sort the subarray from array[left .. right]
83+
//
84+
fn merge_sort_from(comptime T: type, array: []T, comptime left: usize, comptime right: usize) void {
85+
if (left < right) {
86+
const middle = left + (right - left) / 2;
87+
88+
// divide the problem into 2, sort each half
89+
merge_sort_from(T, array, left, middle);
90+
merge_sort_from(T, array, middle + 1, right);
91+
92+
// merge the sorted sub-arrays
93+
return merge(T, array, left, middle, right);
94+
}
95+
}
96+
97+
/// Sort an array using merge sort.
98+
///
99+
pub fn merge_sort(comptime T: type, array: []T, comptime length: usize) void {
100+
if (length <= 1) {
101+
return;
102+
}
103+
104+
merge_sort_from(T, array, 0, length - 1);
105+
}
106+
22107
test {
23108
testing.refAllDecls(@This());
24109
}
@@ -27,6 +112,9 @@ test "insertion_sort" {
27112
var empty = [_]u32{};
28113
insertion_sort(u32, &empty);
29114

115+
var single = [_]u32{42};
116+
insertion_sort(u32, &single);
117+
30118
var array = [_]u32{ 1, 5, 4, 2, 3 };
31119

32120
insertion_sort(u32, &array);
@@ -37,3 +125,20 @@ test "insertion_sort" {
37125
try testing.expectEqual(4, array[3]);
38126
try testing.expectEqual(5, array[4]);
39127
}
128+
129+
test "merge_sort" {
130+
var empty = [_]u32{};
131+
merge_sort(u32, &empty, empty.len);
132+
133+
var single = [_]u32{42};
134+
merge_sort(u32, &single, single.len);
135+
136+
var array = [_]u32{ 1, 5, 4, 2, 3 };
137+
merge_sort(u32, &array, array.len);
138+
139+
try testing.expectEqual(1, array[0]);
140+
try testing.expectEqual(2, array[1]);
141+
try testing.expectEqual(3, array[2]);
142+
try testing.expectEqual(4, array[3]);
143+
try testing.expectEqual(5, array[4]);
144+
}

0 commit comments

Comments
 (0)