-2

Lately I used the great sorting algorythm made by Rebuilder from Habr.com. It served me well, but it sorts only positive integers, and recently I run into the need to sort negatives as well. For now I use QuickSort, but since the array is very large (10k+ elements), I wonder if one could modify RadixSort for this task.

There is the procedure as for now. Comment translation is mine, sorry if I get something wrong.

procedure RSort(var m: array of Longword);
//--------------------------------------------------
   procedure Sort_step(var source, dest, offset: array of Longword; const num: Byte);
   var i,temp : Longword;
       k : Byte;
   begin
     for i := High(source) downto 0 do
     begin
       temp := source[i];
       k := temp SHR num;
       dec(offset[k]);
       dest[offset[k]] := temp;
     end;
   end;
//--------------------------------------------------
// Объявляем массив корзин первым, для выравнивания на стеке
// Creating the bin array first for aligning at the stack
var s : array[0..3] of array[0..255] of Longword;
    i,k : longword;
    // Смещение байт внутри переменной k
    // Byte offset inside of variable k
    offset : array[0..3] of byte absolute k;
    m_temp : array of Longword;
begin
  SetLength(m_temp, Length(m));
  // Быстрая очистка корзин
  // Quick bin clear
  FillChar(s[0], 256 * 4 * SizeOf(Longword), 0);

  // Заполнение корзин
  // Filling bins
  for i := 0 to High(m) do
  begin
    k := m[i];
    Inc(s[0,offset[0]]);
    Inc(s[1,offset[1]]);
    Inc(s[2,offset[2]]);
    Inc(s[3,offset[3]]);
  end;

  // Пересчёт смещений для корзин
  // Recalculating bin offsets
  for i := 1 to 255 do
  begin
    Inc(s[0,i], s[0,i-1]);
    Inc(s[1,i], s[1,i-1]);
    Inc(s[2,i], s[2,i-1]);
    Inc(s[3,i], s[3,i-1]);
  end;

  // Вызов сортировки по байтам от младших к старшим
  // Sorting by byte, from least to most
  Sort_step(m, m_temp, s[0], 0);
  Sort_step(m_temp, m, s[1], 8);
  Sort_step(m, m_temp, s[2], 16);
  Sort_step(m_temp, m, s[3], 24);

  SetLength(m_temp, 0);
end;

Link: https://habr.com/ru/post/484224/

I found some helpful advice on the Internet, including StackOverflow, but I met two problems:

  1. There are too many different solutions and I can't choose the optimal one for Delphi.

  2. I lack the knowledge and skill to implement them correctly. I've tried some and get wrong results.

So, could someone modify the given function and explain to me what they did and why?

Alexander
  • 388
  • 1
  • 12
  • Forgot to mention: I use Delphi 10.3. – Alexander Aug 16 '20 at 09:09
  • SO isn't a coding service – David Heffernan Aug 16 '20 at 09:37
  • @DavidHeffernan Well yes, I aknowledge this, but I feel stuck. If it helps, I could show how I tried to get it done in the main post, maybe someone would fix my attempts. Though I think they are garbage. – Alexander Aug 16 '20 at 09:50
  • 1
    10k seems like a very small array. Are you sure you need radix sort? – David Heffernan Aug 16 '20 at 09:54
  • @DavidHeffernan This is the minimum size of array. It could go up. But no, I'm not sure. – Alexander Aug 16 '20 at 09:57
  • I did a test on an array with excluded negative values in my actual code. Radix gave me about 40% performance increase, and some more because it's stable. It could be because of my implementation of QuickSort tho, I'll work at it. Maybe I could use some of that performance to walk through array once, splitting into two, with only positive and negative values, sort them independandly and then merge? – Alexander Aug 16 '20 at 10:11
  • Is that 40% on total runtime of program, or just the sort? Also, stability is a meaningless property on an array of integers. It only has meaning if the data has redundancy beyond the key. In other words, if you had, say, element that was an integer and a string with the integer as the key. – David Heffernan Aug 16 '20 at 10:59
  • @DavidHeffernan Just the sort. I've tried my solution, but now it's - again - slower than a quicksort. Well. – Alexander Aug 16 '20 at 11:03
  • What difference does it make to the entire program? If the sort is not the performance bottleneck then the algo choice won't matter. Note that the spring4d project has good sorting algorithms. – David Heffernan Aug 16 '20 at 11:14

1 Answers1

1

A simple approach is to complement the sign bit somewhere during the process. Note this only affects the most significant "digit" (usually a byte for fast radix sort). The code to handle the most significant "digit" could be handled in a separate loop than the code that handles the other "digits".

The simplest approach would be to make an initial pass to complement the sign bit of every element in the array, do the radix sort, then a final pass complement the sign bit of every element again.

rcgldr
  • 27,407
  • 3
  • 36
  • 61