Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Bitonic sort sorting algorithm implementation #9

Merged
merged 2 commits into from
Oct 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions array/sort/bitonic_sort/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Bitonic Sort

Bitonic sort is a parallel sorting algorithm which performs O(n2 log n) comparisons. Although, the number of comparisons are more than that in any other popular sorting algorithm, It performs better for the parallel implementation because elements are compared in predefined sequence which must not be depended upon the data being sorted. The predefined sequence is called Bitonic sequence.

### Algorithm
1. Form a Bitonic sequence from the given random sequence which we have formed in the above step. We can consider it as the first step in our procedure. After this step, we get a sequence whose first half is sorted in ascending order while second step is sorted in descending order.
2. Compare first element of first half with the first element of the second half, then second element of the first half with the second element of the second half and so on. Swap the elements if any element in the second half is found to be smaller.
3. After the above step, we got all the elements in the first half smaller than all the elements in the second half. The compare and swap results into the two sequences of n/2 length each. Repeat the process performed in the second step recursively onto every sequence until we get single sorted sequence of length n.

### Complexity
```
Worst Case Time Complexity: O(log 2 n)
Best Case Time Complexity: O(log 2 n)
Average Time Complexity: O(log 2 n)
```
35 changes: 35 additions & 0 deletions array/sort/bitonic_sort/bitonic_sort.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package sort

// BitonicSort sorts slice using parallel sorting algorithm,
// which performs O(n2 log n) comparisons.
//
// This sort works when size of input is power of 2.
//
func BitonicSort(array []int) {
bitonicSort(array, 0, len(array), true)
}

func bitonicSort(array []int, low, count int, d bool) {
if count < 2 {
return
}
k := count / 2
bitonicSort(array, low, k, true)
bitonicSort(array, low+k, k, false)
merge(array, low, count, d)
}

func merge(array []int, low, count int, d bool) {
if count < 2 {
return
}
k := count / 2
for i := 0; i < low+k; i++ {
if d != (array[i] > array[i+k]) {
continue
}
array[i], array[i+k] = array[i+k], array[i]
}
merge(array, low, k, d)
merge(array, low+k, k, d)
}
43 changes: 43 additions & 0 deletions array/sort/bitonic_sort/bitonic_sort_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package sort

import (
"math/rand"
"testing"
"time"

"github.com/stretchr/testify/require"
)

func init() {
rand.Seed(time.Now().UnixNano())
}

func Test_BitonicSort(t *testing.T) {
tt := []struct {
name string
array []int
expResult []int
}{
{
name: "test_simple",
array: []int{1, 10, 2, 3, 1, 23, 45, 21},
expResult: []int{1, 1, 2, 3, 10, 21, 23, 45},
},
{
name: "test_from_100_to_0",
array: []int{64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1},
expResult: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64},
},
{
name: "test_256_elements",
array: []int{464, 607, 524, 772, 925, 90, 141, 651, 555, 319, 741, 263, 600, 558, 676, 514, 61, 308, 641, 261, 332, 102, 302, 374, 797, 11, 98, 909, 206, 404, 187, 916, 686, 301, 188, 998, 361, 252, 662, 701, 254, 759, 513, 986, 250, 490, 419, 18, 379, 796, 650, 142, 919, 794, 170, 453, 705, 205, 138, 963, 198, 207, 163, 458, 52, 366, 926, 846, 884, 701, 530, 931, 203, 859, 899, 902, 848, 879, 475, 528, 469, 68, 781, 876, 46, 32, 51, 598, 149, 281, 312, 506, 609, 910, 584, 996, 651, 902, 627, 751, 694, 660, 546, 388, 804, 878, 505, 855, 614, 913, 260, 431, 95, 861, 177, 192, 396, 675, 597, 212, 519, 808, 180, 36, 430, 636, 907, 935, 196, 252, 37, 924, 711, 158, 81, 501, 274, 694, 771, 249, 129, 39, 711, 369, 257, 650, 195, 554, 940, 481, 640, 319, 799, 180, 231, 935, 808, 59, 510, 688, 494, 481, 51, 111, 481, 977, 128, 143, 156, 983, 428, 348, 677, 639, 147, 264, 430, 26, 282, 909, 462, 840, 227, 42, 936, 420, 398, 350, 75, 485, 276, 945, 826, 967, 452, 261, 445, 5, 387, 437, 232, 965, 679, 811, 389, 840, 131, 738, 677, 14, 722, 355, 907, 645, 387, 955, 977, 597, 804, 276, 607, 465, 520, 907, 72, 43, 162, 233, 431, 584, 409, 805, 581, 908, 593, 963, 600, 915, 784, 985, 688, 791, 791, 503, 13, 866, 540, 475, 84, 272, 742, 326, 456, 801, 384, 564},
expResult: []int{5, 11, 13, 14, 18, 26, 32, 36, 37, 39, 42, 43, 46, 51, 51, 52, 59, 61, 68, 72, 75, 81, 84, 90, 95, 98, 102, 111, 128, 129, 131, 138, 141, 142, 143, 147, 149, 156, 158, 162, 163, 170, 177, 180, 180, 187, 188, 192, 195, 196, 198, 203, 205, 206, 207, 212, 227, 231, 232, 233, 249, 250, 252, 252, 254, 257, 260, 261, 261, 263, 264, 272, 274, 276, 276, 281, 282, 301, 302, 308, 312, 319, 319, 326, 332, 348, 350, 355, 361, 366, 369, 374, 379, 384, 387, 387, 388, 389, 396, 398, 404, 409, 419, 420, 428, 430, 430, 431, 431, 437, 445, 452, 453, 456, 458, 462, 464, 465, 469, 475, 475, 481, 481, 481, 485, 490, 494, 501, 503, 505, 506, 510, 513, 514, 519, 520, 524, 528, 530, 540, 546, 554, 555, 558, 564, 581, 584, 584, 593, 597, 597, 598, 600, 600, 607, 607, 609, 614, 627, 636, 639, 640, 641, 645, 650, 650, 651, 651, 660, 662, 675, 676, 677, 677, 679, 686, 688, 688, 694, 694, 701, 701, 705, 711, 711, 722, 738, 741, 742, 751, 759, 771, 772, 781, 784, 791, 791, 794, 796, 797, 799, 801, 804, 804, 805, 808, 808, 811, 826, 840, 840, 846, 848, 855, 859, 861, 866, 876, 878, 879, 884, 899, 902, 902, 907, 907, 907, 908, 909, 909, 910, 913, 915, 916, 919, 924, 925, 926, 931, 935, 935, 936, 940, 945, 955, 963, 963, 965, 967, 977, 977, 983, 985, 986, 996, 998},
},
}
for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) {
BitonicSort(tc.array)
require.Equal(t, tc.expResult, tc.array)
})
}
}