在使用相似列表的堆栈中实现正确的(底流保护的)pop/peek方法时出现问题 < >我想用链表编写C++ POST的方法来完成我的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); } };
现在是堆栈:在使用相似列表的堆栈中实现正确的(底流保护的)pop/peek方法时出现问题 < >我想用链表编写C++ POST的方法来完成我的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); } };,c++,stack,stackunderflow,C++,Stack,Stackunderflow,现在是堆栈: 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()) {
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,而不必通过引用传递任何内容?这是一个规范问题。有几种可能的解决方案:
- 将堆栈不为空作为
的先决条件。它是 客户确保这一点的责任(可能通过致电pop
),并且违反了前提条件 导致断言失败在弹出前为空()
- 如果堆栈为空,则引发异常。这是最明显的 解决方案,但可能是最不普遍适用的
- 不要让
返回值(或者让它返回您的pop
)。到 获取顶部元素时,您有一个单独的函数,bool
,以及一个客户端 想要同时完成这两项任务,需要两个函数调用:tos()
x=s.tos();s、 pop()代码>。 例如,这就是标准所做的。在实践中,这往往是错误的 首选方法,因为对于复制可以抛出的类型(例如。
),不可能实现pop来返回值和 给予强有力的例外保证。(无论这是否是一个问题 这是另一个问题,但在特定情况下可能是一个问题,事实确实如此 标准中的选择背后的动机,其中没有流行音乐 函数返回一个值。)std::string
add_to_head
中使用if
。如果头部==
NULL
,您将使用第二个参数调用构造函数
NULL
,因此在这两种情况下,您最好只传递head
(我将跳过一个事实,即使用链表效率非常低
实现堆栈的方法,因为代码显然是一种学习
他们说异常很好。你不想用讨厌的列表来代替吗?@doublep:好吧,从我(从C#)知道你不能这样做:int peek(){try{return list->get_head()->data;}catch(…){}你会得到一个错误,说所有路径都必须返回某个东西。但是我只是尝试了C++,效果不错!它编译时没有任何错误。它不应该给我那个错误吗?@ VXEE,如果代码真的走了那个路径,C++中只有一个错误。编译器很难确定这一点,因此不需要错误消息。(这叫做未定义的行为。)说得再好不过了。但是,实现堆栈的最佳方法是什么?使用数组?是的,正如你所猜测的,我只是在链表上训练。@VeXe我通常会使用
std::vector
,使用push_-back
,pop_-back
和back
来实现push、pop和tos。