Skip to content

Commit

Permalink
Decimal + base 4 display for radix
Browse files Browse the repository at this point in the history
  • Loading branch information
lee-naish committed Jan 28, 2025
1 parent 09ee9dc commit 364d5f9
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 37 deletions.
1 change: 1 addition & 0 deletions src/algorithms/controllers/straightRadixSort.js
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ export default {

chunker.add(SRS_BOOKMARKS.radix_sort,
(vis, array) => {
vis.mask.setAddBase4(true); // add Base 4 display
setArray(vis.array, array);

if (isCountExpanded()) {
Expand Down
77 changes: 44 additions & 33 deletions src/algorithms/explanations/MSDRadixSortExp.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,58 @@
# Most Significant Digit / Bit Radix Exchange Sort
# Most Significant Digit Radix Sort

---

## Introduction to Most Significant Digit / Bit Radix Exchange Sort (MSDRexSort)
The Most Significant Digit/Bit (MSD/MSB) variant of Radix Sort is a recursive algorithm that sorts an array (of integers)
by focusing on individual bits, starting from the most significant (left most) bit and working down to the least significant
one as indicated by the binary representation and mask. <br>
## Introduction
Unlike most sorting algorithms, which are based on *comparison* of whole
keys, radix sorting is based on examining individual "digits" in the
keys.
Most Significant Digit (MSD) Radix Sort (also known as Radix Exchange Sort)
is a recursive algorithm that sorts an array of keys (here we use integers)
by focusing on individual bits, starting from the most significant (left
most) bit of each key and working down to the least significant bit.

By sorting based on the most significant bits first, it ensures that larger or more important bits are considered before
smaller ones.

## Processes of MSDRexSort
## The algorithm

### 1. Initial Setup:
* The ```Rexsort``` function sets up the sorting process by determining the largest bit position in the array element,
referred to as the ```mask```. This ```mask``` serves as a reference for which bit is being compared in the following
steps.
* The recursive sorting function ```RexsortRecursive``` is then called to sort the entire array starting from the most significant
bit.
* The ```Rexsort``` function sets up the sorting process by determining the
most significant bit position in the array elements.
* A *mask* is created that has a 1 in this bit position and 0 elsewhere. The
mask is used to extract bits from keys during sorting.
* The recursive sorting function ```RexsortRecursive``` is then called to
sort the entire array starting with this mask. The mask is shifted to the
right for recursive calls.
### 2. Recursive Sorting:
* The ```RexsortRecursive``` function works on sub-arrays, defined by a left and right index/guard, and recursively divides
the array based on the current bit position determined by the ```mask```.
* If the segment contains more than one element, ```i < j``` and the mask is greater than 0, the function proceeds to partition
the array.
* The ```RexsortRecursive``` function works on sub-arrays, defined by a left
and right index, and additionally has the current mask as a parameter.
* If the sub-array contains no more than one element or the mask is 0, the
function simply returns.
* Otherwise, the array is first *partitioned* into two sub-arrays using the
mask bit. The
(smaller) keys with a 0 mask bit are put at the left and (larger) keys with a 1
mask bit are put at the right (similar to partition in quicksort).
* Finally, the two sub-arrays are recursively sorted, using the appropriate
indices for the sub-arrays boundaries and and the mask shifted one bit
position to the right.

### 3. Partitioning Based on Current Bit
* The guards ```i``` and ```j```, are set at the left and right of the array segment.
* These guards move towards each other, adjusting positions based on the bit value at the current ```mask``` position
i.e.,
* Increment ```i``` until an element with a 1 in the current ```mask``` position is found.
* Decrement ```j``` until an element with a 0 in the current ```mask``` position is found.

* If the two guards have not crossed, perform a swap. to ensure that 0s and placed on the left and 1s on the right.
* The indices ```i``` and ```j```, are set at the left and right of the array segment.
* These indices move towards each other, adjusting positions based on the
mask bit of each key:
* Increment ```i``` until an element with a 1 as the mask bit is reached
* Decrement ```j``` until an element with a 0 as the mask bit is reached

### 4. Completion
Once the array is done with sorting its left and right sub arrays, the ```mask``` is reduced by 1 to shift the focus to
the next bit. The recursion continues until the entire array is sorted based on all bits, from the most significant bit to
the least significant bit.
* If the two guards have not crossed, perform a swap to ensure that 0s are placed on the left and 1s on the right.

## Complexity
### Time Complexity
* ```n``` is the number elements in the array
* ```log(largest bit)``` is the number of bits required to represent the largest number in the array
* Hence, overall time complexity is ```O(n * log(largest bit)```
* Partitioning takes```O(n)```, where ```n``` is the number elements in the
array.
* If we *assume the number of bits is limited* the overall time complexity is: ```O(n)```
* Note that the best comparison-based sorting algorithms have ```O(n log n)```
complexity, but the number of bits is typically related to ```log n```
so radix sorts are not necessarily better.

### Space Complexity
```O(log(largest bit))```
Extra space is required for the stack but, unlike quicksort, the stack depth
is limited by the number of bits, so it is a constant (if the number of bits
is limited).
7 changes: 5 additions & 2 deletions src/components/DataStructures/Mask/BinaryRenderer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import React, { useCallback } from 'react';
import styles from './BinaryRenderer.module.scss';
import PropTypes from 'prop-types';

const BinaryRenderer = ({ header, data, maxBits, highlight }) => {
// renders integers as binary (by default), or other base, with optional
// highlighting of some digits
const BinaryRenderer = ({ header, data, maxBits, highlight, base = 2 }) => {
const binary = useCallback(() => {
let binaryString = data.toString(2);
let binaryString = data.toString(base);
if (binaryString.length < maxBits) {
binaryString = binaryString.padStart(maxBits, '0');
}
Expand Down Expand Up @@ -38,6 +40,7 @@ BinaryRenderer.propTypes = ({
data: PropTypes.number.isRequired,
maxBits: PropTypes.number,
highlight: PropTypes.array,
base: PropTypes.number,
});

export default BinaryRenderer;
25 changes: 23 additions & 2 deletions src/components/DataStructures/Mask/MaskRenderer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,33 @@ class MaskRenderer extends Renderer {
this.toggleZoom(true);
}

// display key in decimal, base 4 (optional) and binary plus
// mask in binary; some (non-decimal) digits highlighted
renderData() {
const { binaryData, maskData, maxBits, highlight } = this.props.data;
const { binaryData, maskData, maxBits, highlight, addBase4 } = this.props.data;
let extra = <div/>;
if (addBase4) {
console.log([highlight,highlight.map((b) => Math.trunc(parseInt(b)/2))]);
extra =
<BinaryRenderer
header={"Base 4"}
data={binaryData}
maxBits={maxBits/2}
highlight={highlight.map((b) => Math.trunc(parseInt(b)/2))}
base={4}
/>
}
return (
<div className={styles.container}>
<BinaryRenderer
header={"Binary Rep"}
header={"Decimal"}
data={binaryData}
highlight={[]}
base={10}
/>
{extra}
<BinaryRenderer
header={"Binary"}
data={binaryData}
maxBits={maxBits}
highlight={highlight}
Expand Down
5 changes: 5 additions & 0 deletions src/components/DataStructures/Mask/MaskTracer.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ class MaskTracer extends Tracer {
this.binaryData = 0;
this.maskData = 0;
this.highlight = [];
this.addBase4 = false;
}

setAddBase4(b) {
this.addBase4 = b;
}

setMaxBits(bits) {
Expand Down

0 comments on commit 364d5f9

Please sign in to comment.