数据结构期末复习·表达式树(重写)

表达式树(expression tree):

我们已经知道了在计算机中用后缀表达式和栈来计算中缀表达式的值。在计算机中还有一种方式是利用表达式树来计算表达式的值。表达式树是这样一种树,其根节点为操作符,非根节点为操作数,对其进行后序遍历将计算表达式的值。由后缀表达式生成表达式树的方法如下:

l  读入一个符号:

l  如果是操作数,则建立一个单节点树并将指向他的指针推入栈中;

l  如果是运算符,就从栈中弹出指向两棵树T1和T2的指针(T1先弹出)并形成一棵新树,树根为该运算符,它的左、右子树分别指向T2和T1,然后将新树的指针压入栈中。

例如输入的后缀表达为:

    ab+cde+**

则生成的表达式树为:

 

这题属于,思路不麻烦,操作麻烦的类型。首先需要使用栈,将中缀表达式转化为后缀表达式,然后需要使用树和树的栈将后缀表达式转化为表达式树。

1·中缀转后缀

遍历中缀表达式,如果读到了数字,就直接输出,如果读到符号则进行如下操作:

        如果是 ( : 直接入栈

        如果是 ) : 将栈顶元素输出,直到遇到 ( 为止

        如果是 + - : 其优先级低于栈中的+ - * /,所以要一直将栈顶元素输出直到遇到(或者空栈为止。最后把其加到栈中。

        如果是 * / :其优先级只比栈中的* /低,只有在遇到栈顶是* / 的时候将其输出,最后入栈、

        如果是 = :标志表达式结束

用到的函数:

char stack[MAXSIZE];
int top = -1;

void push(char c)
{
    stack[++top] = c;
    return;
}

char pop()
{
    char tmp = stack[top];
    top--;
    return tmp;
}

char get_top()
{
    return stack[top];
}

int is_empty()
{
    if (top >= 0)
        return 0;
    return 1;
}

char polish[MAXSIZE];
int pcnt = 0;

int is_op(char c)
{
    if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')')
        return 1;
    return 0;
}

void process_op(char c)
{
    if (c == '(')
    {
        push(c);
        return;
    }
    if (c == ')')
    {
        while (!is_empty() && get_top() != '(')
        {
            polish[pcnt++] = pop();
        }
        pop();
        return;
    }
    if (c == '+' || c == '-')
    {
        while (!is_empty() && get_top() != '(')
        {
            polish[pcnt++] = pop();
        }
        push(c);
        return;
    }
    if (c == '*' || c == '/')
    {
        while (!is_empty() && (get_top() == '*' || get_top() == '/'))
        {
            polish[pcnt++] = pop();
        }
        push(c);
    }
}

求后缀函数:

void make_polish()
{
    char c;
    int flag = 0;
    while (scanf("%c", &c))
    {
        if (flag == 1 && !(c >= '0' && c <= '9'))
            polish[pcnt++] = ' ';
        if (c == ' ')
        {
            flag = 0;
            continue;
        } //space
        else if (c >= '0' && c <= '9')
        {
            flag = 1;
            polish[pcnt++] = c;
        } ///number
        else if (is_op(c))
        {
            flag = 0;
            process_op(c);
        }
        else if (c == '=')
        {
            break;
        }
    }
    while (!is_empty())
    {
        polish[pcnt++] = pop();
    }
}

2·用后缀表达式求表达式树

此处需要用一个栈存储树的指针,用顺序栈即可。

typedef struct tree_node
{
    char symb[20];
    struct tree_node *left, *right;
} tnode;

tnode *make_tree()
{
    tnode *tstack[MAXSIZE];
    int ttop = -1;
    for (int i = 0; i < pcnt; i++)
    {
        char tmp[20];
        int tcnt = 0;
        if (polish[i] >= '0' && polish[i] <= '9')
        {
            tmp[tcnt++] = polish[i++];
            while (polish[i] >= '0' && polish[i] <= '9')
            {
                tmp[tcnt++] = polish[i++];
            }
            tmp[tcnt] = '\0';

            tnode *tmpnode = (tnode *)malloc(sizeof(tnode));
            tmpnode->left = tmpnode->right = NULL;
            strcpy(tmpnode->symb, tmp);

            tstack[++ttop] = tmpnode;
        }
        else if (is_op(polish[i]))
        {
            tnode *tmpnode = (tnode *)malloc(sizeof(tnode));
            tmpnode->left = tmpnode->right = NULL;
            tmpnode->symb[0] = polish[i];
            tmpnode->symb[1] = 0;

            tnode *t1 = tstack[ttop];
            ttop--;
            tnode *t2 = tstack[ttop];
            ttop--;
            tmpnode->left = t2;
            tmpnode->right = t1;

            tstack[++ttop] = tmpnode;
        }
    }
    return tstack[0];
}

void in_traverse(tnode *p)
{
    if (p->left != NULL)
        in_traverse(p->left);

    puts(p->symb);

    if (p->right != NULL)
        in_traverse(p->right);
}

void s_traverse(tnode *p)
{
    if (p->left != NULL)
        s_traverse(p->left);

    if (p->right != NULL)
        s_traverse(p->right);

    printf("%s ", p->symb);
}

3·完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSIZE 200

char stack[MAXSIZE];
int top = -1;

void push(char c)
{
    stack[++top] = c;
    return;
}

char pop()
{
    char tmp = stack[top];
    top--;
    return tmp;
}

char get_top()
{
    return stack[top];
}

int is_empty()
{
    if (top >= 0)
        return 0;
    return 1;
}

char polish[MAXSIZE];
int pcnt = 0;

int is_op(char c)
{
    if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')')
        return 1;
    return 0;
}

