【问题标题】:Advice on implementing put() function in a c++ templated queue?关于在 C++ 模板化队列中实现 put() 函数的建议?
【发布时间】:2011-12-01 02:44:04
【问题描述】:

我正在尝试实现一个不允许更改头文件定义的队列,如下所示:

class PQueue
{
  private:

    struct Node
    {
      EType Item;
      unsigned Priority;
      unsigned Identifier;
      Node * Pred;
      Node * Succ;
    };

    Node * Head;    // Pointer to head of chain (front)
    Node * Tail;    // Pointer to tail of chain (back)

  public:

    // Initialize pqueue to empty
    //
    PQueue();

    // De-initialize pqueue
    //
    ~PQueue();

    // Re-initialize pqueue to empty
    //
    void reset();

    // Initialize pqueue using existing pqueue
    //
    PQueue( const PQueue<EType>& );

    // Assign into pqueue from other pqueue
    //
    PQueue<EType>& operator=( const PQueue<EType>& );

    // Display attributes and contents of pqueue
    // (from front to back, or back to front)
    //
    void display( ostream&, Direction ) const;

    // Return number of items in pqueue
    //
    unsigned length() const;

    // Return copy of item at front of pqueue (unless pqueue is empty)
    //
    bool front( EType& ) const;

    // Return copy of item at back of pqueue (unless pqueue is empty)
    //
    bool back( EType& ) const;

    // Insert one item (with specified priority) into pqueue (if possible)
    //
    bool put( const EType&, unsigned );

    // Remove item with highest priority from pqueue (unless pqueue is empty)
    //
    bool get( EType& );

    // Discard item with specified identifier from pqueue (if possible)
    //
    bool discard( unsigned );
};

到目前为止,我有这些构造函数和析构函数:

template <typename EType> PQueue::PQueue() {
    Head->Pred = NULL;
    Tail->Succ = NULL;
    Tail->Pred=Head;
    Head->Succ=Tail;
} 

template <typename EType> PQueue::~PQueue() {
    reset();
    delete Head;
    Head = NULL;
    delete Tail;
    Tail = NULL;
}

现在我卡在put(),我不知道从哪里开始,有什么帮助吗?

【问题讨论】:

    标签: c++ templates queue


    【解决方案1】:

    您应该分配一个节点,并将其挂接到列表中。

    像这样:

       template <typename EType>
       bool PQueue::put( const EType& et, unsigned pri ) {
          Node *p = new Node ();
          p->Item = et;
          p->priority = pri;
    // now hook it into the list
       p->pred = NULL;
       head = p;
       }
    

    但是,这还不够,因为您没有在构造函数中正确初始化 head 和 tail;以至于我无法判断您是在创建单链表还是双链表。在您当前的代码中,您的代码就像 head 和 tail 指向实际节点一样,但我看不到这些节点在哪里(或在哪里创建)。

    此外,您的某些代码是在 EType 上模板化的,而其他部分则不是。你需要保持一致。

    【讨论】:

    • 在一个队列中,我们通常会假设它是先进先出的。因此,从语义上讲,您会将新节点放在 tail 而不是头部。定义清楚地表明这是一个双向链表,因此 OP 至少需要p-&gt;Pred = Tail; Tail-&gt;Succ = p; p-&gt;Succ = NULL; Tail = p;。此外,priority 字段的存在表明必须付费才能在某个时间点找到优先位置......并且由于存在不可修改的访问器(如正面和背面),因此当时为定位付费是最有意义的插入,所以它比这更复杂。
    • @Marshall Clow,我的硬件就是这样。我无法更改 EType。
    【解决方案2】:

    在继续使用 put() 之前,您需要正确设置现有的构造函数和析构函数!

    如果您要设置节点的-&gt;Pred-&gt;Succ,则节点必须首先存在。 Head 和 Tail 是 Node 的 pointers...不是 Node 的 instances,所以没有节点可以操作:

    如果 Head 和 Tail 本身是节点,事情会有所不同,但它们会被声明为:

    Node Head;    // head node of chain (front)
    Node Tail;    // tail node of chain (back)
    

    ...而不是:

    Node * Head;    // Pointer to head of chain (front)
    Node * Tail;    // Pointer to tail of chain (back)
    

    这在技术上是可行的,但不清楚为什么空且未初始化的队列实现需要任何节点都存在。如果您正在创建一个不寻常的队列类,它总是至少有两个元素(出于某种原因),那么您可能会考虑这样的奇怪之处。但你的任务显然不是要求这样做的。

    您要遵循的规则是空队列(例如刚刚构建的队列)具有 Nodes。只需将 Head 和 Tail 指针本身设置为 NULL 即可完成:

    template <typename EType> PQueue::PQueue() {
        Head = NULL;
        Tail = NULL;
    } 
    

    顺便说一句,初始化成员有一种特殊的语法……虽然在这种情况下,是否使用代码中的赋值语句进行初始化并不重要,但在某些情况下,例如基类初始化,您必须这样做:

    template <typename EType> PQueue::PQueue() :
        Head (NULL),
        Tail (NULL)
    {
    } 
    

    因此,如果规则(或"invariant")是空队列的头部和尾部为空,那么调用reset() 应该会使您处于头部和尾部为空的状态。然而,如果 head 和 tail 为 NULL,那么你为什么要在析构函数中删除它们?它在技术上是安全的:

    Is it safe to delete a NULL pointer?

    但不会有任何效果。一个 reset() 调用应该足以实现析构函数的工作,以释放任何非空队列的所有已分配节点......如果队列为空,reset() 应该足够聪明,可以什么都不做:

    template <typename EType> PQueue::~PQueue() {
        reset();
    }
    

    至于我对继续使用 put() 的建议...嗯...看来您需要阅读书籍并了解语言和数据结构的基本问题。处理简单的链表...没有模板...只需要一个工作:

    http://en.wikipedia.org/wiki/Linked_list

    【讨论】:

      猜你喜欢
      • 2013-01-04
      • 1970-01-01
      • 2013-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-18
      • 2021-05-29
      相关资源
      最近更新 更多