我正在学习如何分析算法,我找到了“摊销时间”的表示法。我找到了一些预定义的估算,如:
- 在排序数组中插入的延迟时间为:O(n)
从排序数组中删除的分摊时间为:O(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)。