在排序数组中插入的分摊时间是O(n),删除是O(1)?

时间:2017-10-28 17:09:52

标签: arrays algorithm sorting amortized-analysis

我正在学习如何分析算法,我找到了“摊销时间”的表示法。我找到了一些预定义的估算,如:

- 在排序数组中插入的延迟时间为:O(n)

从排序数组中删除的分摊时间为:O(1)

请有人详细解释一下吧!

1 个答案:

答案 0 :(得分:4)

这个想法是将数组中的每个条目与一个名为deleted的布尔值相关联。删除项目包括将deleted设置为true。如果删除的项目太多,请将其压缩。如果您将压实阈值设置为总大小的一小部分,则可以从达到压缩点所需的所有删除中支付压缩。

这是草图。它不完整,但演示了插入和删除算法。

class sorted_array
{
public:
    typedef std::vector<std::pair<int, bool>>::iterator iterator;

    iterator insert(int value)
    {
        auto item = std::make_pair(value, false);
        return vec.insert(std::lower_bound(vec.begin(), vec.end(), item), item);
    }

    void erase(iterator pos)
    {
        pos->second = true; // deleted = true
        deleted_count++;
        if (deleted_count * 2 > vec.size())
        {
           vec.erase(std::remove_if(vec.begin(), vec.end(),
                                    std::get<1, int, bool>), vec.end());
           deleted_count = 0;
        }
    }

private:
    size_t deleted_count = 0;
    std::vector<std::pair<int, bool>> vec;
}

插入与往常一样是O(n)。当我们插入元素时,我们也将其标记为未删除。

要删除元素,我们只需将其标记为已删除并存入两个学分。

当向量中超过一半的元素被删除时,这意味着我们至少有与向量中的元素一样多的信用。这意味着我们可以负担得起运行O(n)压缩。

要查找元素,请运行传统的二进制搜索,然后跳过已删除的元素。由于最多删除了一半的元素,因此二进制搜索最多运行2n个元素,这意味着它以O(log 2n)= O(log n)步进运行。在二进制搜索完成后,有一些额外的成本会跳过已删除的项目,但数据结构中的一些更聪明可以将其减少为常量。 (留作练习。)

类似地,迭代集合最多需要2n步(因为最多删除了一半的元素),这仍然是O(n)。