无法使用喜欢的列表在堆栈中实现正确的(下溢保护的)pop / peek方法

时间:2012-11-05 19:45:34

标签: c++ stack stackunderflow

好的,我正在尝试使用链接列表为我的C ++作业编写堆栈弹出方法。 让我先向您展示节点和列表类,然后告诉您问题:

class Node
{
public:
    int data;
    Node* next;

    Node(int data, Node* next = 0)
    {
        this->data = data;
        this->next = next;
    }
};
class List
{
private:
  Node* head; // no need for the tail when using the list for implementing a stack

public:
    List()
    {
        head = 0;
    }
    void add_to_head(int  data)
    {
        if(head == 0)
        {
            head = new Node(data);
        }
        else 
        {
            head = new Node(data, head);
        }
    }

    Node* get_head()
    {
        return head;
    }

    // this deletes the head element and makes 'head' points to the node after it.
    void delete_head()
    {
        // storing the head so that we could delete it afterwards.
        Node* temp = head;

        // making the head point to the next element.
        head = temp->next;

        // freeing memory from the deleted head.
        delete(temp);
    }
};

现在这里是堆栈:

class stack
{
private: 
    List* list;

public:
  stack()
  {
      list = new List();
      flush();
  }
  void push(int value)
  {
      list->add_to_head(value);
  }
  bool pop(int& value_to_fill)
  {
      if(is_empty())
      {
        return false; // underflow...
      }

      value_to_fill = list->get_head()->data;

     // deleting the head. NOTE that head will automatically point to the next element after deletion 
     // (check out the delete_head definition)
     list->delete_head();

     return true; // popping succeed.
  }
  bool peek(int& value_to_fill)
  {
    if(is_empty())
    {
       return false;
    }
    value_to_fill = list->get_head()->data;
    return true;
  }
 // other stuff...
};

现在的问题是流行和偷看,我只是觉得它们不方便。 pop和peek不应该给出任何参数,但如果我这样做:

int peek()
{
  if(is_empty())
    // what should I do here?
  return list->get_head()->data;
}
int pop()
{
  if(is_empty())
    // same thing here.

  // deleting the tos then returning it.
  // I know this is not what the pop in the STL stack does, but I like it this way
    int tos = list->get_head()->data;
    list->delete_head();
    return tos;
}

我不知道发生下溢时该怎么办。 我不能只返回-1或0或类似的东西,因为这看起来好像我弹出-1或0(tos == -1或0) 有没有办法写一个反下溢的流行/偷看,而不必通过引用传递任何东西?

1 个答案:

答案 0 :(得分:2)

这是一个规范问题。有几种可能的解决方案:

  • 使其成为pop的前提条件,表示堆栈不为空。它是 客户有责任确保这一点(也许是通过电话 在弹出之前is_empty(),并违反前提条件 导致断言失败。

  • 如果堆栈为空,则抛出异常。这是最明显的 解决方案,但可能是最不普遍适用的。

  • 不要让pop返回值(或让它返回bool)。至 获取顶部元素,您有一个单独的函数tos()和一个客户端 谁想要两者都需要两个函数调用:x = s.tos(); s.pop();。 例如,这就是标准所做的。在实践中,它经常是 首选方法,因为对于复制可以抛出的类型(例如 std::string),无法实现pop返回值和 给予强有力的例外保证。 (这是否是一个问题 是另一个问题,但在特定情况下可能是一个问题,而且确实如此 标准中选择背后的动机,其中没有流行音乐 函数返回一个值。)

最后,重要的是你要定义界面,所以 您的用户知道会发生什么。

顺便说一句,您不需要if中的add_to_head。如果head == NULL,您将使用第二个参数调用构造函数 NULL,所以您也可以在两种情况下都通过head

(我将跳过使用链表非常低效的事实 实现堆栈的方法,因为代码显然是一种学习 锻炼。)