+++ /dev/null
-/*
- * A Linked-List Memory Sort
- * by Philip J. Erdelsky
- * pje@acm.org
- * pje@efgh.com
- * http://alumnus.caltech.edu/~pje/
- *
- * Version taken from:
- * http://alumnus.caltech.edu/~pje/cdmake.txt
- *
- * An extended version can be found at:
- * http://alumnus.caltech.edu/~pje/llmsort.html
- * http://www.efgh.com/software/llmsort.htm
- *
- * Public domain; no restrictions on use.
- */
-
-#include <stdio.h>
-
-void *sort_linked_list(void *p, unsigned index, int (*compare)(void *, void *))
-{
- unsigned base;
- unsigned long block_size;
-
- struct record
- {
- struct record *next[1];
- /* other members not directly accessed by this function */
- };
-
- struct tape
- {
- struct record *first, *last;
- unsigned long count;
- } tape[4];
-
- /* Distribute the records alternately to tape[0] and tape[1]. */
-
- tape[0].count = tape[1].count = 0L;
- tape[0].first = NULL;
- base = 0;
- while (p != NULL)
- {
- struct record *next = ((struct record *)p)->next[index];
- ((struct record *)p)->next[index] = tape[base].first;
- tape[base].first = ((struct record *)p);
- tape[base].count++;
- p = next;
- base ^= 1;
- }
-
- /* If the list is empty or contains only a single record, then */
- /* tape[1].count == 0L and this part is vacuous. */
-
- for (base = 0, block_size = 1L; tape[base+1].count != 0L;
- base ^= 2, block_size <<= 1)
- {
- int dest;
- struct tape *tape0, *tape1;
- tape0 = tape + base;
- tape1 = tape + base + 1;
- dest = base ^ 2;
- tape[dest].count = tape[dest+1].count = 0;
- for (; tape0->count != 0; dest ^= 1)
- {
- unsigned long n0, n1;
- struct tape *output_tape = tape + dest;
- n0 = n1 = block_size;
- while (1)
- {
- struct record *chosen_record;
- struct tape *chosen_tape;
- if (n0 == 0 || tape0->count == 0)
- {
- if (n1 == 0 || tape1->count == 0)
- break;
- chosen_tape = tape1;
- n1--;
- }
- else if (n1 == 0 || tape1->count == 0)
- {
- chosen_tape = tape0;
- n0--;
- }
- else if ((*compare)(tape0->first, tape1->first) > 0)
- {
- chosen_tape = tape1;
- n1--;
- }
- else
- {
- chosen_tape = tape0;
- n0--;
- }
- chosen_tape->count--;
- chosen_record = chosen_tape->first;
- chosen_tape->first = chosen_record->next[index];
- if (output_tape->count == 0)
- output_tape->first = chosen_record;
- else
- output_tape->last->next[index] = chosen_record;
- output_tape->last = chosen_record;
- output_tape->count++;
- }
- }
- }
-
- if (tape[base].count > 1L)
- tape[base].last->next[index] = NULL;
- return tape[base].first;
-}
-
-/* EOF */