Skip to content

Commit dfa606a

Browse files
committed
straightRadixSort various improvements
+ minor one for msort_arr_nat
1 parent afa551a commit dfa606a

File tree

3 files changed

+104
-54
lines changed

3 files changed

+104
-54
lines changed

src/algorithms/controllers/straightRadixSort.js

Lines changed: 76 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// Some animation deleted, some added; could delete some commented out stuff
12
import ArrayTracer from '../../components/DataStructures/Array/Array1DTracer';
23
import MaskTracer from '../../components/DataStructures/Mask/MaskTracer';
34
import { areExpanded } from './collapseChunkPlugin';
@@ -8,10 +9,10 @@ const SRS_BOOKMARKS = {
89
radix_sort: 1,
910
max_number: 2,
1011
counting_sort_for_loop: 3,
11-
counting_sort: 4,
12-
count_nums: 5,
13-
cumulative_sum: 6,
14-
populate_array: 7,
12+
// counting_sort: 4, // no longer used
13+
// count_nums: 5, // no longer used
14+
// cumulative_sum: 6, // no longer used
15+
// populate_array: 7, // no longer used
1516
populate_for_loop: 8,
1617
insert_into_array: 9,
1718
copy: 10,
@@ -20,6 +21,9 @@ const SRS_BOOKMARKS = {
2021
add_count_for_loop: 13,
2122
cum_sum_for_loop: 14,
2223
add_cum_sum: 15,
24+
zero_counts: 16,
25+
get_digit1: 17,
26+
dec_count: 18,
2327
};
2428

2529
const isCountExpanded = () => {
@@ -63,6 +67,8 @@ const bitsAtIndex = (num, index, bits) => {
6367
return num >> (index * bits) & ((1 << bits) - 1);
6468
};
6569

70+
// could check that isArray is defined and avoid some of the
71+
// isCountExpanded() checks elsewhere
6672
const setArray = (visArray, array) => {
6773
visArray.set(array, 'straightRadixSort');
6874
};
@@ -83,11 +89,21 @@ export default {
8389
const count = Array.apply(null, Array(1 << bits)).map(() => 0);
8490
let lastBit = -1;
8591

86-
chunker.add(SRS_BOOKMARKS.count_nums);
92+
chunker.add(SRS_BOOKMARKS.zero_counts,
93+
(vis, count) => {
94+
if (isCountExpanded()) {
95+
setArray(vis.countArray, count);
96+
}
97+
},
98+
[count]
99+
);
87100

88101
for (let i = 0; i < n; i++) {
89102
chunker.add(SRS_BOOKMARKS.add_count_for_loop,
90-
(vis, i, lastBit) => {
103+
(vis, i, lastBit, count) => {
104+
if (isCountExpanded()) {
105+
setArray(vis.countArray, count);
106+
}
91107
if (i !== 0) {
92108
unhighlight(vis.array, i - 1);
93109
}
@@ -99,7 +115,7 @@ export default {
99115
highlight(vis.array, i);
100116
updateBinary(vis, A[i]);
101117
},
102-
[i, lastBit]
118+
[i, lastBit, count]
103119
);
104120

105121
const bit = bitsAtIndex(A[i], k, bits);
@@ -118,6 +134,7 @@ export default {
118134
lastBit = bit;
119135
}
120136

137+
/*
121138
chunker.add(SRS_BOOKMARKS.cumulative_sum,
122139
(vis, n, lastBit) => {
123140
unhighlight(vis.array, n - 1);
@@ -128,15 +145,23 @@ export default {
128145
},
129146
[n, lastBit]
130147
);
148+
*/
131149

132150
for (let i = 1; i < count.length; i++) {
133151
chunker.add(SRS_BOOKMARKS.cum_sum_for_loop,
134-
(vis, i) => {
135-
if (i === 1 && isCountExpanded()) {
136-
highlight(vis.countArray, 0);
152+
(vis, i, n, lastBit) => {
153+
if (isCountExpanded()) {
154+
if (i === 1) {
155+
unhighlight(vis.array, n - 1);
156+
} else
157+
unhighlight(vis.countArray, i-1, false);
158+
if (i === 1 && isCountExpanded()) {
159+
unhighlight(vis.countArray, lastBit);
160+
}
161+
highlight(vis.countArray, i);
137162
}
138163
},
139-
[i]
164+
[i, n, lastBit]
140165
);
141166

142167
count[i] += count[i - 1];
@@ -145,15 +170,16 @@ export default {
145170
(vis, count, i) => {
146171
if (isCountExpanded()) {
147172
setArray(vis.countArray, count);
148-
highlight(vis.countArray, i);
173+
highlight(vis.countArray, i, false);
149174
}
150175
},
151176
[count, i]
152177
)
153178
}
154179

155-
const sortedA = Array.apply(null, Array(n)).map(() => 0);
180+
const sortedA = Array.apply(null, Array(n)).map(() => undefined);
156181

182+
/*
157183
chunker.add(SRS_BOOKMARKS.populate_array,
158184
(vis, countLength) => {
159185
if (isCountExpanded()) {
@@ -162,31 +188,54 @@ export default {
162188
},
163189
[count.length]
164190
);
191+
*/
165192

166-
chunker.add(SRS_BOOKMARKS.populate_for_loop);
193+
// chunker.add(SRS_BOOKMARKS.populate_for_loop);
167194

168195
let bit;
169196

170197
for (let i = n - 1; i >= 0; i--) {
171198
const num = A[i];
199+
chunker.add(SRS_BOOKMARKS.populate_for_loop,
200+
(vis, num, i, bit, count, sortedA) => {
201+
if (i === n - 1) {
202+
if (isCountExpanded()) {
203+
unhighlight(vis.countArray, count.length - 1, false);
204+
}
205+
} else {
206+
unhighlight(vis.array, i + 1);
207+
if (isCountExpanded()) {
208+
setArray(vis.countArray, count);
209+
setArray(vis.tempArray, sortedA);
210+
unhighlight(vis.countArray, bit);
211+
unhighlight(vis.tempArray, count[bit]);
212+
}
213+
}
214+
updateBinary(vis, num);
215+
highlight(vis.array, i);
216+
},
217+
[num, i, bit, count, sortedA]
218+
);
172219
bit = bitsAtIndex(num, k, bits);
173220
count[bit]--;
221+
chunker.add(SRS_BOOKMARKS.dec_count,
222+
(vis, num, i, bit, count, sortedA) => {
223+
224+
if (isCountExpanded()) {
225+
setArray(vis.countArray, count);
226+
highlight(vis.countArray, bit);
227+
}
228+
},
229+
[num, i, bit, count, sortedA]
230+
);
174231
sortedA[count[bit]] = num;
175232
chunker.add(SRS_BOOKMARKS.insert_into_array,
176233
(vis, num, i, bit, count, sortedA) => {
177-
if (i !== n - 1) {
178-
unhighlight(vis.array, i + 1);
179-
}
180234

181235
if (isCountExpanded()) {
182-
setArray(vis.countArray, count);
183236
setArray(vis.tempArray, sortedA);
184-
highlight(vis.countArray, bit);
185237
highlight(vis.tempArray, count[bit]);
186238
}
187-
188-
updateBinary(vis, num);
189-
highlight(vis.array, i);
190239
},
191240
[num, i, bit, count, sortedA]
192241
);
@@ -249,7 +298,7 @@ export default {
249298

250299
A = countingSort(A, k, n, BITS);
251300

252-
chunker.add(SRS_BOOKMARKS.counting_sort);
301+
// chunker.add(SRS_BOOKMARKS.counting_sort);
253302
}
254303

255304
chunker.add(SRS_BOOKMARKS.done,
@@ -273,15 +322,15 @@ export function initVisualisers() {
273322
order: 0,
274323
},
275324
array: {
276-
instance: new ArrayTracer('array', null, 'Array view', { arrayItemMagnitudes: false }),
325+
instance: new ArrayTracer('array', null, 'Array A', { arrayItemMagnitudes: false }),
277326
order: 1,
278327
},
279328
countArray: {
280329
instance: new ArrayTracer('countArray', null, 'Count array', { arrayItemMagnitudes: false }),
281330
order: 1,
282331
},
283332
tempArray: {
284-
instance: new ArrayTracer('tempArray', null, 'Temp array', { arrayItemMagnitudes: false }),
333+
instance: new ArrayTracer('tempArray', null, 'Temp array B', { arrayItemMagnitudes: false }),
285334
order: 1,
286335
},
287336
};
@@ -292,9 +341,9 @@ export function initVisualisers() {
292341
order: 0,
293342
},
294343
array: {
295-
instance: new ArrayTracer('array', null, 'Array view', { arrayItemMagnitudes: true }),
344+
instance: new ArrayTracer('array', null, 'Array A', { arrayItemMagnitudes: true }),
296345
order: 1,
297346
},
298347
};
299348
}
300-
}
349+
}

src/algorithms/pseudocode/msort_arr_nat.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ MergeAll
3232
\\Expl{ We compute mid to get the longest sequence where A[left] <=
3333
A[left+1] <= ... <= A[mid].
3434
\\Expl}
35-
find the second run, A[mid+1..right] it could be empty \\Ref SecondRun
35+
find the second run, A[mid+1..right] (possibly empty) \\Ref SecondRun
3636
\\Expl{ We compute right to get the longest sequence where A[mid+1] <=
3737
A[mid+2] <= ... <= A[right]. If mid = size this will be empty.
3838
\\Expl}

src/algorithms/pseudocode/straightRadixSort.js

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,18 @@ would be good for the counts array.
2020
2121
\\Code{
2222
Main
23-
Radixsort(A, n) // Sort array A[1]..A[n] in ascending order. \\B 1
23+
Radixsort(A, n) // Sort array A[0]..A[n-1] in ascending order. \\B 1
24+
\\Expl{ Note that all arrays start at index zero.
25+
\\Expl}
2426
2527
Find maximum number of "digits" used in the data \\B 2
2628
\\Expl{ This depends on the radix (base) we use to view the data.
29+
Here we use radix 4 for illustration (the digits are 0-3 and use
30+
two bits; we show the binary representation of the keys and the
31+
mask used to extract the current digit).
2732
We could use radix 10 (decimal digits), radix 2
28-
(binary) or anything else. Here we use radix 4 for illustration
29-
(the digits are 0-3 and use two bits). Radix 256 (one byte) is a
30-
better choice in practice and we can set the maximum to be the
33+
(binary) or anything else. Radix 256 (one byte) is a
34+
good choice in practice and we can set the maximum to be the
3135
word size rather than scanning all the input data as we do here.
3236
\\Expl}
3337
@@ -48,36 +52,36 @@ Radixsort(A, n) // Sort array A[1]..A[n] in ascending order. \\B 1
4852
4953
\\Code{
5054
Countingsort
51-
// Countingsort(A, k, n) \\B 4
52-
// Count number of 1s and 0s in B
53-
Array C <- counts of each kth digit value \\Ref CountNums
54-
\\Expl{ We count the number of occurrences of each digit value (0-3
55-
here) in the kth digits of the data.
55+
Array Count <- counts of each kth digit value \\Ref CountNums
56+
\\Expl{ We count the number of occurrences of each digit value (here 0-3
57+
or binary 00-11) in the kth digits of the data.
5658
\\Expl}
5759
Cumulatively sum digit value counts \\Ref CumSum
5860
\\Expl{ For each digit value, we compute the count for that digit value
5961
plus all smaller digit values. This allows us to determine where the
60-
last occurrence of each digit value will appear in the sorted array.
62+
last occurrence of each digit value will appear in the sorted array
63+
(the counts are one greater than the index because we start at index 0).
6164
\\Expl}
62-
Populate temporary array B with sorted numbers \\Ref Populate
65+
Array B <- sorted numbers \\Ref Populate
6366
\\Expl{ We copy the data to temporary array B, using the digit
64-
value counts to determine where each element is copied to.
67+
value counts to determine where each element is copied to, so the result
68+
is sorted on this digit.
6569
\\Expl}
6670
Copy B back to A \\B 10
67-
\\Expl{ Array A is now sorted on digit k and all smaller digits
68-
(because the smaller digits were sorted previously and counting
71+
\\Expl{ Array A is now sorted on digit k and all less significant digits
72+
(because the less significant digits were sorted previously and counting
6973
sort is stable).
7074
\\Expl}
7175
\\Code}
7276
7377
\\Code{
7478
CountNums
75-
// Put counts of each kth digit value in array C \\B 5
76-
initialise array C to all zeros \\B 16
79+
initialise array Count to all zeros \\B 16
7780
for num in A \\B 13
7881
\\In{
7982
digit <- kth digit value in num \\B 17
80-
\\Expl{ To extract the kth digit we can use div and mod operations.
83+
\\Expl{ The digit is the two highlighted bits in the binary representation.
84+
To extract the kth digit we can use div and mod operations.
8185
If the radix is a power of two we can use bit-wise operations
8286
(right shift and bit-wise and) instead.
8387
\\Expl}
@@ -86,35 +90,32 @@ for num in A \\B 13
8690
highlighted, and the digit value 0-3 (maybe the latter can be done
8791
by just highlighting B[digit] instead).
8892
\\Note}
89-
C[digit] <- C[digit]+1 \\B 12
93+
Count[digit] <- Count[digit]+1 \\B 12
9094
\\In}
9195
\\Code}
9296
9397
\\Code{
9498
CumSum
95-
// Cumulatively sum counts \\B 6
96-
\\Note{ Best remove this comment line and move bookmark
97-
\\Note}
9899
for i = 1 to maximum digit value \\B 14
99100
\\Expl{ We must scan left to right. The count for digit 0 remains
100101
unchanged.
101102
\\Expl}
102103
\\In{
103-
B[i] = B[i-1] + B[i] \\B 15
104+
Count[i] = Count[i-1] + Count[i] \\B 15
104105
\\In}
105106
\\Code}
106107
107108
\\Code{
108109
Populate
109-
// Populate new array C with sorted numbers \\B 7
110110
for each num in A in reverse order \\B 8
111111
\\Expl{ We go from right to left so that we preserve the order of numbers
112112
with the same digit.
113113
This is CRUCIAL in radix sort as the counting sort MUST be stable.
114114
\\Expl}
115115
\\In{
116116
digit <- kth digit value in num \\B 19
117-
\\Expl{ To extract the kth digit value we can use div and mod operations.
117+
\\Expl{ The digit is the two highlighted bits in the binary representation.
118+
To extract the kth digit we can use div and mod operations.
118119
If the radix is a power of two we can use bit-wise operations
119120
(right shift and bit-wise and) instead.
120121
\\Expl}
@@ -123,8 +124,8 @@ for each num in A in reverse order \\B 8
123124
highlighted, and the digit value 0-3 (maybe the latter can be done
124125
by just highlighting B[digit] instead).
125126
\\Note}
126-
B[digit] = B[digit]-1 \\B 18
127-
C[B[digit]] = num \\B 9
127+
Count[digit] = Count[digit]-1 \\B 18
128+
B[Count[digit]] = num \\B 9
128129
\\In}
129130
\\Code}
130131

0 commit comments

Comments
 (0)