是否可以在没有临时存储的情况下进行就地合并?

时间:2010-12-07 04:11:44

标签: c++ algorithm

我只是想,如果我要实现std::inplace_merge,它可能看起来像这样:

template <class Bi, class Cmp>
void inplace_merge(Bi first, Bi middle, Bi last, Cmp cmp) {
    if(first != last) {
        typedef typename iterator_traits<Bi>::value_type T;
        typedef typename iterator_traits<Bi>::difference_type Dist;

        const Dist count = distance(first, last);
        if(count != 1) {
            // can I avoid this allocation?
            T *const temp = new T[count];       
            merge(first, middle, middle, last, temp, cmp);      
            copy(temp, temp + count, first);
            delete [] temp;
        }
    }
}

我知道我可以使用现有的实现,但除了这一点之外。 我很好奇是否有比我所知的更好的算法。

我想到的原因是大多数c ++标准库(如果我没记错的话,所有的STL)都允许用户指定执行分配的方式和位置,但如果std::inplace_merge需要按设计分配,如果这是一个问题,似乎没有办法控制它。

我认为对答案的暗示来自标准本身关于std::inplace_merge的复杂性:

  

复杂性:足够的额外   内存可用,(最后 - 第一) -   1比较。如果没有额外的记忆   是可用的,一种算法   复杂度N log N(其中N相等   可以使用(最后一次)。

对我而言,这意味着该算法的已知有效版本需要额外的存储空间。我读得对吗?如果是的话,有没有提到存储应该来自哪里?

1 个答案:

答案 0 :(得分:15)

有几种已知的就地合并算法,尽管其中一些算法相当复杂。它们工作的一般方式是使用一些数组元素本身作为外部存储空间进行异地合并。我知道Alex Stepanov和Paul McJones的“编程元素”详述了一种算法。

我最近阅读了一篇名为"Practical In-Place Merging"的关于就地合并的论文,其中详细介绍了进行此类合并的相当简单的算法。我以接近std::inplace_merge接口的方式编码an implementation of this algorithm,但存在一些差异。也许那里有一些你可能觉得有用的东西?