From ebf993535a30db5cf03133c504b06b4c0bf38797 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 22 May 2021 11:40:14 +0200 Subject: [PATCH 1/2] Implemented MSD radix sort algorithm inplace --- sorts/msd_radix_sort.py | 79 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/sorts/msd_radix_sort.py b/sorts/msd_radix_sort.py index ee152bbc696a..af4f8f652ca3 100644 --- a/sorts/msd_radix_sort.py +++ b/sorts/msd_radix_sort.py @@ -74,6 +74,85 @@ def _msd_radix_sort(list_of_ints: List[int], bit_position: int) -> List[int]: return res +def msd_radix_sort_inplace(list_of_ints: List[int]): + """ + Inplace implementation of the MSD radix sort algorithm. + Sorts based on the binary representation of the integers. + >>> lst = [1, 345, 23, 89, 0, 3] + >>> msd_radix_sort_inplace(lst) + >>> lst == sorted(lst) + True + >>> lst = [1, 43, 0, 0, 0, 24, 3, 3] + >>> msd_radix_sort_inplace(lst) + >>> lst == sorted(lst) + True + >>> lst = [] + >>> msd_radix_sort_inplace(lst) + >>> lst == [] + True + >>> lst = [-1, 34, 23, 4, -42] + >>> msd_radix_sort_inplace(lst) + Traceback (most recent call last): + ... + ValueError: All numbers must be positive + """ + + length = len(list_of_ints) + if not list_of_ints or length == 1: + return + + if min(list_of_ints) < 0: + raise ValueError("All numbers must be positive") + + most_bits = max(len(bin(x)[2:]) for x in list_of_ints) + _msd_radix_sort_inplace(list_of_ints, most_bits, 0, length) + + +def _msd_radix_sort_inplace(list_of_ints: List[int], bit_position: int, + begin_index: int, end_index: int): + """ + Sort the given list based on the bit at bit_position. Numbers with a + 0 at that position will be at the start of the list, numbers with a + 1 at the end. + >>> lst = [45, 2, 32, 24, 534, 2932] + >>> _msd_radix_sort_inplace(lst, 1, 0, 3) + >>> lst == [32, 2, 45, 24, 534, 2932] + True + >>> lst = [0, 2, 1, 3, 12, 10, 4, 90, 54, 2323, 756] + >>> _msd_radix_sort_inplace(lst, 2, 4, 7) + >>> lst == [0, 2, 1, 3, 12, 4, 10, 90, 54, 2323, 756] + True + """ + if bit_position == 0 or end_index - begin_index <= 1: + return + + bit_position -= 1 + + i = begin_index + j = end_index - 1 + while i <= j: + changed = False + if not ((list_of_ints[i] >> bit_position) & 1): + # found zero at the beginning + i += 1 + changed = True + if (list_of_ints[j] >> bit_position) & 1: + # found one at the end + j -= 1 + changed = True + + if changed: + continue + + list_of_ints[i], list_of_ints[j] = list_of_ints[j], list_of_ints[i] + j -= 1 + if not j == i: + i += 1 + + _msd_radix_sort_inplace(list_of_ints, bit_position, begin_index, i) + _msd_radix_sort_inplace(list_of_ints, bit_position, i, end_index) + + if __name__ == "__main__": import doctest From 78c210e5e46435a63fb4eac091b71e7bdfb8162e Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 22 May 2021 11:48:31 +0200 Subject: [PATCH 2/2] Fixed formatting --- sorts/msd_radix_sort.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sorts/msd_radix_sort.py b/sorts/msd_radix_sort.py index af4f8f652ca3..4c3cea30ef68 100644 --- a/sorts/msd_radix_sort.py +++ b/sorts/msd_radix_sort.py @@ -108,8 +108,9 @@ def msd_radix_sort_inplace(list_of_ints: List[int]): _msd_radix_sort_inplace(list_of_ints, most_bits, 0, length) -def _msd_radix_sort_inplace(list_of_ints: List[int], bit_position: int, - begin_index: int, end_index: int): +def _msd_radix_sort_inplace( + list_of_ints: List[int], bit_position: int, begin_index: int, end_index: int +): """ Sort the given list based on the bit at bit_position. Numbers with a 0 at that position will be at the start of the list, numbers with a