我正在尝试通过coursebuffet.com上的计算机科学课程,该课程将我推荐给saylor.org,它让我this了解如何在C中实现带有链表的堆栈。
首先,我想我理解了这个概念,但如果你是如此善良并在链接中向下滚动,你会在它的末尾找到一个指向主文件的链接,你应该用它测试你的实现。在过去的两天里,最让我感到困惑的是(是的,我已经在这个问题中沉没了多少时间)是以下段落:
/*
* Initialize the stack. Make it at least
* big enough to hold the string we read in.
*/
StackInit(&stack, strlen(str));
我无法理解如何初始化链表。我的意思是,这违背了它的概念,不是吗?我需要在使用push命令填充之前创建struct Elements,但是如果我这样做,我需要在两个方向上跟踪堆栈。推动它的一个方向和弹出它的相反方向。这需要两个指针。我认为这里描述的整个概念将是一个数据元素和每个ADT单元一个指针。
有人可以向我解释一下吗?
答案 0 :(得分:1)
当您将list初始化为要读取的字符串的长度时,仍然会有堆栈指针指向列表的第一个元素。所以基本上没有什么丢失。无论你是对的,都没有必要这样做。
不需要双链表。堆栈指针将始终指向第一个元素。基本上每当你想要BindingSource
时,你会将新节点添加到列表的开头,每当你想要push()
时,你将删除列表的第一个节点。
答案 1 :(得分:1)
假设堆栈仅表示LIFO操作。即最后一次出门。
现在让我们想一想我们是如何实现它的。
首选:只需一个固定大小的内部数组。在这种情况下,您将永远无法动态调整大小。所以堆栈init上面的注释是有效的,你应该分配一个你认为对此目的是安全的大小。
第二选择:拥有一个数组,但使用动态内存。在这种情况下,即使您达到现有堆栈的限制,也始终可以通过realloc扩展大小。所以评论没有意义。
第三种选择:使用linklist,理论上,即使你用0大小初始化堆栈,它也应该在每个节点插入时扩展,因此注释具有误导性。只是要添加,top始终是linklist的头部,每次插入时,新节点都将成为新的头。
所以回答你的问题,上面的评论只是在内部实现是基于数组的时候才会引起混淆。
但是在与Stack DS相关的常识和一般感知中,Stack是始终与Stack Depth相关联的DS。在实现这个时,它总是安全的,可以推送的元素的最大限制,我想,可能是注释意味着。
为了用一个真实的例子进一步说明它,你必须听说过函数的callstack,虽然理论上它的扩展但是有MAX可能的限制,这就是我们在进行无限递归时看到堆栈溢出错误的原因。