后缀表达式建立二叉树并遍历测试

本文介绍如何使用后缀表达式构建二叉树,并通过递归实现先序、中序和后序遍历。文章详细解释了构建过程及遍历算法,展示了如何将后缀表达式转换为二叉树并进行遍历,最后给出测试用例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/* 后缀表达式建立二叉树并遍历测试
 * 原理:
   扫描后缀表达式,遇到操作数时即建立单二叉树节点, 左右指针都为空,放入栈中, 遇到
   操作符时也建立单二叉树节点, 但是节点的左右指针需要取栈顶元素,即此时依次从栈顶
   出栈的元素分别作为当前扫描节点的右,左子树(注意顺序), 之后也将该节点进栈, 循环
   该步骤直到后缀表达式结尾, 此时栈顶元素即为建立好的二叉树的根节点.

   可以用二叉树的逆波兰式与原始表达式对比验证, 同时可以打印中序遍历, 得到自然表达式.
   后缀表达式测试用例: "ab+cde+**"
 */

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

typedef struct _tBINARY_TREE_
{
    int value;
    _tBINARY_TREE_ *lchild;
    _tBINARY_TREE_ *rchild;
}tBINARY_TREE;

static bool is_operator(const char c);
static int priority_com(int operator1, int operator2);

static tBINARY_TREE *suffix_express_create_binary_tree(const char *suffix_express)
{
    std::stack<tBINARY_TREE *> operator_stack;

    const char *p = suffix_express;
    while (*p != '\0')
    {
        if (!is_operator(*p))
        {
            tBINARY_TREE *ptree = new tBINARY_TREE;
            ptree->value = *p;
            ptree->lchild = NULL;
            ptree->rchild = NULL;
            operator_stack.push(ptree);
        }
        else
        {
            tBINARY_TREE *ptree = new tBINARY_TREE;
            ptree->value = *p;
            ptree->lchild = NULL;
            ptree->rchild = NULL;
            if (!operator_stack.empty())
            {
                ptree->rchild = operator_stack.top();
                operator_stack.pop();
            }
            if (!operator_stack.empty())
            {
                ptree->lchild = operator_stack.top();
                operator_stack.pop();
            }
            if (ptree->lchild == NULL || ptree->rchild == NULL)
            {
                printf("express is invalid, exit.\n");
                exit(-2);
            }
            operator_stack.push(ptree);
        }
        ++p;
    }
    if (operator_stack.empty())
    {
        printf("internal error.\n");
        exit(-1);
    }
    tBINARY_TREE *pRoot = operator_stack.top();
    operator_stack.pop();
    return pRoot;
}

//递归先序遍历
void pre_order_reserver_tree(tBINARY_TREE *pTree)
{
    if (pTree != NULL)
    {
        printf("%c", pTree->value);
        pre_order_reserver_tree(pTree->lchild);
        pre_order_reserver_tree(pTree->rchild);
    }
    return;
}

//递归中序遍历
static void in_order_traverser(tBINARY_TREE *pTree)
{
    int flag_l = 0, flag_r = 0;
    if (pTree != NULL)
    {
        int ret;
        if (pTree->lchild != NULL) //非叶子节点
        {
            ret = priority_com(pTree->value, pTree->lchild->value);
            if (ret < 0)
            {
                printf("2. invalid express, exit.\n");
                exit(-1);
            }
            else if (ret == 1) //当前节点的优先级大于左子树, 左子树需要加括号, 防止误解
            {
                printf("%c", '(');
                flag_l = 1;
            }
        }
        in_order_traverser(pTree->lchild);
        if (flag_l == 1)
        {
            printf("%c", ')');
            flag_l = 0;
        }

        printf("%c", pTree->value);

        if (pTree->rchild != NULL) //非叶子结点
        {
            ret = priority_com(pTree->value, pTree->rchild->value);
            if (ret < 0)
            {
                printf("3. invalid express, exit.");
                exit(-1);
            }
            else if (ret == 1)//当前节点的优先级大于右子树, 又子树需要加括号, 防误解
            {
                printf("%c", '(');
                flag_r = 1;
            }
        }
        in_order_traverser(pTree->rchild);
        if (flag_r == 1)
        {
            printf("%c", ')');
            flag_r = 0;
        }
    }
 }


//递归后序遍历
void post_order_reserver_tree(tBINARY_TREE *pTree)
{
    if (pTree != NULL)
    {
        post_order_reserver_tree(pTree->lchild);
        post_order_reserver_tree(pTree->rchild);
        printf("%c", pTree->value);
    }
    return;
}

void destroy_binary_tree(tBINARY_TREE *pTree)
{
    if (pTree != NULL)
    {
        destroy_binary_tree(pTree->lchild);
        destroy_binary_tree(pTree->rchild);
        delete pTree; pTree = NULL;
    }
    return;
}

static bool is_operator(const char c)
{
    if (c == '+'
        || c == '-'
        || c == '*'
        || c == '/'
        || c == '('
        || c == ')')
    return true;
    return false;
}

static int priority_com(int operator1, int operator2)
{
    if (operator1 == '*' || operator1 == '/')
    {
        if (operator2 == '+' || operator2 == '-')
            return 1;
    }
    return 0;
}


int main(void)
{
    const char suffix_express[] = "ab+cde+**";
    tBINARY_TREE *pTree = suffix_express_create_binary_tree(suffix_express);
    printf("old suffix express:%s\n", suffix_express);
    printf("new suffix express:");
    post_order_reserver_tree(pTree);
    printf("\nnew prefix express:");
    pre_order_reserver_tree(pTree);
    printf("\nnew  infix express:");
    in_order_traverser(pTree);
    printf("\n");
    destroy_binary_tree(pTree);
    return 0;
}

测试结果:

old suffix express:ab+cde+**
new suffix express:ab+cde+**
new prefix express:*+ab*c+de
new  infix express:(a+b)*c*(d+e)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值