void process_op(char c)
{
    if (c == '(')
    {
        push(c);
        return;
    }
    if (c == ')')
    {
        while (!is_empty() && get_top() != '(')
        {
            polish[pcnt++] = pop();
        }
        pop();
        return;
    }
    if (c == '+' || c == '-')
    {
        while (!is_empty() && get_top() != '(')
        {
            polish[pcnt++] = pop();
        }
        push(c);
        return;
    }
    if (c == '*' || c == '/')
    {
        while (!is_empty() && (get_top() == '*' || get_top() == '/'))
        {
            polish[pcnt++] = pop();
        }
        push(c);
    }
}

void make_polish()
{
    char c;
    int flag = 0;
    while (scanf("%c", &c))
    {
        if (flag == 1 && !(c >= '0' && c <= '9'))
            polish[pcnt++] = ' ';
        if (c == ' ')
        {
            flag = 0;
            continue;
        } //space
        else if (c >= '0' && c <= '9')
        {
            flag = 1;
            polish[pcnt++] = c;
        } ///number
        else if (is_op(c))
        {
            flag = 0;
            process_op(c);
        }
        else if (c == '=')
        {
            break;
        }
    }
    while (!is_empty())
    {
        polish[pcnt++] = pop();
    }
}

typedef struct tree_node
{
    char symb[20];
    struct tree_node *left, *right;
} tnode;

tnode *make_tree()
{
    tnode *tstack[MAXSIZE];
    int ttop = -1;
    for (int i = 0; i < pcnt; i++)
    {
        char tmp[20];
        int tcnt = 0;
        if (polish[i] >= '0' && polish[i] <= '9')
        {
            tmp[tcnt++] = polish[i++];
            while (polish[i] >= '0' && polish[i] <= '9')
            {
                tmp[tcnt++] = polish[i++];
            }
            tmp[tcnt] = '\0';

            tnode *tmpnode = (tnode *)malloc(sizeof(tnode));
            tmpnode->left = tmpnode->right = NULL;
            strcpy(tmpnode->symb, tmp);

            tstack[++ttop] = tmpnode;
        }
        else if (is_op(polish[i]))
        {
            tnode *tmpnode = (tnode *)malloc(sizeof(tnode));
            tmpnode->left = tmpnode->right = NULL;
            tmpnode->symb[0] = polish[i];
            tmpnode->symb[1] = 0;

            tnode *t1 = tstack[ttop];
            ttop--;
            tnode *t2 = tstack[ttop];
            ttop--;
            tmpnode->left = t2;
            tmpnode->right = t1;

            tstack[++ttop] = tmpnode;
        }
    }
    return tstack[0];
}

void in_traverse(tnode *p)
{
    if (p->left != NULL)
        in_traverse(p->left);

    puts(p->symb);

    if (p->right != NULL)
        in_traverse(p->right);
}

void s_traverse(tnode *p)
{
    if (p->left != NULL)
        s_traverse(p->left);

    if (p->right != NULL)
        s_traverse(p->right);

    printf("%s ", p->symb);
}

int main()
{
    make_polish();
    //for(int i=0;i<pcnt;i++) printf("%c",polish[i]);
    tnode *root = make_tree();
    s_traverse(root);
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值