Skip to content

Commit d36bf5d

Browse files
committed
Adding comb sort
1 parent 6fd3540 commit d36bf5d

File tree

3 files changed

+167
-11
lines changed

3 files changed

+167
-11
lines changed

sort/combSort.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Implementation of comb sort algorithm, an improvement of bubble sort
2+
// Reference: https://www.geeksforgeeks.org/comb-sort/
3+
4+
package sort
5+
6+
func getNextGap(gap int) int {
7+
gap = (gap * 10) / 13
8+
if gap < 1 {
9+
return 1
10+
}
11+
return gap
12+
}
13+
14+
func combSort(data []int) []int {
15+
n := len(data)
16+
gap := n
17+
swapped := true
18+
19+
for gap != 1 || swapped {
20+
gap = getNextGap(gap)
21+
swapped = false
22+
for i := 0; i < n-gap; i++ {
23+
if data[i] > data[i+gap] {
24+
data[i], data[i+gap] = data[i+gap], data[i]
25+
swapped = true
26+
}
27+
}
28+
}
29+
return data
30+
}

sort/countingsort.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// countingsort.go
2+
// description: Implementation of counting sort algorithm
3+
// details: A simple counting sort algorithm implementation
4+
// author [Phil](https://github.com/pschik)
5+
// see sort_test.go for a test implementation, test function TestQuickSort
6+
7+
// package sort provides primitives for sorting slices and user-defined collections
8+
package sort
9+
10+
func Count(data []int) []int {
11+
var aMin, aMax = -1000, 1000
12+
count := make([]int, aMax-aMin+1)
13+
for _, x := range data {
14+
count[x-aMin]++
15+
}
16+
z := 0
17+
for i, c := range count {
18+
for c > 0 {
19+
data[z] = i + aMin
20+
z++
21+
c--
22+
}
23+
}
24+
return data
25+
}

sort/sorts_test.go

