What is Bitonic sort?
The bitonic sequence is a sequence in which the numbers are in increasing order, and after a certain point, they start decreasing. For example, the sequence [1,3,5,4,2] is a bitonic sequence.
The bitonic sort is a comparison-based sorting algorithm that sorts by converting elements to the bitonic sequence. It was introduced by Ken Batcher in 1968 for parallel computing architectures. The basic working of bitonic sort is to split the array into bitonic sequences and then merge them in a bitonic manner until the array is sorted completely. It’s a better choice for parallel implementation because it compares the elements in a predetermined sequence.
Algorithm steps
Let’s list down the steps of bitonic sort:
Split the array into two halves: In this step, the array is divided into two halves for sorting.
Sort each half: The first half is sorted in ascending order and the second is in descending order, to make it the bitonic sequence.
Merge the sorted halves: Both halves of the arrays are then sorted in ascending or descending order accordingly.
Repeat until the array is sorted: This process is repeated recursively until the array is sorted in the desired order.
Play the following slides to visualize the working of the bitonic sort:
Code example
Let’s implement the Python code of bitonic sort in the following playground:
def bitonic_sort(array, asc=True):def bitonic_merge(array, p1, mid, p2, asc=True):n = p2-p1temp_array = [0]*ni, j = p1, p2-1ind = 0 if asc else n-1step = 1 if asc else -1while i < mid and j >= mid:if array[i] < array[j]:temp_array[ind]= array[i]i += 1else:temp_array[ind] = array[j]j -= 1ind += stepwhile i < mid:temp_array[ind]= array[i]ind += stepi += 1while j >= mid:temp_array[ind] = array[j]ind += stepj -= 1array[p1:p2] = temp_arrayreturndef sort(array, p1, p2, asc=True):if p2-p1 < 2: returnmid = (p1+p2)//2sort(array, p1, mid, asc=True) # sorting the left subarray in ascending ordersort(array, mid, p2, asc=False) # sorting the right subarray in descending orderbitonic_merge(array, p1, mid, p2, asc) # merging both subarrays (the bitonic sequence)returnsort(array, 0, len(array), asc=asc)returnarray = [18, 13, 15, 11, 19, 12, 14, 16]print("Unsorted array:", array)bitonic_sort(array)print("Sorted array in ascending order:", array)array = [18, 13, 15, 11, 19, 12, 14, 16]bitonic_sort(array, asc=False)print("Sorted array in descending order:", array)
Code explanation
Let's discuss the code below:
Lines 2–26: We define a helper function
bitonic_merge()that sorts the bitonic sequence. This function receives five arguments:arrayholds the actual array,p1indicates the first index of the first subarray,midindicates the center index, which is the first index of the second subarray,p2indicates the boundary of the second subarray, andascholds the boolean value that indicates to merge both subarrays in ascending or descending order. The subarray fromp1top2is the bitonic sequence. In this function:Line 3: We define a variable
nand store the count of the elements to merge by subtractingp1fromp2.Line 4: We define a temporary array
temp_arrayof sizen.Line 5: We define two loops variables
iandj, and assign them to the initial indexp1and the last index of the subarrayp2-1, respectively.Line 6: We define a variable
indto store the index for thetemp_array. We assign it a value of 0 (the first index) if theascvalue isTrue, andn-1(the last index) otherwise.Line 7: We define the variable
stepto move theindforward or backward. We assign it the value of 1 if theascvalue isTrueand -1 otherwise.Lines 9–16: We use the
whileloop to iterate through both subarrays. We compare the elements of thearrayat theith andjth index and assign the required element to thetemp_arrayat indexind. We increment the loop variable, and index variableindaccordingly.Lines 17–20: We shift the remaining elements of the first subarray to the
temp_array.Lines 21–24: Similarly, we shift the remaining elements of the second subarray to the
temp_array.Line 26: Lastly, we copy back the
temp_arrayto the original array in the range ofp1top2.
Lines 29–35: We define a function
sort()that recursively sorts thearray. This function receives four parameters:array,p1,p2, andasc. In this function:Line 30: We define the base case for the
sort()function. The function returns if the elements are less than 2.Line 31: We find the center index
midby calculating the integer average ofp1andp2.Line 32: We call the
sort()function to sort thearrayfromp1tomidin ascending order.Line 33: We call the
sort()function to sort thearrayfrommidtop2in descending order. Thearrayfrom the indexp1top2is now a bitonic sequence.Line 34: Finally, we call the
bitonic_merge()function to sort thearrayfrom the indexp1top2in the given orderasc.
Line 37: We call the
sort()function to sort the completearray. We pass thearrayboundaries in thep1andp2variables. We also pass theascto sort in the given order.Lines 40–41: We create an unsorted
arrayand print thearraybefore sorting.Lines 43–44: We call the
bitonic_sort()function and print thearrayafter sorting it in ascending order.Lines 46–48: We reassign the same values to the
arrayand call thebitonic_sort()function by passing theFalsevalue to theascparameter. We print thearrayafter sorting it in descending order.
Complexity
The time complexity of the bitonic sort is
The space complexity of the bitonic sort is
Benefits and limitations
Let’s discuss some benefits and limitations of the bitonic sort.
Benefits
Bitonic sort is highly suitable for parallel machines.
The algorithm of bitonic sort is simple to understand and implement.
It has a time complexity of
, which is similar to merge sort and other efficient sorting algorithms.
Limitations
The bitonic sort is not a stable sorting algorithm, which means it doesn’t guarantee that the order of similar elements in the sorted array will be maintained.
The bitonic sort is not an in-place sorting algorithm, which means it requires extra space to sort the data.
It’s not as widely used as other sorting algorithms, such as quicksort and merge sort, because it’s less efficient on sequential machines.
Bitonic sort vs. merge sort
The implementation of bitonic sort looks similar to merge sort, but it’s different in multiple ways. Let’s compare them in the following table:
Merge sort | Bitonic sort |
It uses the divide and conquer paradigm to sort the array. | It uses the bitonic sequence paradigm to sort the array. |
It’s not naturally suitable and designed for parallel architectures. | It’s designed for parallel architectures. |
It’s a stable sorting algorithm. | It’s not a stable sorting algorithm. |
It’s widely used in different applications where stable and efficient sorting is required. | It’s not widely used as it was designed for parallel computing architectures. |
Conclusion
The bitonic sort has significant importance in parallel computing architectures, although it’s not widely used. It’s efficient to use the bitonic sequence to sort the data, which makes it a valuable addition to the sorting algorithm family. It can be a good choice in modern-day computing applications due to its unique characteristics and sorting principles.
Unlock your potential: Sorting algorithms series – all in one place!
To continue your exploration of sorting algorithms, check out our series of Answers below:
What are sorting algorithms?
Understand the fundamentals of sorting algorithms and their role in organizing data efficiently.What is tree sort?
Learn how tree-based structures can be used to sort elements efficiently.What is Bitonic sort?
Discover Bitonic Sort, a parallel sorting algorithm ideal for hardware implementations.What is Flash Sort?
Explore Flash Sort, a hybrid sorting technique designed for fast performance on large datasets.How to implement the pigeonhole sorting algorithm in Python
A step-by-step guide to implementing Pigeonhole Sort in Python for efficient data sorting.How to implement comb sort in C++
Learn how to implement Comb Sort in C++ to improve sorting efficiency over Bubble Sort.Implementation of the cocktail sort in C++
Understand how Cocktail Sort refines Bubble Sort for bidirectional sorting in C++.How to implement cocktail sort in Python
Implement Cocktail Sort in Python to enhance sorting performance with a two-way pass.How to implement Gnome sort in C++
Explore the simplicity of Gnome Sort and its implementation in C++.How to implement pancake sort in Java?
Learn how to implement Pancake Sort in Java, inspired by flipping pancakes to sort stacks.Comparison of linear-time sorting algorithms
Analyze and compare different linear-time sorting algorithms to understand their efficiency.
Free Resources