不明白这个代码原则

时间:2013-09-02 07:52:24

标签: c++ stl

// set::insert (C++98)
#include <iostream>
#include <set>

int main ()
{
  std::set<int> myset;
  std::set<int>::iterator it;
  std::pair<std::set<int>::iterator,bool> ret;

  // set some initial values:
  for (int i=1; i<=5; ++i) myset.insert(i*10);    // set: 10 20 30 40 50

  ret = myset.insert(20);               // no new element inserted

  if (ret.second==false) it=ret.first;  // "it" now points to element 20

  myset.insert (it,25);                 // max efficiency inserting
  myset.insert (it,24);                 // max efficiency inserting
  myset.insert (it,26);                 // no max efficiency inserting

  int myints[]= {5,10,15};              // 10 already in set, not inserted
  myset.insert (myints,myints+3);

  std::cout << "myset contains:";
  for (it=myset.begin(); it!=myset.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}

我在cplusplus参考站点上看到此代码为例。它说

myset.insert (it,25);                 // max efficiency inserting
myset.insert (it,24);                 // max efficiency inserting

这是插入效率的最大值,但我不明白。 谁能告诉我为什么?

3 个答案:

答案 0 :(得分:3)

std::set使用平衡树结构。当您致电insert时,您可以提供实施提示 - 它可以用来加快插入速度。

考虑常规二进制搜索树中的常规insert方法如何工作。从根节点开始,您必须使用常规检查进行降级:

void insert(node* current, const T& value)
{
    if(node == nullptr) // Construct our new node here
    else if(value < node->current) insert(current->left, value);
    else if(value > node->current) insert(current->right, value);
}

void insert(const T& value)
{
    insert(root, value);
}

在平衡树中,这必须执行(平均)O(log n)比较以插入给定值。

但是,假设我们不是从根节点开始,而是为实现提供一个起始节点,该节点是实际插入发生的地方。例如,在上面,我们知道24和25将成为包含20的节点的子节点。因此,如果我们从那个节点开始,我们不需要进行O(log n)比较 - 我们可以直接插入我们的节点。这就是“最大效率”插入的意思。

答案 1 :(得分:0)

您是否阅读过通知?

  

位置   提示元素可以插入的位置。   C ++ 98   如果位置指向,则该函数优化其插入时间   插入元素之前的元素。

它指向20并且在25之前。

答案 2 :(得分:0)

通常,std::set必须查找它插入的位置;这个 查找是O(lg n)。如果你提供“提示”(附加的 迭代器)插入应该发生的地方 实现将首先检查此提示是否正确(哪个 可以在O(1)中完成,如果是,则插入那里,从而跳过 O(lg n)向上看。如果提示不正确,当然,它 然后恢复到插入状态,好像它没有得到提示一样。

有两种情况经常使用提示:第一种 是在插入已排序数据的序列时。在 在这种情况下,提示是结束迭代器,因为如果数据是 已经排序,每个新值实际上将被插入 结束。第二种是使用插入复制到集合中 迭代器。在这种情况下,“提示”(可以是任何东西) 不仅仅是出于语法原因:你不能使用 back_insertion_iteratorfront_insertion_iterator, 因为std::set没有push_backpush_front,并且 简单的insertion_iterator需要一个迭代器来告诉它 在哪里插入;此迭代器将传递给insert