C++ 更新数组中给定单元格范围的值的有效方法?
A有一组灯光->l1、l2、l3、l4、…lx等 在任何给定的时间点,只有连续的灯光序列处于打开状态。例如: l2、l3、l4可以打开。或者l9、l10、l11可以打开。 但两者之间不可能有差距。例如,不能有l3、l7、l8 在时钟的每一个滴答声中,我都会被告知序列中的起始灯和结束灯,我需要确保只有范围内的灯亮起。(这意味着我可能必须打开或关闭灯,这取决于在上一次勾选中打开和关闭的灯。如果灯已经打开或关闭,则我不需要更新这些灯。) 计算打开和关闭哪些灯光的最快方法是什么? 我提出了许多解决方案,但无法决定哪一个是最好的:C++ 更新数组中给定单元格范围的值的有效方法?,c++,c,arrays,C++,C,Arrays,A有一组灯光->l1、l2、l3、l4、…lx等 在任何给定的时间点,只有连续的灯光序列处于打开状态。例如: l2、l3、l4可以打开。或者l9、l10、l11可以打开。 但两者之间不可能有差距。例如,不能有l3、l7、l8 在时钟的每一个滴答声中,我都会被告知序列中的起始灯和结束灯,我需要确保只有范围内的灯亮起。(这意味着我可能必须打开或关闭灯,这取决于在上一次勾选中打开和关闭的灯。如果灯已经打开或关闭,则我不需要更新这些灯。) 计算打开和关闭哪些灯光的最快方法是什么? 我提出了许多解决方案,
- 如果范围相同,则不执行任何操作。(ls,美国)
- 如果下限增加,则打开灯直到新的下限。(李)
- 如果上限增加,打开灯直到新的上限。(用户界面)
- 如果下限降低,则将灯从新下限打开到旧下限(ld)
- 如果上限降低,关闭从旧上限到新上限的灯。(ud)。如您所见,在方法(2)中,有九种可能的更改组合。因此,第二种方法有很多if,因此我不清楚编写此代码的最佳方法是什么(有9个if-else块?-看起来很混乱):
编辑:我只能访问一个线程,因此无法并行处理该线程的任何部分。现在问题已经解决,我的第一个想法是直接在循环中使用起始和结束灯
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
}
}