// This program is to my knowledge, the best low level scoreboad insertion scheme possible. // ARRAY_SIZE must be equal to 2^n + 2 for this algorithm to work as optimally as it does. // memmove() has replaced for() loops to shift array elements, because there is a claim that it is faster. #include #include #include #include #define ARRAY_SIZE 10 // This constant search depth is 1 less than LOG-base-2(ARRAY_SIZE - 2) because the final condition statement is conducted outside of the loop. #define MAX_LOOP_SEARCH_DEPTH 2 // Returns the number of comparisons made to arrive at the insertion position. Returns "1" if the "NewValue" is too small to make the list. // When put into use, this function should only return a boolean flag to indicate if the "NewValue" made the cut. unsigned int BinaryInsertionSortOne(unsigned int *ThisArray, unsigned int NewValue){ unsigned int X; unsigned int Result = 1; unsigned int Left = 0; unsigned int Right = ARRAY_SIZE - 1; unsigned int NextElement; // "NewValue" does not make the cut; it is too small. if ( NewValue <= ThisArray[Right] ) return Result; // "NewValue" belongs at the end of the list. Right -= 1; Result += 1; if ( NewValue <= ThisArray[Right] ) { ThisArray[ARRAY_SIZE - 1] = NewValue; return Result; } // "NewValue" belongs at the first position in the list. Result += 1; if ( NewValue >= ThisArray[Left] ) { memmove(ThisArray + 1, ThisArray, sizeof(unsigned int)*(ARRAY_SIZE - 1)); ThisArray[Left] = NewValue; return Result; } // Set the initial midpoint. NextElement = Left + ((Right - Left)>>1); // This loop will be unwound by compiler optimization. for ( X = 0; X < MAX_LOOP_SEARCH_DEPTH; X++ ) { Result += 1; // "NextElement" is the new "Left". if ( ThisArray[NextElement] > NewValue ) { Left = NextElement; } // "NextElement" will become the new "Right". else if ( ThisArray[NextElement] < NewValue ) { Result += 1; Right = NextElement; } // "NextElement" holds a value equal to "NewValue", and is the insertion point. else { Result += 1; // memmove() is going to employ pointer arithmatic for pointers to internal array members. memmove(ThisArray + NextElement + 1, ThisArray + NextElement, sizeof(unsigned int)*(ARRAY_SIZE - 1 - NextElement)); ThisArray[NextElement] = NewValue; printf("Out Early\n"); return Result; } // Advance the "NextElement"; NextElement = Left + ((Right - Left)>>1); } Result += 1; // "NextElement" is now flanked by "Left" and "Right", and this is known with absolute certainty. // Since two cases will result in the insertion position being equal to "Right", we only need to make one comparison on the final iteration. if ( ThisArray[NextElement] < NewValue ) { memmove(ThisArray + NextElement + 1, ThisArray + NextElement, sizeof(unsigned int)*(ARRAY_SIZE - 1 - NextElement)); ThisArray[NextElement] = NewValue; printf("Out First\n"); return Result; } // The "NewValue" is smaller or equal to "ThisArray[NextElement]", so the insertion position will be "Right". else { memmove(ThisArray + Right + 1, ThisArray + Right, sizeof(unsigned int)*(ARRAY_SIZE - 1 - Right)); ThisArray[Right] = NewValue; printf("Out Second\n"); return Result; } } int main(){ unsigned int X; unsigned int NumberOfComparisons; long int Input; unsigned int TheArray[ARRAY_SIZE]; // Set the initial values on the scoreboard far enough apart, so we can test the insertion performance at every position in the array. for ( X = 0; X < ARRAY_SIZE; X++ ) TheArray[X] = 10*(ARRAY_SIZE - X); printf("We are going to be inserting values into this array if they are big enough:\n\n"); for ( X = 0; X < ARRAY_SIZE; X++ ) printf("|%u", TheArray[X]); printf("|\n\n"); while ( 1 ) { printf("Enter an unsigned, 32 bit integer that you want on the scoreboard(ctrl c - To Exit): "); if ( scanf("%ld", &Input) == 0 ) return 0; if ( Input < 0 ) return 0; if ( Input > UINT_MAX ) return 0; NumberOfComparisons = BinaryInsertionSortOne(TheArray, (unsigned int)Input); printf("\nThe Insertion of |%u| required |%d| comparisons.\n\n", (unsigned int)Input, NumberOfComparisons); for ( X = 0; X < ARRAY_SIZE; X++ ) printf("|%u", TheArray[X]); printf("|\n\n"); } return 0; }