好的,我正在尝试使用链接列表为我的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) 有没有办法写一个反下溢的流行/偷看,而不必通过引用传递任何东西?
答案 0 :(得分:2)
这是一个规范问题。有几种可能的解决方案:
使其成为pop
的前提条件,表示堆栈不为空。它是
客户有责任确保这一点(也许是通过电话
在弹出之前is_empty()
,并违反前提条件
导致断言失败。
如果堆栈为空,则抛出异常。这是最明显的 解决方案,但可能是最不普遍适用的。
不要让pop
返回值(或让它返回bool
)。至
获取顶部元素,您有一个单独的函数tos()
和一个客户端
谁想要两者都需要两个函数调用:x = s.tos(); s.pop();
。
例如,这就是标准所做的。在实践中,它经常是
首选方法,因为对于复制可以抛出的类型(例如
std::string
),无法实现pop返回值和
给予强有力的例外保证。 (这是否是一个问题
是另一个问题,但在特定情况下可能是一个问题,而且确实如此
标准中选择背后的动机,其中没有流行音乐
函数返回一个值。)
最后,重要的是你要定义界面,所以 您的用户知道会发生什么。
顺便说一句,您不需要if
中的add_to_head
。如果head ==
NULL
,您将使用第二个参数调用构造函数
NULL
,所以您也可以在两种情况下都通过head
。
(我将跳过使用链表非常低效的事实 实现堆栈的方法,因为代码显然是一种学习 锻炼。)