【问题标题】:Create a generic stack implemented with a linked-list in C在 C 中创建一个用链表实现的通用堆栈
【发布时间】:2012-02-18 11:52:08
【问题描述】:

我想创建一个通用堆栈。我想用链表来实现它。

我创建了这个结构 stack_l

typedef struct stack
 {
   void * data;

   void (*copy)(void *o);

   struct stack *next;

 } stack_l;

我有一些问题:


  • 结构的第二个字段是指向函数的指针,用于复制新数据(在函数 Push 中通过参数传递)。 Push函数的原型是:

stack_l * Push(stack_l * head, void * d);

  1. 将指针传递给函数副本的方式是否正确?
  2. 我必须在函数Push中实现它??

  • 是否有必要创建一个函数 NewStack(例如)来初始化结构的字段,或者最好只有一个 Push 函数,如果堆栈为空,则创建第一个元素,如果有则在顶部添加新元素至少一个元素?

  • void * 需要用 malloc 分配?

【问题讨论】:

  • 显然我还创建了一个 Pop 函数来删除元素。

标签: c data-structures stack linked-list function-pointers


【解决方案1】:

首先,stackstack_l 不需要不同的标识符。现在,针对您的问题:

您的Push 函数与stack_lcopy 字段的类型不兼容。如果您想在 struct 中包含指向(成员)函数的指针以使其看起来像 C++,您仍然必须将对象传递给这些函数。

是的,您必须在某个地方实现您的功能,而这不能在struct stack 的定义范围内。这意味着您确实需要某种构造函数(如果您愿意,可以将其称为newStack)。您的构造函数必须至少初始化您的函数指针(如果您想保留它们)。如果您选择不保留这些函数指针,您可以按照您的建议将初始化代码很好地放入您的 push 例程中:

stack_l* stackPush(stack_l* head, void* content) {
  // head might be NULL, meaning the stack is "empty" or it might be an actual pointer
  // we don't care
  stack_l* const front = malloc(sizeof(stack_l));
  *front = (stack_l){.data = content, .next = head};
  return front;
}

请注意,您必须明确说明空堆栈是什么。因此,为了清楚起见,您可能需要实现一个构造函数:

stack_l* stackCreateEmpty() {
  retun NULL;
}

甚至可能是一个析构函数:

void stackDestroyEmpty(stack_l* s) {
  assert(s == NULL && "Tried to destroy non-empty stack.");
}

对于你的最后一个问题:正如你在上面看到的,你必须使用malloc 来获得空间来保存你的stack_l 对象,除此之外,你不需要为你的void* 成员分配额外的空间,因为它是stack_l 的一部分。

【讨论】:

  • 感谢您的评论。如果您将 void* 内容分配给具有 .data = content 的数据,我只是不明白是否需要我的函数副本。可能我不太了解。
  • @Kyrol:你不必这样做!正如我所说,这只是为了清楚起见,因此您的堆栈实现的用户有一些接口可以保留。关于copy:由于您的堆栈仅存储void 指针(它存储指针的文字值,而不是它指向的内容),您不必实现复制功能,您只需逐字复制指针。 然而,如果您确实想要复制指针指向的内容,则必须为 push 函数提供自定义复制参数,因为您的堆栈不可能知道您的内容'存储在里面。希望这对您有所帮助,否则请询问。
  • 好的,对于构造函数的误解,抱歉!关于copy: 好的,如果我写了具有最大泛型属性的函数,我就不需要那个函数了。但是如果我在 main 中调用 Push,并且我想在数据中存储一个 int(例如),我需要那个函数,不是吗?
  • 另一件事:为什么你将前面声明为const ??
  • @Kyrol:换句话说,如果您的stack 拥有数据,您必须提供一些复制数据的方法(即知道void* 的语义和大小的东西)论点指向)。但是,如果您希望堆栈仅跟踪指针本身,则不需要复制机制。关于front,我不打算更改指针,而且我有习惯,让一切尽可能不可变和本地化(可能是函数式编程的一些残余恋物癖)。它通常可以防止错误!
猜你喜欢
  • 2012-05-24
  • 2019-03-04
  • 2020-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-29
相关资源
最近更新 更多