无法将元素推入堆栈

时间:2015-05-04 21:27:52

标签: c

我正在开发一个项目,我必须在反向抛光表示法中使用表达式,将整数和运算符压入堆栈,然后在将它们插入二叉搜索树时将它们从堆栈中弹出。 / p>

#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>

struct snode 
{
  int datum;
  struct snode* bottom;
};

struct tnode
{
  int datum;
  struct tnode* left;
  struct tnode*right;
};

struct snode* 
push(struct snode* stack, int x) {
  struct snode *S = (struct snode*)malloc(sizeof(struct snode));
  S->datum = x;
  S->bottom = stack;
  return S;
}

struct snode* pop(struct snode* stack) {
  struct snode *S;
  if (stack == NULL)
    return NULL;
  S = stack->bottom;
  free(stack);
  return S;
}

int
peek(struct snode* stack){
  return stack->datum;
}


struct tnode*
create_node(int x){
  struct tnode* tmp;
  tmp = (struct tnode*)malloc(sizeof(struct tnode));
  tmp->datum = x;
  tmp->right = NULL;
  tmp->left = NULL;
  return tmp;
}

void
print_table(struct tnode *AST){
  if(AST !=NULL){
    print_table(AST->left);
    printf("%d ", AST->datum);
    print_table(AST->right);
  }
}

struct tnode*
build_tree(struct snode *S)
{
  struct tnode* root;
  if (S==NULL){
    return NULL;
  }else{
    int top = peek(S);
    if (top == 65 || top == 83 || top == 88 || top == 68 || top == 77){
      return create_node(top);
    }else{
      root= create_node(top);
      root->right = build_tree(pop(S));
      root->left = build_tree(pop(S));
      return root;
    }
  }
}

int
main(int argc, const char *argv[])
{

  int i = 1;
  struct tnode *tree = NULL;
  struct snode *stack = NULL;


  while (argv[i]!= NULL){
    stack = push(stack, argv[i][0]);
    i++;
  }

 tree =  build_tree(stack);
 print_table(tree);

 return EXIT_SUCCESS;
}

我觉得这应该有效。一切都清洁干净。我通过说

来运行它
./project 5 4 A

出来的是

135208 135224 135208 135240 135208 135224 135208 0 135208 135224 135208 52 0 53 0 

什么时候应该

4 65 5

我认为这是因为我将元素推入堆栈的方式。

编辑:

我初始化了i,因此我= 1。

这是我得到的结果。

134480 134496 134480 0 5 4 5 

EDIT2:

我决定摆脱atol(argv [i])并将其更改为argv [i] [0]。 见代码。

现在我的出局就是

65

1 个答案:

答案 0 :(得分:0)

终于弄清楚发生了什么!

以下是新修改的部分,可让您的代码正常工作(请查看// <== EDIT评论):

struct tnode*
build_tree(struct snode *S)
{

  struct tnode* root;
  if (S == NULL)
    return NULL;

  int top = peek(S);

  if (top == 65 || top == 83 || top == 88 || top == 68 || top == 77)
  {
     root = create_node(top);
     S = pop(S); // <== EDIT
     root->right = build_tree(S);


     S = pop(S); // <== EDIT
     root->left = build_tree(S);
     return root;
  } 

  root= create_node(top);

  return root;
}

int
main(int argc, const char *argv[])
{

  int i = 1;
  struct tnode *tree = NULL;
  struct snode *stack = NULL;

  int value = 0;
  while (argv[i]!= NULL)
  {
    if ((value = atoi(argv[i])) == 0) // <== EDIT
        value = argv[i][0];
    stack = push(stack, value);
    i++;
  }


 tree =  build_tree(stack);
 print_table(tree);

 return EXIT_SUCCESS;
}

我注意到有3个问题导致了你的价值。

第一期: 您要查找的结果是4 65 5,这意味着如果输入是数字(4,5等),则必须使用atoi()的结果。如果输入不是数字,则必须使用ASCII值。

为此,我使用了以下几行:

    if ((value = atoi(argv[i])) == 0) // <== EDIT
        value = argv[i][0];
    stack = push(stack, value);

atoi()的实施中,当转化失败时,atoi()会返回0。因此,我检查赋值的值:如果atoi()返回0,则使用ASCII值。

第二期: 你遇到的第二个问题是build_tree()函数似乎有错误的逻辑。由于这是一棵树,我希望字符A是根,数字4和5是分支,如下所示:

  A
 / \
4   5

你的逻辑似乎扭转了局面,你的设置方式,数字成为根值,字母是分支。扭转你的逻辑解决了这个问题:

  int top = peek(S);

  if (top == 65 || top == 83 || top == 88 || top == 68 || top == 77)
  {
     root = create_node(top);
     S = pop(S); // <== EDIT
     root->right = build_tree(S);


     S = pop(S); // <== EDIT
     root->left = build_tree(S);
     return root;
  } 

  root= create_node(top);

  return root;

上一期: 这是一个很大的问题。致电build_tree()时,您会直接传递pop()的结果。问题在于,您没有将新的根值影响到S。因此:

  1. 第一次调用build_tree(pop(S))时,最终会释放S的内存空间。

  2. 稍后,当您第二次致电build_tree(pop(S))时,您最终会在初始值(早期释放的值)上调用pop(S)

  3. 解决方案是在您致电S时重新分配pop(),然后再致电build_tree(S)

         S = pop(S); // <== EDIT
         root->right = build_tree(S);
    
    
         S = pop(S); // <== EDIT
         root->left = build_tree(S);
    

    TL; DR: 我重新格式化了你的代码,现在应该解决这个问题。复制粘贴,你应该很好。