使用2种不同的appraoches时,大O(N)差异

时间:2017-02-25 20:39:49

标签: c++ c loops big-o

我的问题如下:

我有一个函数来操作MAX元素数组的内容。此功能将如下所示:

    //GLobal Variables
    uint8_t my_array[ MAX ];
    #define EMPTY 0xFF

    ...
    void initArray( void )
    {
        for( uint8_t i=0; i<MAX; i++ )
        {
             my_array[ i ] = EMPTY;   
        }
    }
    void manipulateArray( uint8_t value )
    {
        for( uint8_t i=0; i<MAX; i++ )
        {
             if( EMPTY == my_array[ i ] )
             {
                  my_array[ i ] = value;
                  break;
              }
        }
    }

    ...

    int main( void )
    {
         ...
         initArray();
         ...
         while( false == exit_flag )
         {
               manipulateArray( value );
               //get new value from user
               //update exit_flag based on new value
         }
         ...
         return 0;
    }

但后来我认为,如果我最终做了大量的插入/删除,那么我将使用像疯狂一样的循环,这必然会影响程序的速度或大O(N)。所以我想如果我使用另一个全局

变量用于跟踪数组中下一个空运动的位置,而不是每次都循环通过它:

//GLobal Variables
uint8_t my_array[ MAX ];
uint8_t idx = 0;

...

void manipulateArray( uint8_t value )
{
    my_array[ idx++ ] = value;
} 

我的假设在这里是否正确?在这种特殊情况下使用另一种更适合于操作性质(大量插入和无删位)的数据结构也是更好的:向量,链表......

提前致谢,

1 个答案:

答案 0 :(得分:2)

通常解释一下,我带你去询问“插入”值的问题是覆盖EMPTY值,还是用EMPTY代替“删除”值。在这种情况下,您建议维护一个跟踪下一个“空”位置的全局变量,以避免必须在数组中搜索该位置。

实际上,如果你知道下一个插入位置的位置,那么你可以在O(1)步骤中执行插入,而如果你需要执行线性搜索,最好的界限是O(n)。如果你总是在数组的(非空部分)的末尾插入或删除,那么维护你提出的元数据是一个非常好的策略,因为你可以用O(1)步骤维护辅助变量,太

但是假设您需要支持从任意位置删除,而不移动其他数组元素,并且您还希望能够使用插入函数重新填充这些位置。在这种情况下,您必须解决维护多个空位置的信息的问题。单个标量变量是不够的,依赖于数组本身需要您在数组中搜索空位置,这将返回到您开始的位置。

另一种方法是使用更复杂的数据结构 - 例如数组或链表 - 来跟踪主阵列中的开口。通过这种方式,您可以在任何序列的任何位置实现任意数量的插入和删除的O(1)复杂度,代价是使用O(n)内存来维护关于开放阵列位置的元数据。这是一个经典的空间与速度的权衡:实现更快的算法需要使用更多的内存,但是你可以通过使用更慢的算法来节省内存。