Skip to the content of the web site.

Partitioning algorithms

Suppose you have two arrays and you want to swap two sub-ranges with the same number of entries. There is one requirement which may or may not be necessary:

  • The array entries must end up in the same order after the swap.

Same order required

If this is a requirement, then all one can do is perform an entry-by-entry swap, requiring then $3n$ assignments:

// Swap the 'n' entries of Array 0 going from
//      i0, ..., i0 + n - 1
// with the entries of Array 1 going from
//      i1, ..., i1 + n - 1
void ordered_array_range_swap(
  double      array0[],
  std::size_t i0,
  double      array1[],
  std::size_t i1,
  std::size_t n
) {
    for ( std::size_t k{ 0 }; k < n; ++k ) {
        // Swap the two entries
        double tmp{ array0[i0] };
        array0[i0] = array1[i1];
        array1[i1] = tmp;

        ++i0;
        ++i1;
    }
}

You will note that we continue to use the parameters i0 and i1 throughout the algorithm:

  • The loop executes exactly $n$ times, once for each entry to be swapped.
  • With the first loop, both i0 and i1 store the address of the first entries to be swapped.
  • Both indices are then incremented, so with the next iteration of the loop, the next pair of entries are swapped.

You can see these two implementations at replit.com.

Order can be altered

If the order can be altered, then we can reduce the number of assignments from $3n$ to $2n + 1$:

// Move the 'n' entries of Array 0 going from
//      i0, ..., i0 + n - 1
// to the entries of Array 1 going from
//      i1, ..., i1 + n - 1
// and vice versa, but the order need not
// remain the same.
void unordered_array_range_swap(
  double      array0[],
  std::size_t i0,
  double      array1[],
  std::size_t i1,
  std::size_t n
) {
    if ( n == 0 ) {
        return;
    }

    double tmp{ array0[i0] };

    // This runs 'n - 1' times
    for ( std::size_t k{ 1 }; k < n; ++k ) {
        array0[i0] = array1[i1];
	++i0;
        array1[i1] = array0[i0];
	++i1;
    }

    array0[i0] = array1[i1];
    array1[i1] = tmp;
}

You will note that we temporarily store the first entry of the first array, and this creates a 'hole', which we fill from an entry in the second array, which creates a 'hole' there that we then fill again from the first, and so on. At the end, we fill the last two entries as appropriate. Note that declaring tmp requires one assignment, even if the assignment operator is not used.