简体   繁体   中英

How can I test sorting algorithms for stability in C?

I have three sorting algorithms: bubble, insertion, selection.
I need to experimentally test them for stability. I understand that I need to somehow compare the same numbers before sorting and after, but I don't know how to do it in C.
I need some advice on how this can be implemented.

As chqrlie has rightly pointed out, the following approach does NOT prove absence of stability mistakes for all inputs. It is however something of a smoke-test, which actually has a chance to detect implementation mistakes. This is at least a small step ahead to trying to test based on sequences of numbers, which do NOT allow detecting ANY stability mistake.

In order to test stability you therefore need to do sorting on elements which have the same sorting key AND can still be told apart outside of the sorting.
One way would be to sort elements with two keys. One is non-unique, ie there are pairs of elements with the same first key. The other, second key is unique, ie no two elements have the same second key.

Then create several pairs of elements with same first key and different second key.
Then sort.
Then verify that the relative position of elements with same first key have not changed, use the non-identical second key to do so.
Then sort again and verify that the elements with same first key have again not changed (relative) location. This is for paranoia, the algorithm (strictly speaking the tested implementation) might be stable from an unsorted list, but unstable on a sorted one.

Then restart with unsorted list/array, similar to before, but with reversed relative location of elements with identical first key.
Then sort and verify unchanged relative location AND reverse relative location compared to first sorting.
Then sort again and verify for paranoia.

As mentioned this will not detect ALL stability mistakes, but at least there are two improvements over a simple "do and verify" test here.

  • test unsorted and sorted (described as paranoia), this will detect all toggle-based stability mistakes, ie any mechanisms to always change the relative order of same-keyed pairs
  • test both "directions" of same keyed pairs, this at leat ensures detection of all stability mistakes which are caused by some kind of "preferred order", by making sure that the non-preferred order is among the test inputs and would get sorted into the preferred order

If one is going to test it probabilistically, one needs to have, at minimum, key and a monotonic value to test if they are the same order before and after. There are several ways that one can do this. I would think that one of the simpler, more effective, ways is to sort them by oddness: the key is { even, odd } and the value is the integer. Having only two values increases the chance that the non-stable sort algorithms put it in the wrong spot per item. Here, the qsort function is tested.

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

static int cmp(const int *const a, const int *const b)
    { return (*a & 1) - (*b & 1); }

static int void_cmp(const void *a, const void *b) { return cmp(a, b); }

int main(void) {
    unsigned a[10], counter = 0;
    size_t i;
    const size_t a_size = sizeof a / sizeof *a;
    const unsigned seed = (unsigned)clock();

    /* http://c-faq.com/lib/randrange.html */
    printf("Seed %u.\n", seed), srand(seed);
    for(i = 0; i < a_size; i++)
        a[i] = (counter += 1 + rand() / (RAND_MAX / (2 - 1 + 1) + 1));
    qsort(a, a_size, sizeof *a, &void_cmp);

    for(i = 0; i < a_size; i++) printf("%s%u", i ? ", " : "", a[i]);
    printf("\n");

    /* Even numbers. */
    for(counter = 0, i = 0; i < a_size && !(a[i] & 1) && counter < a[i];
        counter = a[i], i++);
    if(i == a_size) goto pass;
    if(!(a[i] & 1)) goto fail; /* Not stable by `counter >= a[i]`. */

    /* Odd numbers. */
    for(counter = 0; i < a_size && counter < a[i]; counter = a[i], i++);
    if(i == a_size) goto pass;

fail:
    printf("Not stable.\n");
    return EXIT_FAILURE;

pass:
    printf("Possibly stable.\n");
    return EXIT_SUCCESS;
}

Note that this doesn't prove that an algorithm is stable, but after sorting a large number of elements, the chance that it gets it right by chance is exponentially small.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM