heap

STL heap以vector为底层容器,从1开始存,2i为左子节点,即是个二叉堆,是个大根堆。

优先队列(priority queue)允许用户以任何次序将任何元素插入容器,但取出时要从优先权最大的元素开始取。二叉大根堆具有这样的特性,因此作为优先队列的底层机制。

能不能用list作为优先队列底层机制?

list作为优先队列底层机制可以实现元素插入的常数时间,但是要找到list的最值,却要对list做线性扫描。我们可以先对元素排序,这样,找到最值以及元素删除为常数时间,但是元素的插入又是线性时间。

能不能用二叉搜索树作为优先队列底层机制? 

用二叉搜索树元素插入和最值取得都可以在O(logn)内完成,但是这样小题大做:第一,二叉搜索树的输入需要足够的随机性;第二,二叉搜索树的实现不容易。

 

push_heap(first,last):(当数组中已经放入了一个新的元素并且这个元素位于容器最尾端,数组之前是有序的)用来将尾端元素调整至有序的位置

pop_heap(first,last):将最大元素放置最尾端,然后调整数组使有序(最大元素要调用pop_back()进行删除,现在还未删,数组之前是有序的

sort_heap(first,last):对所有元素进行整体升序排列(数组之前是满足二叉堆的规则的,所以实际实现是用pop_heap每次排列后最大元素归位)

make_heap(first,last):对无序的元素进行排序使得它满足二叉堆的规则

 

push_heap中的核心算法如下:

template <class RandomAccessIterator, class Distance, class T, class Compare>  
void __push_heap(RandomAccessIterator first, Distance holeIndex,  
                 Distance topIndex, T value, Compare comp)  
{  
  Distance parent = (holeIndex - 1) / 2;  
  while (holeIndex > topIndex && comp(*(first + parent), value)) {  
    *(first + holeIndex) = *(first + parent);  
    holeIndex = parent;  
    parent = (holeIndex - 1) / 2;  
  }  
  *(first + holeIndex) = value;  
}  

pop_heap以及make_heap的核心算法是一样的,如下:

template <class RandomAccessIterator, class Distance, class T>  
void __adjust_heap(RandomAccessIterator first, Distance holeIndex,  
                   Distance len, T value)  
{  
  Distance topIndex = holeIndex;  
  Distance secondChild = 2 * holeIndex + 2;     // 弹出元素的有子孩  
  
  // 调整heap元素位置  
  while (secondChild < len) {  
    // 选择两个子孩中较大的进行操作, 使用secondChild表示其偏移  
    if (*(first + secondChild) < *(first + (secondChild - 1)))  
      secondChild--;  
  
    // 将较大元素向上填充, 并将整体偏移向下调整, 继续调整  
    *(first + holeIndex) = *(first + secondChild);  
    holeIndex = secondChild;  
    secondChild = 2 * (secondChild + 1);  
  }  
  
  if (secondChild == len) {  
    *(first + holeIndex) = *(first + (secondChild - 1));  
    holeIndex = secondChild - 1;  
  }  
  
  __push_heap(first, holeIndex, topIndex, value);  
}  

 

你可能感兴趣的:(heap)