Arrays 有效地合并相邻块

Arrays 有效地合并相邻块,arrays,algorithm,data-structures,merge,theory,Arrays,Algorithm,Data Structures,Merge,Theory,这就是我想做的: 我有一个名为merge()的例程,它定期被调用。它的任务是合并名为“Block”的数据结构,其内容是由“s_idx”和“e_idx”表示的一系列整数,分别表示起始索引和结束索引。相邻块是其范围可以组合成新的连续范围的块。例如,具有范围(25,32)的块3和具有范围(33,40)的块4是相邻的,因此可以组合它们的范围以产生新的连续范围(25,40)。因此,在结束时,只剩下一个块,将所有单独的块组合起来生成范围(0,N-1),其中N是块的总数 我的问题是:有没有有效的算法来执行这样

这就是我想做的: 我有一个名为merge()的例程,它定期被调用。它的任务是合并名为“Block”的数据结构,其内容是由“s_idx”和“e_idx”表示的一系列整数,分别表示起始索引和结束索引。相邻块是其范围可以组合成新的连续范围的块。例如,具有范围(25,32)的块3和具有范围(33,40)的块4是相邻的,因此可以组合它们的范围以产生新的连续范围(25,40)。因此,在结束时,只剩下一个块,将所有单独的块组合起来生成范围(0,N-1),其中N是块的总数

我的问题是:有没有有效的算法来执行这样的操作

当前的实现使用O(N^2)算法,该算法随着块数的增加而显著减慢

for( int i=0 ; i<_merge_list.max()-1 ; i++ )
    {
        for( int j=i+1 ; j<_merge_list.max() ; j++ )
        {
            if( _merge_list.exist(i) && _merge_list.exist(j) )
            {
                if( _merge_list[i]->get_end_idx() + 1 ==    _merge_list[j]->get_start_idx() )
                {
                    _merge_list[i]->set_end_idx( _merge_list[j]->get_end_idx() );
                    _merge_list[i]->set_link( _merge_list[j]->get_block_idx() );


                                    perform(_merge_list[i]);

                    _merge_list.remove(j);          
                }
            }
        }

    }   
for(inti=0;iget\u start\u idx())
{
_merge_list[i]->set_end_idx(_merge_list[j]->get_end_idx());
_merge_list[i]->set_link(_merge_list[j]->get_block_idx());
执行(_merge_list[i]);
_合并列表。删除(j);
}
}
}
}   

是否保证所有区块都是连续的?如果是这种情况,那么在O(N)时间内找到最小、最大索引,然后创建一个最终块应该很简单,否则可以先对块进行排序,然后合并O(NlogN)+O(N)=O(NlogN)


如果以排序方式维护块,则合并块只需O(N)个时间。如果同时拥有所有块,则首先对块数组进行排序,然后合并。如果您将它们逐块合并到块数组中,以保持排序顺序。

是否保证所有块都是连续的?如果是这种情况,那么在O(N)时间内找到最小、最大索引,然后创建一个最终块应该很简单,否则可以先对块进行排序,然后合并O(NlogN)+O(N)=O(NlogN)



如果以排序方式维护块,则合并块只需O(N)个时间。如果同时拥有所有块,则首先对块数组进行排序,然后合并。如果逐块获得这些块,则以保持排序顺序的方式将它们合并到块数组中。

例程merge()从其他处理器接收块,并在某些特定点调用例程以合并块。当每合并两个块时,将对生成的新块执行一个操作,如行所示:perform(_merge_list[i]);所以块之间随时都可能有间隙。不,没有限制。现在我假设正确性,只要它不超过最大的可表示数。[0,5]和[8,12]不能合并,因为它们不是连续的。但是,[0,5]、[6,7]、[8,12]可以合并如下:[0,5]+[6,7]=[0,7],然后[0,7]+[8,12]=[0,12]。但是,最后总是保证它们都可以合并到一个块中,因为所有的块都已经可用。例程merge()从其他处理器接收块,并且在某些特定点调用例程来合并块。当每合并两个块时,将对生成的新块执行一个操作,如行所示:perform(_merge_list[i]);所以块之间随时都可能有间隙。不,没有限制。现在我假设正确性,只要它不超过最大的可表示数。[0,5]和[8,12]不能合并,因为它们不是连续的。但是,[0,5]、[6,7]、[8,12]可以合并如下:[0,5]+[6,7]=[0,7],然后[0,7]+[8,12]=[0,12]。然而,最后总是保证它们都可以合并成一个块,因为所有的块都已经可用了。我不太理解你的想法。为了澄清问题,此例程不会被调用一次,而是在运行时定期调用。此外,在最后一个块出现之前无法确定N。因此,出于这个原因,我的代码中使用了一个动态数组(_merge_list是动态数组的一个实例)。但是,块根据其ID存储在动态数组中。因此,它们总是保持排序。@t如果块总是保持排序,那么您总是可以在O(N)时间内合并,只需迭代排序的块列表并合并。哦..您是对的。我希望有一些更快的O(logn)类算法。。。然而,这个线程仍然可以接受新的想法…哈哈,当你收到一个块,如果你知道收到的块是什么,你可以直接合并O(1),然后通过二进制搜索找到你需要添加它的位置O(logn)。我不太明白你的想法。为了澄清问题,此例程不会被调用一次,而是在运行时定期调用。此外,在最后一个块出现之前无法确定N。因此,出于这个原因,我的代码中使用了一个动态数组(_merge_list是动态数组的一个实例)。但是,块根据其ID存储在动态数组中。因此,它们总是保持排序。@t如果块总是保持排序,那么您总是可以在O(N)时间内合并,只需迭代排序的块列表并合并。哦..您是对的。我希望有一些更快的O(logn)类算法。。。然而,这个线程仍然可以接受新的想法…哈哈,当你收到一个块,如果你知道收到的块是什么,你可以直接合并O(1)后,找到你需要添加它的位置O(logn)通过二进制搜索。