用C ++ STL进行修改?

时间:2015-08-25 20:23:50

标签: c++ algorithm stl

我正在寻找一个实现Heapify的函数,但似乎没有直接来自C ++ STL的高效函数。

CLRS教科书中定义的堆化函数将采用元素位置i,假设i的左右子树都是堆,并使以i为根的树成为堆,复杂性为log(n )。

给定[first,last]中的堆,我想删除第一个元素,将其替换为另一个元素,并维护堆属性。为了实现这一点,我们只需要调用heapify(first)一次,遍历堆一次,具有log(n)复杂性。

STL有pop_heap和push_heap函数,它可以通过首先调用pop_heap和push_heap来实现目标,但pop_heap维护堆属性,而push_heap也维护堆属性,这会在堆中推断出两个遍历。尽管整体复杂性仍然是log(n),但效率并不高。删除第一个元素后,我们不需要维护堆属性。

除了编写自己的heapify函数之外还有什么好主意吗?

1 个答案:

答案 0 :(得分:2)

标准库没有swimDownswimUp函数(如算法书中所述,无论如何std::make_heap在线性时间内对矢量实现堆积(详情here)。您可以修改所需的元素,然后在向量上调用make_heap

int main()
{
  int myints[] = {10,20,30,5,15};
  std::vector<int> v(myints,myints+5);

  std::make_heap (v.begin(),v.end());
  std::cout << "initial max heap   : " << v.front() << '\n';

  // Modify first element
  v[0] = 10;
  std::make_heap(v.begin(),v.end());
  std::cout << "after modification max heap   : " << v.front() << '\n';
}

另一种解决方案是

  1. 将修改后的元素推送到向量的背面
  2. 致电pop_heap,它将交换第一个和最后一个元素并重新合并(一个swimDown
  3. 从后面弹出前一个元素
  4. 这可能更有效(如果仅用于比较次数)

    int main()
    {
      int myints[] = {10,20,30,5,15};
      std::vector<int> v(myints,myints+5);
    
      std::make_heap (v.begin(),v.end());
      std::cout << "initial max heap   : " << v.front() << '\n';
    
      v.push_back(10);
      std::pop_heap(v.begin(), v.end()); // Takes 30 out of the heap and swims 10 down
      v.pop_back(); // Drops 30
    
      std::cout << "after modification max heap   : " << v.front() << '\n';
    }