/* This lets us join together two macro names to make *oneidentifier.Thetwolevels(JOIN,JOIN2)istoforce *thecompilertoevaluatemacros,so: *PREFIXNAME(Insert),whereSORT_FUNC_NAMEis *Sort,comesoutasSortInsert,ratherthan *SORT_FUNC_NAMEInsert
*/
// Compare a and b, first checking if a and b are equal objects, // and if so returning false straight away. We do this because // some comparators do not work when comparing equal objects. // This can occur either because the original list had identical // objects, or when comparing against the pivot in quicksort. #define SORT_COMP_CHECK_EQ PREFIXNAME(SortCompCheckEqObj) staticInt SORT_COMP_CHECK_EQ(SORT_FUNC_ARGS, Obj a, Obj b) { if(a==b) return0; else return SORT_COMP(a, b);
}
staticvoid PREFIXNAME(Shell)(SORT_FUNC_ARGS, Int start, Int end)
{
UInt len; // length of the list
UInt h; // gap width in the shellsort
SORT_CREATE_LOCAL(v);
SORT_CREATE_LOCAL(w);
UInt i, k; // loop variables
// sort the list with a shellsort
len = end - start + 1;
h = 1; while (9 * h + 4 < len) {
h = 3 * h + 1;
} while (0 < h) { for (i = h + start; i <= end; i++) {
SORT_ASS_LIST_TO_LOCAL(v, i);
k = i;
SORT_ASS_LIST_TO_LOCAL(w, k - h); while (h + (start - 1) < k && SORT_COMP_CHECK_EQ(SORT_ARGS, v, w)) {
SORT_ASS_LOCAL_TO_LIST(k, w);
k -= h; if (h + (start - 1) < k) {
SORT_ASS_LIST_TO_LOCAL(w, k - h);
}
}
SORT_ASS_LOCAL_TO_LIST(k, v);
}
h = h / 3;
}
SORT_FILTER_CHECKS();
}
// Swap values at indices a and b #define SWAP_INDICES PREFIXNAME(Swap) staticinlinevoid PREFIXNAME(Swap)(SORT_FUNC_ARGS, Int a, Int b) {
SORT_CREATE_LOCAL(t);
SORT_CREATE_LOCAL(u);
SORT_ASS_LIST_TO_LOCAL(t, a);
SORT_ASS_LIST_TO_LOCAL(u, b);
SORT_ASS_LOCAL_TO_LIST(b, t);
SORT_ASS_LOCAL_TO_LIST(a, u);
}
// Compare values at indices a and b #define COMP_INDICES PREFIXNAME(CompIndices) staticinlineint COMP_INDICES(SORT_FUNC_ARGS, Int a, Int b) {
SORT_CREATE_LOCAL(t);
SORT_CREATE_LOCAL(u);
SORT_ASS_LIST_TO_LOCAL(t, a);
SORT_ASS_LIST_TO_LOCAL(u, b); return SORT_COMP_CHECK_EQ(SORT_ARGS, t, u);
}
// Sort 3 indices staticinlinevoid PREFIXNAME(Sort3)(SORT_FUNC_ARGS, Int a, Int b, Int c) { if (!(COMP_INDICES(SORT_ARGS, b, a))) { if (!(COMP_INDICES(SORT_ARGS, c, b))) return;
SWAP_INDICES(SORT_ARGS, b, c); if (COMP_INDICES(SORT_ARGS, b, a)) {
SWAP_INDICES(SORT_ARGS, a, b);
} return;
}
if (COMP_INDICES(SORT_ARGS, c, b)) {
SWAP_INDICES(SORT_ARGS, a, c); return;
}
SWAP_INDICES(SORT_ARGS, a, b); if (COMP_INDICES(SORT_ARGS, c, b)) {
SWAP_INDICES(SORT_ARGS, b, c);
}
}
/* Partition a list, from indices start to end. Return if any values had *tobemoved,andstorethepartition_pointintheargument *partition_point
*/ staticinlineInt PREFIXNAME(Partition)(SORT_FUNC_ARGS, Int start, Int end, Int *partition_point) { Int left = start; Int right = end; Int first_pass = 1;
SORT_CREATE_LOCAL(pivot);
PREFIXNAME(Sort3)(SORT_ARGS, start, start / 2 + end / 2, end);
SORT_ASS_LIST_TO_LOCAL(pivot, start / 2 + end / 2);
left++;
while (1) { while (left < right) {
SORT_CREATE_LOCAL(listcpy);
SORT_ASS_LIST_TO_LOCAL(listcpy, left); if (SORT_COMP_CHECK_EQ(SORT_ARGS, pivot, listcpy)) break;
left++;
}
right--; while (left < right) {
SORT_CREATE_LOCAL(listcpy);
SORT_ASS_LIST_TO_LOCAL(listcpy, right); if (!(SORT_COMP_CHECK_EQ(SORT_ARGS, pivot, listcpy))) break;
right--;
}
staticvoid PREFIXNAME(Insertion)(SORT_FUNC_ARGS, Int start, Int end)
{
SORT_CREATE_LOCAL(v);
SORT_CREATE_LOCAL(w);
UInt i, k; // loop variables
// sort the list with insertion sort for (i = start + 1; i <= end; i++) {
SORT_ASS_LIST_TO_LOCAL(v, i);
k = i;
SORT_ASS_LIST_TO_LOCAL(w, k - 1); while (start < k && SORT_COMP_CHECK_EQ(SORT_ARGS, v, w)) {
SORT_ASS_LOCAL_TO_LIST(k, w);
k -= 1; if (start < k) {
SORT_ASS_LIST_TO_LOCAL(w, k - 1);
}
}
SORT_ASS_LOCAL_TO_LIST(k, v);
}
}
/* This function performs an insertion sort with a limit to the number
* of swaps performed -- if we pass that limit we abandon the sort */ static Obj PREFIXNAME(LimitedInsertion)(SORT_FUNC_ARGS, Int start, Int end)
{
SORT_CREATE_LOCAL(v);
SORT_CREATE_LOCAL(w);
UInt i, k; // loop variables Int limit = 8; // how long do we try to insertion sort? // sort the list with insertion sort for (i = start + 1; i <= end; i++) {
SORT_ASS_LIST_TO_LOCAL(v, i);
k = i;
SORT_ASS_LIST_TO_LOCAL(w, k - 1); while (start < k && SORT_COMP_CHECK_EQ(SORT_ARGS, v, w)) {
limit--; if (limit == 0) {
SORT_ASS_LOCAL_TO_LIST(k, v); returnFalse;
}
SORT_ASS_LOCAL_TO_LIST(k, w);
k -= 1; if (start < k) {
SORT_ASS_LIST_TO_LOCAL(w, k - 1);
}
}
SORT_ASS_LOCAL_TO_LIST(k, v);
} returnTrue;
}
/* This function assumes it doesn't get called for ranges which are very small
*/ staticvoid PREFIXNAME(CheckBadPivot)(SORT_FUNC_ARGS, Int start, Int end, Int pivot)
{ Int length = end - start; if (pivot - start < length / 8) {
SWAP_INDICES(SORT_ARGS, pivot, pivot + length / 4);
SWAP_INDICES(SORT_ARGS, end, end - length / 4);
} if (pivot - start > 7 * (length / 8)) {
SWAP_INDICES(SORT_ARGS, start, start + length / 4);
SWAP_INDICES(SORT_ARGS, pivot - 1, pivot - 1 - length / 4);
}
}
staticvoid PREFIXNAME(QuickSort)(SORT_FUNC_ARGS, Int start, Int end, Int depth)
{ Int pivot, first_pass;
void SORT_FUNC_NAME(SORT_FUNC_ARGS) { Int len = SORT_LEN_LIST();
SORT_FILTER_CHECKS();
PREFIXNAME(QuickSort)(SORT_ARGS, 1, len, CLog2Int(len) * 2 + 2);
}
// Merge the consecutive ranges [b1..e1] and [e1+1..e2] in place, // Using the temporary buffer 'tempbuf'. staticvoid PREFIXNAME(MergeRanges)(SORT_FUNC_ARGS, Int b1, Int e1, Int e2,
Obj tempbuf)
{ Int pos1 = b1; Int pos2 = e1 + 1; Int resultpos = 1; Int i;
for (i = 1; i < resultpos; ++i) {
SORT_CREATE_LOCAL(t);
SORT_ASS_BUF_TO_LOCAL(tempbuf, t, i);
SORT_ASS_LOCAL_TO_LIST(b1 + i - 1, t);
}
}
void PREFIXNAME(Merge)(SORT_FUNC_ARGS) { Int len = SORT_LEN_LIST();
Obj buf = SORT_CREATE_TEMP_BUFFER(len);
SORT_FILTER_CHECKS(); Int stepsize = 24; Int i; // begin with splitting into small steps we insertion sort for (i = 1; i + stepsize <= len; i += stepsize) {
PREFIXNAME(Insertion)(SORT_ARGS, i, i + stepsize - 1);
} if (i < len) {
PREFIXNAME(Insertion)(SORT_ARGS, i, len);
}
while (stepsize < len) { for (i = 1; i + stepsize * 2 <= len; i += stepsize * 2) {
PREFIXNAME(MergeRanges)(SORT_ARGS, i, i+stepsize-1, i+stepsize*2-1, buf);
} if (i + stepsize <= len) {
PREFIXNAME(MergeRanges)(SORT_ARGS, i, i + stepsize - 1, len, buf);
}
stepsize *= 2;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.