【问题标题】:What is a 2-way heap?什么是双向堆?
【发布时间】:2011-12-23 16:45:44
【问题描述】:

我正在读一本关于 AI 的书,目前正在学习寻路(目前正在做 Dijkstra 算法)

在示例代码中,他使用了一个他称之为 IndexedPriorityQueue 的东西,该队列实现为双向堆。我在谷歌上找不到关于什么是双向堆的任何信息。

此搜索算法是使用索引优先级队列实现的。 优先级队列,简称 PQ,是一个保留其元素的队列 按优先级排序(那就没有惊喜了)。这类 数据结构可用于存储目标节点 搜索边界上的边缘,按距离(成本)递增的顺序 从源节点。该方法保证节点在 PQ 的前面将是不在 SPT 上的节点,即 离源节点最近。

这是它的实现方式:

//----------------------- IndexedPriorityQLow ---------------------------
//
//  Priority queue based on an index into a set of keys. The queue is
//  maintained as a 2-way heap.
//
//  The priority in this implementation is the lowest valued key
//------------------------------------------------------------------------
template<class KeyType>
class IndexedPriorityQLow
{
private:

  std::vector<KeyType>&  m_vecKeys;

  std::vector<int>       m_Heap;

  std::vector<int>       m_invHeap;

  int                    m_iSize,
                         m_iMaxSize;

  void Swap(int a, int b)
  {
    int temp = m_Heap[a]; m_Heap[a] = m_Heap[b]; m_Heap[b] = temp;

    //change the handles too
    m_invHeap[m_Heap[a]] = a; m_invHeap[m_Heap[b]] = b;
  }

  void ReorderUpwards(int nd)
  {
    //move up the heap swapping the elements until the heap is ordered
    while ( (nd>1) && (m_vecKeys[m_Heap[nd/2]] > m_vecKeys[m_Heap[nd]]) )
    {      
      Swap(nd/2, nd);

      nd /= 2;
    }
  }

  void ReorderDownwards(int nd, int HeapSize)
  {
    //move down the heap from node nd swapping the elements until
    //the heap is reordered
    while (2*nd <= HeapSize)
    {
      int child = 2 * nd;

      //set child to smaller of nd's two children
      if ((child < HeapSize) && (m_vecKeys[m_Heap[child]] > m_vecKeys[m_Heap[child+1]]))
      {
        ++child;
      }

      //if this nd is larger than its child, swap
      if (m_vecKeys[m_Heap[nd]] > m_vecKeys[m_Heap[child]])
      {
        Swap(child, nd);

        //move the current node down the tree
        nd = child;
      }

      else
      {
        break;
      }
    }
  }


public:

  //you must pass the constructor a reference to the std::vector the PQ
  //will be indexing into and the maximum size of the queue.
  IndexedPriorityQLow(std::vector<KeyType>& keys,
                      int              MaxSize):m_vecKeys(keys),
                                                m_iMaxSize(MaxSize),
                                                m_iSize(0)
  {
    m_Heap.assign(MaxSize+1, 0);
    m_invHeap.assign(MaxSize+1, 0);
  }

  bool empty()const{return (m_iSize==0);}

  //to insert an item into the queue it gets added to the end of the heap
  //and then the heap is reordered from the bottom up.
  void insert(const int idx)
  {
    assert (m_iSize+1 <= m_iMaxSize);

    ++m_iSize;

    m_Heap[m_iSize] = idx;

    m_invHeap[idx] = m_iSize;

    ReorderUpwards(m_iSize);
  }

  //to get the min item the first element is exchanged with the lowest
  //in the heap and then the heap is reordered from the top down. 
  int Pop()
  {
    Swap(1, m_iSize);

    ReorderDownwards(1, m_iSize-1);

    return m_Heap[m_iSize--];
  }

  //if the value of one of the client key's changes then call this with 
  //the key's index to adjust the queue accordingly
  void ChangePriority(const int idx)
  {
    ReorderUpwards(m_invHeap[idx]);
  }
};

谁能给我更多关于什么是 2-way heap 的信息?

【问题讨论】:

    标签: c++ data-structures dijkstra


    【解决方案1】:

    “双向堆”只是指标准heap data structure。这段代码展示了一种非常常见的实现方式,即通过将堆的树结构扁平化为数组,使得节点的父节点的索引始终是节点索引的一半(向下舍入)。

    【讨论】:

    • @xcrypt:不确定那里发生了什么,但我最初确实有一个错误的链接,可能有人在后台更正了它,而我又做了一次编辑,覆盖了第一次编辑。
    【解决方案2】:

    它被实现为双向堆,因为他省略了堆中的 0 索引以使父子计算更容易,但键值 vektor 从 0 索引开始,因此倒排堆存储索引,堆的键存储索引keyVector 的键以从 keyVector 获取适当的值,您需要执行类似 keyVector[heap[invHeap[itemIndex] ] ] 的操作,其余代码只是标准二进制堆实现。

    【讨论】:

      猜你喜欢
      • 2012-08-06
      • 2012-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-11
      • 1970-01-01
      • 2011-09-05
      • 1970-01-01
      相关资源
      最近更新 更多