Design an efficient algorithm to sort 5 distinct - very large - keys less than 8 comparisons in the worst case. You can\'t use radix sort.
Here is C++ implementation which sorts 5 elements in <= 7 comparisons. Was able to find 8 cases which can be sorted in 6 comparisons. That makes sense if we imagine full binary tree with 120 leaf nodes, there will be 112 nodes at level 7 and 8 leaf nodes at level 6. Here is the full code that is tested to work for all possible permutations.
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
ostream& operator << ( ostream& os, vector v )
{
cout << "[ ";
for ( auto x: v ) cout << x << ' ';
cout << "]";
return os;
}
class Comp {
int count;
public:
Comp(): count{0}{}
bool isLess( vector v, int i, int j ) {
count++;
//cout << v << "Comparison#" << count << ": " << i << ", " << j << endl;
return v[ i ] < v[ j ];
}
int getCount() { return count; }
};
int mySort( vector &v )
{
Comp c;
if ( c.isLess( v, 1, 0 ) ) {
swap( v[ 0 ], v[ 1 ] );
}
if ( c.isLess( v, 3, 2 ) ) {
swap( v[ 2 ], v[ 3 ] );
}
// By now (0, 1) (2, 3) (4)
if ( c.isLess( v, 0, 2 ) ) {
// ( 0, 2, 3 ) (1)
swap( v[ 1 ], v[ 2 ] );
swap( v[ 2 ], v[ 3 ] );
} else {
// ( 2, 0, 1 ) ( 3 )
swap( v[ 1 ], v[ 2 ] );
swap( v[ 0 ], v[ 1 ] );
}
// By now sorted order ( 0, 1, 2 ) ( 3 ) ( 4 ) and know that 3 > 0
if ( c.isLess( v, 4, 1 ) ) {
if ( c.isLess( v, 4, 0 ) ) {
// ( 4, 0, 1, 2 ) ( 3 ) ( ... )
v.insert( v.begin(), v[4] );
// By now ( 0, 1, 2, 3 ) ( 4 ) ( ... ) and know that 4 > 1
if ( c.isLess( v, 4, 2 ) ) {
// ( 0, 1, 4, 2, 3 ) ( ... )
v.insert( v.begin() + 2, v[4] );
} else {
if ( c.isLess( v, 4, 3 ) ) {
// ( 0, 1, 2, 4, 3 ) ( ... )
v.insert( v.begin() + 3, v[4] );
} else {
// ( 0, 1, 2, 3, 4 ) ( ... )
v.insert( v.begin() + 4, v[4] );
}
}
// ( 1 2 3 4 5 ) and trim the rest
v.erase( v.begin()+5, v.end() );
return c.getCount(); /////////// <--- Special case we could been done in 6 comparisons
} else {
// ( 0, 4, 1, 2 ) ( 3 ) ( ... )
v.insert( v.begin() + 1, v[4] );
}
} else {
if ( c.isLess( v, 4, 2 ) ) {
// ( 0, 1, 4, 2 ) ( 3 ) ( ... )
v.insert( v.begin() + 2, v[4] );
} else {
// ( 0, 1, 2, 4 ) ( 3 ) ( ... )
v.insert( v.begin() + 3, v[4] );
}
}
// By now ( 0, 1, 2, 3 ) ( 4 )( ... ): with 4 > 0
if ( c.isLess( v, 4, 2 ) ) {
if ( c.isLess( v, 4, 1 ) ) {
// ( 0, 4, 1, 2, 3 )( ... )
v.insert( v.begin() + 1, v[4] );
} else {
// ( 0, 1, 4, 2, 3 )( ... )
v.insert( v.begin() + 2, v[4] );
}
} else {
if ( c.isLess( v, 4, 3 ) ) {
// ( 0, 1, 2, 4, 3 )( ... )
v.insert( v.begin() + 3, v[4] );
} else {
// ( 0, 1, 2, 3, 4 )( ... )
v.insert( v.begin() + 4, v[4] );
}
}
v.erase( v.begin()+5, v.end() );
return c.getCount();
}
#define TEST_ALL
//#define TEST_ONE
int main()
{
#ifdef TEST_ALL
vector v1(5);
iota( v1.begin(), v1.end(), 1 );
do {
vector v2 = v1, v3 = v1;
int count = mySort( v2 );
if ( count == 6 )
cout << v3 << " => " << v2 << " #" << count << endl;
} while( next_permutation( v1.begin(), v1.end() ) );
#endif
#ifdef TEST_ONE
vector v{ 1, 2, 3, 1, 2};
mySort( v );
cout << v << endl;
#endif
}