使用堆栈和二叉树构建表达式树c

时间:2012-12-08 12:17:13

标签: c stack binary-tree expression-trees

我得到一个包含运算符+, - ,*,/和括号的算术公式(可能会也可能不会改变运算符的自然优先级)。一个例子如下:a / b + f - (c + d)* e - a * c。并且我被要求使用堆栈(实现为链接列表)以跟踪操作数和运算符:我的程序应该如何工作的示例如下:

  • 读取a,推送操作数堆栈
  • 读取/,按下操作员堆栈
  • 读取b,按下操作数堆栈
  • 读取+:优先级低于/,因此:
    • 从操作数堆栈中弹出2个操作数(a和b)
    • pop / from operator stack
    • 创建子树并推送操作数堆栈
    • 运算符堆栈为空,因此按+上
  • 读取f,按下操作数堆栈
  • 读取 - :与+具有相同的优先级,因此:
    • 从操作数堆栈中弹出2个操作数
    • pop operator + from operator stack
    • 创建一个树,其中operator +作为根,两个操作数作为左右子项
    • 将创建的树的根推回操作数堆栈
    • 运算符堆栈为空,因此按下它

我难以理解的问题是如何区分操作数的优先级

这是我写的代码的不完整版本:

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

typedef struct btnode Btree;
typedef struct node s_Node;

struct btnode {
    char info; 
    Btree *left; 
    Btree *right;
};


struct node {
    char element;
    s_Node*next;
}; 

typedef struct{
    s_Node *top_stack;
} stack_t; 

int IsOperator(char c);

main () {
    FILE* fp;
    stack_t operands;
    stack_t operators;
    char c;
    operands=NewStack();
    operators=NewStack();
    fp= fopen ("Myfile.txt", "r");
    if (fp== NULL)
        printf ("   FILE COULD NOT BE OPENED");
    else
    {
        c=getc(fp);
        while (!feof (fp))
        {
            if ( c== ' ');
            else 
            {
                printf ("Here is your character: %c\n", c);
                if (IsOperator (c))
                    Push (c, &operands);
                else if ( isalpha (c))


            }
        c=getc(fp);
        }
    }
}

int IsOperator(char c)
{   
    switch(c)
    {
        case '+':
        case '-':
        case '/':
        case '*':
        return 1;
        default:
        return 0;
    }
} 

stack_t NewStack()
{
    stack_t *n_stack;
    n_stack=(stack_t*)malloc(sizeof(stack_t));
    n_stack->top_stack=NULL;
    return (*n_stack);  
}

int Push(char e, stack_t *q)
{       
    s_Node *nn;
    nn= (s_Node*)malloc(sizeof(s_Node));

    if(Full(*q))
    {
        printf("\n\t Stack is Full !! \n\n");
        return 0;   // return 0 if enstack NOT successful
    }
    else 
    { 
        nn->element=e; // Storing the elemnt read inside the the new node
        nn->next=q->top_stack; // Pointing the new node to the top of the stack
        q->top_stack=nn; // Changing the top of the stack
        return 1;
    }
}

提前谢谢!

1 个答案:

答案 0 :(得分:5)

对于您正在使用的算法,操作数没有优先权。但是在自下而上的shift-reduce解析器中,它确实具有优先权,因为@WhozCraig在下面这篇文章的评论中说。

操作数总是被推入操作数堆栈并将被弹出2并用运算符计算,然后再次作为单个操作数被推送到操作数堆栈。

对于你的公式: a / b + f - (c + d)* e - a * c

  • push到操作数堆栈
  • 操作数:a
  • <强>运算符

  • <强> /

  • push到运营商堆栈
  • 操作数:a
  • 运营商:/

  • <强> B'/强>

  • push到操作数堆栈
  • 操作数:a b
  • 运营商:/

  • <强> +

  • +&lt; = / - &gt; pop /,&amp; b - &gt; a / b - &gt;推送到操作数堆栈
  • +推送到运算符堆栈
  • 操作数 :( a / b)
  • 运营商:+

  • <强>˚F

  • 推送到操作数堆栈
  • 操作数 :( a / b)f
  • 运营商:+

  • <强> -

  • -&lt; = + - &gt; pop +,(a / b)&amp; f - &gt; (a / b) + f - &gt;推送到操作数堆栈
  • 操作数 :((a / b)+ f)
  • 运营商: -

  • (适用

  • 推送到运营商堆栈
  • 操作数 :((a / b)+ f)
  • 运营商: - (

  • <强> C

  • 推送到操作数堆栈
  • 操作数 :((a / b)+ f)c
  • 运营商: - (

  • <强> +

  • 推送到运营商堆栈
  • 操作数 :((a / b)+ f)c
  • 运营商: - (+

  • <强> d

  • 推送到操作数堆栈
  • 操作数 :((a / b)+ f)c d
  • 运营商: - (+

  • <强>)

  • 直到'('弹出,逐个弹出堆栈中的所有运算符并用2个操作数计算
  • - &GT; pop +,c &amp; d - &gt; c + d - &gt;推送到操作数堆栈
  • 操作数 :((a / b)+ f)(c + d)
  • 运营商: - (
  • - &GT; pop(,停止弹出操作符堆栈
  • 操作数 :((a / b)+ f)(c + d)
  • 运营商: -

  • *

  • *&gt; -推送到运营商堆栈
  • 操作数 :((a / b)+ f)(c + d)
  • 运营商: - *

  • <强>电子

  • *&gt; -推送到操作数堆栈
  • 操作数 :((a / b)+ f)(c + d)e
  • 运营商: - *

  • <强> -

  • -&lt; = * pop *,(c + d)&amp; e - &gt; (c + d)* e - &gt;推送到操作数堆栈
  • 操作数 :((a / b)+ f)((c + d)* e)
  • 运营商: -
  • -&lt; = - pop - ,((a / b)+ f)&amp; ((c + d)* e) - &gt; ((a / b)+ f) - ((c + d)* e) - &gt;推送到操作数堆栈
  • push - to operator stack
  • 操作数 :(((a / b)+ f) - ((c + d)* e))
  • 运营商: -

  • <强>一个

  • 推送到操作数堆栈
  • 操作数 :(((a / b)+ f) - ((c + d)* e))a
  • 运营商: -

  • *

  • *&gt; -推送到运营商堆栈
  • 操作数 :(((a / b)+ f) - ((c + d)* e))a
  • 运营商: - *

  • C

  • 推送到操作数堆栈
  • 操作数 :(((a / b)+ f) - ((c + d)* e))a c
  • 运营商: - *

  • 行尾

  • 逐个弹出堆栈中的所有运算符
  • pop *,a&amp; c - &gt; (a * c) - &gt;推送到操作数堆栈
  • 操作数 :(((a / b)+ f) - ((c + d)* e))(a * c)
  • 运营商: -
  • pop - ,((((a / b)+ f) - ((c + d)* e))&amp; (a * c) - &gt; (((a / b)+ f) - ((c + d)* e)) - (a * c) - &gt;推送到操作数堆栈
  • 操作数:((((((a / b)+ f) - ((c + d)* e)) - (a * c))
  • 操作

结果:(((((a / b)+ f) - ((c + d)* e)) - (a * c))