1
1
const std = @import ("std" );
2
2
const testing = std .testing ;
3
3
4
+ /// Sort an array using insertion sort.
5
+ ///
4
6
pub fn insertion_sort (comptime T : type , array : []T ) void {
5
7
if (array .len == 0 ) {
6
8
return ;
@@ -19,6 +21,89 @@ pub fn insertion_sort(comptime T: type, array: []T) void {
19
21
}
20
22
}
21
23
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
+
22
107
test {
23
108
testing .refAllDecls (@This ());
24
109
}
@@ -27,6 +112,9 @@ test "insertion_sort" {
27
112
var empty = [_ ]u32 {};
28
113
insertion_sort (u32 , & empty );
29
114
115
+ var single = [_ ]u32 {42 };
116
+ insertion_sort (u32 , & single );
117
+
30
118
var array = [_ ]u32 { 1 , 5 , 4 , 2 , 3 };
31
119
32
120
insertion_sort (u32 , & array );
@@ -37,3 +125,20 @@ test "insertion_sort" {
37
125
try testing .expectEqual (4 , array [3 ]);
38
126
try testing .expectEqual (5 , array [4 ]);
39
127
}
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