Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If-else-if versus map

Suppose I have such an if/else-if chain:

if( x.GetId() == 1 )
{
}
else if( x.GetId() == 2 )
{
}
// ... 50 more else if statements

What I wonder is, if I keep a map, will it be any better in terms of performance? (assuming keys are integers)

like image 373
perezvon Avatar asked Mar 17 '10 06:03

perezvon


People also ask

Is map or set faster?

The map solution results in "Time Limit Exceeded on Test 3", whereas the set solution results in "Time Limit Exceeded on Test 2", which means that Test 2 is such that the map solution works faster on it than the set solution.

Which is better if or else if?

In general, "else if" style can be faster because in the series of ifs, every condition is checked one after the other; in an "else if" chain, once one condition is matched, the rest are bypassed.

Why use else if instead of multiple if?

Furthermore ELSE IF is more efficient because the computer only has to check conditions until it finds a condition that returns the value TRUE. By using multiple IF-conditions the computer has to go through each and every condition and thus multiple IF-conditions require more time.

What is the point of ELSE IF?

The main reason to use else if is to avoid excessive indentation.


1 Answers

Maps (usually) are implemented using red-black trees which gives O(log N) lookups as the tree is constantly kept in balance. Your linear list of if statements will be O(N) worst case. So, yes a map would be significantly faster for lookup.

Many people are recommending using a switch statement, which may not be faster for you, depending on your actual if statements. A compiler can sometimes optimize switch by using a jump table which would be O(1), but this is only possible for values that an undefined criteria; hence this behavior can be somewhat nondeterministic. Though there is a great article with a few tips on optimizing switch statements here Optimizing C and C++ Code.

You technically could even formulate a balanced tree manually, this works best for static data and I happened to just recently create a function to quickly find which bit was set in a byte (This was used in an embedded application on an I/O pin interrupt and had to be quick when 99% of the time only 1 bit would be set in the byte):

unsigned char single_bit_index(unsigned char bit) {
    // Hard-coded balanced tree lookup
    if(bit > 0x08)
        if(bit > 0x20)
            if(bit == 0x40)
                return 6;
            else
                return 7;
        else
            if(bit == 0x10)
                return 4;
            else
                return 5;
    else
        if(bit > 0x02)
            if(bit == 0x04)
                return 2;
            else
                return 3;
        else
            if(bit == 0x01)
                return 0;
            else
                return 1;
}

This gives a constant lookup in 3 steps for any of the 8 values which gives me very deterministic performance, a linear search -- given random data -- would average 4 step lookups, with a best-case of 1 and worst-case of 8 steps.

This is a good example of a range that a compiler would probably not optimize to a jump table since the 8 values I am searching for are so far apart: 1, 2, 4, 8, 16, 32, 64, and 128. It would have to create a very sparse 128 position table with only 8 elements containing a target, which on a PC with a ton of RAM might not be a big deal, but on a microcontroller it'd be killer.

like image 107
joshperry Avatar answered Sep 25 '22 17:09

joshperry