C++ 更新数组中给定单元格范围的值的有效方法?

C++ 更新数组中给定单元格范围的值的有效方法?,c++,c,arrays,C++,C,Arrays,A有一组灯光->l1、l2、l3、l4、…lx等 在任何给定的时间点,只有连续的灯光序列处于打开状态。例如: l2、l3、l4可以打开。或者l9、l10、l11可以打开。 但两者之间不可能有差距。例如,不能有l3、l7、l8 在时钟的每一个滴答声中,我都会被告知序列中的起始灯和结束灯,我需要确保只有范围内的灯亮起。(这意味着我可能必须打开或关闭灯,这取决于在上一次勾选中打开和关闭的灯。如果灯已经打开或关闭,则我不需要更新这些灯。) 计算打开和关闭哪些灯光的最快方法是什么? 我提出了许多解决方案,

A有一组灯光->l1、l2、l3、l4、…lx等

在任何给定的时间点,只有连续的灯光序列处于打开状态。例如:

l2、l3、l4可以打开。或者l9、l10、l11可以打开。 但两者之间不可能有差距。例如,不能有l3、l7、l8

在时钟的每一个滴答声中,我都会被告知序列中的起始灯和结束灯,我需要确保只有范围内的灯亮起。(这意味着我可能必须打开或关闭灯,这取决于在上一次勾选中打开和关闭的灯。如果灯已经打开或关闭,则我不需要更新这些灯。)

