You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have recently discovered that you do not actually need a keybuffer for grailsort, but can instead find out in other ways from which subarray a block is from.
Note, that in the end, the only thing we need to have, is a sorted list (by tail of each block), and we have to know which subarray a block is from (either the left or the right).
For this purpose, we split the blocks up into two categories: homogenous and inhomogenous.
we can now "encode" into the blocks from which subarray they are.
Inhomogenous blocks:
since by definition these blocks can't be made up of all equal items, we know that the first and last items are distinct. We can
now encode their original subarrays into these items, by simply swapping them if the blocks are from the right, and keeping
them
the same if they are from the left:
example: [1 2 3 4 5 6 7 8] -> left subarray
[8 2 3 4 5 6 7 1] -> right subarray
this can be easily reversed after blockselection (during the merge process, so that we keep this information up until the point where we actually need it)
at this point it might become clear we we need to differentiate between inhomogenous and homogenous blocks, since homogenous blocks, by definition are made up of all equal items.
Homogenous blocks:
with a single comparison, we can find out if a block is homogenous, if it is, we can insert a so called "tag" item that we take from the scrolling buffer, into the second position.
These tags are given to the blocks sequentially, meaning that we first do a selectionsort on the scrolling buffer (we select one item each time we need a new tag), and then swap the selected item with the second item from the block. O(sqrt(n))
After block selection, we can easily regather these tags in O(sqrt(n)), not affecting the overall performance noticibly at all.
This also requires reworking the block selection, since Holy Grail does implement a way to remove buffer rewinds by sorting the blocks by tail, which does not work with this method.
So for this matter, if we find a homogenous block, we sort all blocks with the same head by head, and after that continue to sort by tail.
additionally, we implement an optimization that if we find a homogenous block during merging, we look ahead, to try and find the first not-homogenous block, rotate the scrolling buffer over to it, and then see if the next block also has the same head.
If it does, we keep searching finding the first block that is homogenous anymore, in that block, we find the position, where the equal item ends, and then rotate the scrolling buffer, additionally with the end of the first inhomogenous block it found over to the next inhomogenous block it found, saving O(n) comparisons, and O(n) writes in the best case, additionally the worst case is just as bad as the current worst case (if not better).
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
I have recently discovered that you do not actually need a keybuffer for grailsort, but can instead find out in other ways from which subarray a block is from.
Note, that in the end, the only thing we need to have, is a sorted list (by tail of each block), and we have to know which subarray a block is from (either the left or the right).
For this purpose, we split the blocks up into two categories: homogenous and inhomogenous.
we can now "encode" into the blocks from which subarray they are.
Inhomogenous blocks:
since by definition these blocks can't be made up of all equal items, we know that the first and last items are distinct. We can
now encode their original subarrays into these items, by simply swapping them if the blocks are from the right, and keeping
them
the same if they are from the left:
example: [1 2 3 4 5 6 7 8] -> left subarray
[8 2 3 4 5 6 7 1] -> right subarray
this can be easily reversed after blockselection (during the merge process, so that we keep this information up until the point where we actually need it)
at this point it might become clear we we need to differentiate between inhomogenous and homogenous blocks, since homogenous blocks, by definition are made up of all equal items.
Homogenous blocks:
with a single comparison, we can find out if a block is homogenous, if it is, we can insert a so called "tag" item that we take from the scrolling buffer, into the second position.
These tags are given to the blocks sequentially, meaning that we first do a selectionsort on the scrolling buffer (we select one item each time we need a new tag), and then swap the selected item with the second item from the block. O(sqrt(n))
After block selection, we can easily regather these tags in O(sqrt(n)), not affecting the overall performance noticibly at all.
This also requires reworking the block selection, since Holy Grail does implement a way to remove buffer rewinds by sorting the blocks by tail, which does not work with this method.
So for this matter, if we find a homogenous block, we sort all blocks with the same head by head, and after that continue to sort by tail.
additionally, we implement an optimization that if we find a homogenous block during merging, we look ahead, to try and find the first not-homogenous block, rotate the scrolling buffer over to it, and then see if the next block also has the same head.
If it does, we keep searching finding the first block that is homogenous anymore, in that block, we find the position, where the equal item ends, and then rotate the scrolling buffer, additionally with the end of the first inhomogenous block it found over to the next inhomogenous block it found, saving O(n) comparisons, and O(n) writes in the best case, additionally the worst case is just as bad as the current worst case (if not better).
Beta Was this translation helpful? Give feedback.
All reactions