没有数组POP的堆栈的递归实现无法正常工作

时间:2019-06-09 18:39:55

标签: c c99

我试图递归地实现LIFO堆栈,而不使用数组。该程序将字符串和整数作为输入,并具有一些命令-即push <int> pop empty topquit

pop之外的所有内容都对我有效,而pop仅对部分内容有效。如果只弹出一个int很好,但是除此之外,即使不是,它也会返回一个stack is empty。我知道为什么会发生这种情况,但不确定如何解决。

int stack(int top, int last) {  
  int m = read_symbol();
  if (m != READ_FAIL) {
    if (m == PUSH_SYMBOL) {
      int n = read_int();
      top = stack(n, top);
    } else if (m == POP_SYMBOL) {
      if (top == INT_MIN) {
        printf("pop error - stack is empty\n");
        top = stack(INT_MIN, INT_MIN);
      } else {
        top = stack(last, INT_MIN);
      }
    } else if (m == TOP_SYMBOL) {
      if (top == INT_MIN) {
        printf("top error - stack is empty\n");
      } else {
        printf("top - %d\n", top);
      }
      top = stack(top, last);
    } else if (m == EMPTY_SYMBOL) {
      if (top == INT_MIN) {
        printf("stack is empty\n");
      } else {
        printf("stack is not empty\n");
      }
      top = stack(top, last);
    } else if (m == QUIT_SYMBOL) {
      if (top != INT_MIN) {
        printf("quit error - stack is not empty\n");
        top = stack(top, last);
      } else {
        printf("goodbye\n");
      }
    }
  }
  return top;
}

递归返回top变量,因此一切正常。但是当我做类似的事情

push 1
push 2
push 3
top
pop
top
pop
top

返回的输出是

top - 3
top - 2
top error - stack is empty (SHOULD BE 1)
我尝试了各种不同的方法,但是我无法解决它。实际上,我只是为了解决此问题而引入了last参数,即使没有last,其余的实现也可以正常工作,但目前看来该参数有效,但仅适用于一个pop命令因为下一个递归级别将last设置为INT_MIN,如果再次使用top,则将其设置为pop,因此错误的stack is empty消息

任何指针或帮助将不胜感激。

编辑:INT_MIN是指C99 limits.h INT_MIN,它是-(2 ^ 32-1)

2 个答案:

答案 0 :(得分:0)

所以我想我已经解决了为什么要这样做的问题,首先,我稍微重写了您的函数,以便使用转换语句来实现紧凑性(这不是解决问题的方法):

int stack(int top, int last) {
  switch(read_symbol()) {

    // push n
    case PUSH_SYMBOL:  
      return stack(read_int(), top);

    // pop
    case POP_SYMBOL:
      if (top == INT_MIN) {
        printf("pop error - stack is empty\n");
        return stack(INT_MIN, INT_MIN);
      }

      return stack(last, INT_MIN);

    // top  
    case TOP_SYMBOL:
      if (top == INT_MIN)
        printf("top error - stack is empty\n");
      else
        printf("top - %d\n", top);

      return stack(top, last);

    // empty
    case EMPTY_SYMBOL: 
      if (top == INT_MIN)
        printf("stack is empty\n");
      else
        printf("stack is not empty\n");

      return stack(top, last);

    // quit
    case QUIT_SYMBOL:
      if (top != INT_MIN) {
        printf("quit error - stack is not empty\n");
        return stack(top, last);
      }

      printf("goodbye\n");

    case READ_FAIL: // error handling
    default:
      return top;
  }
}

然后我遵循了假定的调用堆栈:

stack(INT_MIN, INT_MIN) receives PUSH 1 -> stack(1, INT_MIN)
stack(1, INT_MIN)       receives PUSH 2 -> stack(1, 2)
stack(1, 2)             receives PUSH 3 -> stack(3, 2)
stack(3, 2)             receives TOP    -> stack(3, 2)
stack(3, 2)             receives POP    -> stack(2, INT_MIN)
stack(2, INT_MIN)       receives TOP    -> stack(2, INT_MIN)
stack(2, INT_MIN)       receives POP    -> stack(INT_MIN, INT_MIN)
stack(INT_MIN, INT_MIN) receives TOP    => ERROR

这里的问题非常简单,pop调用stack(x,INT_MIN),这在您的代码中意味着在弹出之后,堆栈的大小仅为1(或零)。不使用前一个调用堆栈中的数据。

答案 1 :(得分:-4)

在其他情况下,如果(m == POP_SYMBOL){}更改

if (top == INT_MIN) 

if (top < INT_MIN) 

,并让我知道它是否对您有用,因为变量“ top”的逻辑不正确(例如)我们可能会根据逻辑认为变量“ top”被破坏,而实际上它会在下一次迭代中被破坏。这样做对您不起作用,然后发布INT_MIN的值(可能是#define-ed值)