计算打开和关闭哪些灯光的最快方法是什么? 我提出了许多解决方案,但无法决定哪一个是最好的:

  • 线性方法: 在这个解决方案中,我迭代了l0…lx中的所有灯光。我检查每个灯是否在范围内。如果是,我确保它打开,如果不是,我确保它关闭。这很容易实现,但如果没有更改,则是浪费,如果范围接近终点(例如:l9、l10、l11等),则更糟

  • 国际单项体育联合会系列: 在这种方法中,我在时钟的前一个刻度中跟踪范围的开始/结束,并将其与当前刻度的范围进行比较

    • 如果范围相同,则不执行任何操作。(ls,美国)
    • 如果下限增加,则打开灯直到新的下限。(李)
    • 如果上限增加,打开灯直到新的上限。(用户界面)
    • 如果下限降低,则将灯从新下限打开到旧下限(ld)
    • 如果上限降低,关闭从旧上限到新上限的灯。(ud)。如您所见,在方法(2)中,有九种可能的更改组合。因此,第二种方法有很多if,因此我不清楚编写此代码的最佳方法是什么(有9个if-else块?-看起来很混乱):
    李,李伊,李美,ud ls、ui ls、us ls、ud ld、ui ld、us ld、ud

  • 指针方法-在这种方法中,我创建两个范围的数组

  • 例如:数组1:{3,4,5} 数组2:{4,5,6,7}

    我用p,q指向我正在观察的每个数组中的当前单元格

    我从两个数组的最低索引开始读取 若array1[p]array2[q],那么我打开array2[q]处的灯,并增加q。 我可以通过检查开始/结束索引是否相同来优化此方法

    我认为方法3是最好的——因为代码最容易阅读并且看起来很快。 我可以实现所有3种方法,但不能决定哪种方法最好。如果您能提出更好的方法,或者如何从这三种方法中进行选择并对其进行优化,我们将不胜感激。C或C++可以在我的应用程序中使用。 编辑:两个连续记号中的范围可能相距很远,大小也可能不同。。例如:勾号1可以是{3,4,5},勾号2可以是{7,8,9,10}。所以在这个例子中,我必须在3,4,5关掉灯,然后在7,8,9,10打开

    编辑:“灯光”是我用来解释问题的比喻。灯光只是指软件中的对象


    编辑:我只能访问一个线程,因此无法并行处理该线程的任何部分。

    现在问题已经解决,我的第一个想法是直接在循环中使用起始和结束灯

    for (i = startinglight ; i <= finishinglight ; i++){
        lightarray[i-1] * turn on lights * ;
    }
    

    对于(i=startinglight;i我将从以下方法开始

    • 最容易阅读(因为可读性很重要)和
    • 最容易实施(因为您需要快速的结果/反馈)

    然后进行分析。如果此算法足够,则完成分析。如果不足够,则继续下一种方法。

    我将确保对值进行位打包,而不是进行位打包

    bool lightStatus[NUMBER_OF_LIGHTS];
    

    假设您使用的是64位处理器。否则,请使用
    uint32\u t
    。这将确保您在读/写时不会浪费任何位,因为
    lightStatus
    的所有位实际上都用于编码灯光的状态

    只需对整个阵列执行
    memset()
    ,就可以非常有效地清除所有灯光。这可能足够快,即使您有可能进行不必要的清除


    关于更新,我会做显而易见的事情,因为它基本上是核心信息:存储当前范围,这样每当你得到一个新的,你就可以准确地清除旧的。如果它是一个瓶颈,你可以想象并消除重叠,当然,但我不会担心,除非这是在一个非常慢的CPU上运行或者有(许多?)数千个灯光。

    一个简单的解决方案是结合for循环和if语句:

    其中X是灯光总数

    int lightArray[X] = {0};
    int startLight;
    int endLight;
    
    for (int i = 0, i < X, i++){
        if (i >= startLight && i <= endLight){
            if (lightArray[i] == 0){                 
                lightArray[i] = 1; // or you can change the lights in this loop
            }
        }
        else{
            lightArray[i] = 0; // or you can change the lights in this loop
        }
    } 
    
    for (int i = 0, i < x, i++){
        //some function that sets lights on and off based on lightArray[i]
    }
    
    int lightArray[X]={0};
    内光;
    内景灯;
    对于(int i=0,i如果(i>=startLight&&i这是人为造成的问题,还是通过端口物理控制灯光

    事实上,只有一个连续的序列可以跟踪,这使得这成为一个容易的问题。我认为,最好的选择是选项2。类似的东西应该处理所有重叠和非重叠范围的情况:

    if( old_right < new_left || old_left > new_right ) {
        // Non-overlapping
        for( int i = old_left; i <= old_right; i++ ) set_light_state( i, OFF );
        for( int i = new_left; i <= new_right; i++ ) set_light_state( i, ON );
    } else {
        // Overlapping
        for( int i = old_left; i < new_left; i++ ) set_light_state( i, OFF );
        for( int i = new_left; i < old_left; i++ ) set_light_state( i, ON );
        for( int i = old_right+1; i <= new_right; i++ ) set_light_state( i, ON );
        for( int i = new_right+1; i <= old_right; i++ ) set_light_state( i, OFF );
    }
    
    if(旧的右<新的左| |旧的左>新的右){
    //非重叠
    
    对于(inti=old_left;i您可以将灯光设置为二进制值数组
    {0,1}
    ,例如
    ar

    然后,如果
    [first,last)
    是指示灯亮起的范围,则将阵列拆分为3个范围[开始,首先],[第一,最后],[最后,结束],(其中每个范围都可以为空)

    最后,对每个范围上的每个元素运行一个操作

    for_each(begin, first, [](int i) { i &= 0x0; });
    for_each(first, last , [](int i) { i |= 0x1; });
    for_each(last,  end  , [](int i) { i &= 0x0; });
    
    第一个循环和最后一个循环将状态设置为
    0
    ,第二个循环将状态设置为
    0
    begin = &ar[0];
    end   = &ar[N];
    
    for_each(begin, first, [](int i) { i &= 0x0; });
    for_each(first, last , [](int i) { i |= 0x1; });
    for_each(last,  end  , [](int i) { i &= 0x0; });
    
    int start;
    int end;
    
    void Switcher::toggleLights(int new_start, int new_end) {
    
        if( new_start > start && new_end < end ) {
            //case 1: new lights are within range of lights that are already on           
            turnOffRange(start, new_start);       
            turnOffRange(new_end, end);                     
        }       
        else if( new_start < start && new_end > end) {
            //case 2: lights already on are entirely within new range       
            turnOnRange(new_start, start);
            turnOnRange(end, new_end);           
        }
        else if( new_start < start && new_end > start ) {
            //case 3: new light sequence overlaps start of current range
            turnOffRange(new_end, end);
            turnOnRange(new_start, start);            
        }
        else if( new_start < end && new_end > end ){
            //case 4: new light sequence overlaps end of current range
            turnOffRange(start, new_start);
            turnOnRange(end, new_end);            
        }   
        else {
            //case 5,6 or 7 (no overlap at all)
            turnOffRange(start,end);       
            turnOnRange(new_start,new_end); 
        }
    
        // keep track of the lights that are now on
        start = new_start;
        end = new_end;
    }
    
    void Switcher::turnOffRange(int from, int to) {
        for(int i=from; i < to; ++i) {
            turnOff(i); // (potentially expensive) method to turn light off
        }
    }
    
    void Switcher::turnOnRange(int from, int to) {
        for(int i=from; i < to; ++i) {
            turnOn(i); // (potentially expensive) method to turn lamp on
        }
    }