Lines changed: 112 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,28 +23,24 @@ func testFramework(t *testing.T, sortingFunction func([]int) []int) {
2323
expected: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
2424
name: "Reversed Unsigned",
2525
},
26-
2726
//Sorted slice
2827
{
2928
input: []int{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
3029
expected: []int{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
3130
name: "Sorted Signed",
3231
},
33-
3432
//Reversed slice
3533
{
3634
input: []int{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10},
3735
expected: []int{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
3836
name: "Reversed Signed",
3937
},
40-
4138
//Reversed slice, even length
4239
{
4340
input: []int{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10},
4441
expected: []int{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
4542
name: "Reversed Signed #2",
4643
},
47-
4844
//Random order with repetitions
4945
{
5046
input: []int{-5, 7, 4, -2, 6, 5, 8, 3, 2, -7, -1, 0, -3, 9, -6, -4, 10, 9, 1, -8, -9, -10},
@@ -98,8 +94,73 @@ func TestHeap(t *testing.T) {
9894
testFramework(t, HeapSort)
9995
}
10096

97+
func TestCount(t *testing.T) {
98+
testFramework(t, Count)
99+
}
100+
101101
func TestQuick(t *testing.T) {
102-
testFramework(t, QuickSort)
102+
testCases := []struct {
103+
input []int
104+
expected []int
105+
name string
106+
}{
107+
//Sorted slice
108+
{
109+
input: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
110+
expected: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
111+
name: "Sorted Unsigned",
112+
},
113+
//Reversed slice
114+
{
115+
input: []int{10, 9, 8, 7, 6, 5, 4, 3, 2, 1},
116+
expected: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
117+
name: "Reversed Unsigned",
118+
},
119+
//Sorted slice
120+
{
121+
input: []int{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
122+
expected: []int{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
123+
name: "Sorted Signed",
124+
},
125+
//Reversed slice
126+
{
127+
input: []int{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10},
128+
expected: []int{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
129+
name: "Reversed Signed",
130+
},
131+
//Reversed slice, even length
132+
{
133+
input: []int{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10},
134+
expected: []int{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
135+
name: "Reversed Signed #2",
136+
},
137+
//Random order with repetitions
138+
{
139+
input: []int{-5, 7, 4, -2, 6, 5, 8, 3, 2, -7, -1, 0, -3, 9, -6, -4, 10, 9, 1, -8, -9, -10},
140+
expected: []int{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10},
141+
name: "Random order Signed",
142+
},
143+
//Single-entry slice
144+
{
145+
input: []int{1},
146+
expected: []int{1},
147+
name: "Singleton",
148+
},
149+
{
150+
input: []int{},
151+
expected: []int{},
152+
name: "Empty Slice",
153+
},
154+
}
155+
for _, test := range testCases {
156+
t.Run(test.name, func(t *testing.T) {
157+
QuickSort(test.input)
158+
if !reflect.DeepEqual(test.input, test.expected) {
159+
t.Errorf("test %s failed", test.name)
160+
t.Errorf("actual %v expected %v", test.input, test.expected)
161+
}
162+
})
163+
}
103164
}
104165

105166
func TestShell(t *testing.T) {
@@ -122,6 +183,10 @@ func TestSelection(t *testing.T) {
122183
testFramework(t, SelectionSort)
123184
}
124185

186+
func TestComb(t *testing.T) {
187+
testFramework(t, combSort)
188+
}
189+
125190
//END TESTS
126191

127192
func benchmarkFramework(b *testing.B, f func(arr []int) []int) {
@@ -136,23 +201,18 @@ func benchmarkFramework(b *testing.B, f func(arr []int) []int) {
136201
//Reversed slice
137202
{[]int{10, 9, 8, 7, 6, 5, 4, 3, 2, 1},
138203
[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "Reversed Unsigned"},
139-
140204
//Sorted slice
141205
{[]int{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
142206
[]int{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "Sorted Signed"},
143-
144207
//Reversed slice
145208
{[]int{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10},
146209
[]int{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "Reversed Signed"},
147-
148210
//Reversed slice, even length
149211
{[]int{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10},
150212
[]int{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "Reversed Signed #2"},
151-
152213
//Random order with repetitions
153214
{[]int{-5, 7, 4, -2, 6, 5, 8, 3, 2, -7, -1, 0, -3, 9, -6, -4, 10, 9, 1, -8, -9, -10},
154215
[]int{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10}, "Random order Signed"},
155-
156216
//Empty slice
157217
{[]int{}, []int{}, "Empty"},
158218
//Single-entry slice
@@ -188,8 +248,45 @@ func BenchmarkHeap(b *testing.B) {
188248
benchmarkFramework(b, HeapSort)
189249
}
190250

251+
func BenchmarkCount(b *testing.B) {
252+
benchmarkFramework(b, Count)
253+
}
254+
191255
func BenchmarkQuick(b *testing.B) {
192-
benchmarkFramework(b, QuickSort)
256+
var sortTests = []struct {
257+
input []int
258+
expected []int
259+
name string
260+
}{
261+
//Sorted slice
262+
{[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
263+
[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "Sorted Unsigned"},
264+
//Reversed slice
265+
{[]int{10, 9, 8, 7, 6, 5, 4, 3, 2, 1},
266+
[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "Reversed Unsigned"},
267+
//Sorted slice
268+
{[]int{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
269+
[]int{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "Sorted Signed"},
270+
//Reversed slice
271+
{[]int{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10},
272+
[]int{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "Reversed Signed"},
273+
//Reversed slice, even length
274+
{[]int{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10},
275+
[]int{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "Reversed Signed #2"},
276+
//Random order with repetitions
277+
{[]int{-5, 7, 4, -2, 6, 5, 8, 3, 2, -7, -1, 0, -3, 9, -6, -4, 10, 9, 1, -8, -9, -10},
278+
[]int{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10}, "Random order Signed"},
279+
//Empty slice
280+
{[]int{}, []int{}, "Empty"},
281+
//Single-entry slice
282+
{[]int{1}, []int{1}, "Singleton"},
283+
}
284+
b.ResetTimer()
285+
for i := 0; i < b.N; i++ {
286+
for _, test := range sortTests {
287+
QuickSort(test.input)
288+
}
289+
}
193290
}
194291

195292
func BenchmarkShell(b *testing.B) {
@@ -213,4 +310,8 @@ func BenchmarkSelection(b *testing.B) {
213310
benchmarkFramework(b, SelectionSort)
214311
}
215312

313+
func BenchmarkComb(b *testing.B) {
314+
benchmarkFramework(b, combSort)
315+
}
316+
216317
//END BENCHMARKS

0 commit comments

Comments
 (0)