0

好的,我正在尝试使用链表为我的 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 上,我只是觉得它们不方便。不应为 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) 有没有办法编写反下溢 pop/peek无需通过引用传递任何东西?

4

1 回答 1

2

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

  • pop使其成为堆栈不为空的先决条件。客户有责任确保这一点(可能通过 is_empty()在弹出之前调用),违反前提条件会导致断言失败。

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

  • 没有pop返回值(或让它返回你的bool)。要获取顶部元素,您有一个单独的函数 ,tos()而想要同时执行这两种操作的客户端需要两个函数调用:x = s.tos(); s.pop();. 例如,这就是标准所做的。在实践中,它通常是首选方法,因为对于复制可能抛出的类型(例如 std::string),不可能实现 pop 以返回值并提供强异常保证。(这是否是一个问题是另一个问题,但在特定情况下它可能是一个问题,这是标准中选择背后的动机,其中没有弹出函数返回值。)

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

顺便说一句,你不需要ifin add_to_head。如果head == NULL,您将使用第二个参数调用构造函数 NULL,因此您最好head在两种情况下都通过。

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

于 2012-11-05T20:03:20.553 回答