【问题标题】:C Programming StackC 编程堆栈
【发布时间】:2014-04-22 21:36:55
【问题描述】:

我目前正在处理堆栈。我应该使用以下结构和函数原型:

typedef struct node_{
    char data;
    struct node_ *next;
}node;

typedef struct stack_{
    unsigned int size;
    node* stack;
}stack;

stack* create_stack();
void   push(stack* s, char val);

这是我的 create_stack() 和 push() 的实际代码:

stack* create_stack()
{
    stack *stack;
    stack = malloc(sizeof(stack));
    stack->size = 0;
    stack->stack = NULL;
    return stack;
}

void push(stack* s, char val)
{
    stack *newStack;
    newStack = create_stack();
    newStack->stack->data = val;
    newStack->stack = s->stack;
    s = newStack;
}

当我尝试将 char val 存储到 newStack->stack->data 时出现分段错误。这怎么行不通?我需要做什么才能使这个堆栈在顶部???

【问题讨论】:

  • 很明显,newStack->stackNULL,但您使用 ->data 取消引用它。
  • 您肯定不想在每次推送时创建一个新堆栈,不是吗?
  • 你是在堆还是栈上分配?它看起来像堆
  • @GIJoe 在堆栈上分配和创建堆栈是完全不同的事情
  • @vlad_tepesch 堆栈是一个概念,而不是特定的实现。如果元素在头部被压入和弹出,则单链表会形成一个很好的堆栈。此外,这听起来像是需要 OP 才能使用此结构的分配,因此推荐一个数组也无济于事。

标签: c segmentation-fault stack


【解决方案1】:

推送功能错误。

void push(stack* s, char val)
{
    stack *newStack;
    newStack = create_stack(); /* new stack created, why not work on the existing one ? */
    newStack->stack->data = val; /* you're writing to a NULL pointer */
    newStack->stack = s->stack;
    s = newStack; /* this will not be visible from outside the function */
}

首先,您尝试为该函数的每次调用重新创建一个新堆栈,这当然不是预期的。

如果您尝试修改 s 的值,它将无法从函数外部看到,并且您仍将拥有原始堆栈。

然后,您正在访问 stack->data 成员,即使 stack 尚未分配空间(因为您将其设置为 NULL)。你实际上是在它之后设置的,这就是它崩溃的原因,很可能。

你可能想做这样的事情:

void push(stack* s, char val)
{
    node * n;

    /* go to the end of the "stack" */
    n = s->stack;
    while (n != NULL) {
        n = n->next;
    }

    /* allocate memory for a new node */
    n = malloc(sizeof(node));

    /* initialize node */
    n->data = val;
    n->next = NULL;

    /* increment stack size */
    s->size++;
}

如前所述,这只是一个单链表,不适合堆栈,因为它现在存在,您必须按照节点指针到达最后一个元素,这使得 push 和 pop操作 O(N)。

更快的实现如下所示:

void push(stack* s, char val)
{
    node * first_node, * new_node;
    first_node = s->stack;

    /* allocate memory for a new node */
    new_node = malloc(sizeof(node));

    /* initialize node */
    new_node->data = val;
    new_node->next = first_node;

    /* increment stack size */
    s->stack = new_node;
    s->size++;
}

栈顶始终是第一个节点,性能O(1)。

【讨论】:

  • 您可能认为s 可能为NULL。此外,您可能会考虑,虽然推到最后可以工作,但性能是 O(n),而如果您愿意将签名更改为 stack *push(stack *s, char val); 并返回新的头,则可以通过推到头部来获得 O(1)指针。
  • @mah 同意。虽然,这里只需要改变栈中的头节点,而不是栈本身。我承认最初的命名有点混乱:)
【解决方案2】:

按照您的代码....

stack *newStack = create_stack();   // in push()
    newStack = malloc(sizeof(stack)); // in create_stack()
    newStack->stack = NULL; // in create_stack()
newStack->stack->data = val; // in push()... this is where you crash.

【讨论】:

    【解决方案3】:

    因为newStack->stack 是一个空指针。您的 create_stack() 函数将其设置为 NULL,然后您取消引用它。你必须在某处分配一个struct node

    此代码还存在一些可能导致问题的可读性问题。您将变量命名为与其类型相同的名称,这非常令人困惑。考虑使用其他命名模式,例如 stack_t 用于类型,stack 用于变量名称。

    【讨论】:

      猜你喜欢
      • 2017-08-15
      • 2013-05-26
      • 2020-09-13
      • 1970-01-01
      • 1970-01-01
      • 2019-08-11
      • 2011-07-01
      • 1970-01-01
      • 2012-01-18
      相关资源
      最近更新 更多