数据结构之"逆波兰树"求解算式 [a + b * (c - d) - e / f]

逆波兰树加引号是因为这是我给她起的名字。。莫名喜感。一个算式的”波兰树“的构建并不是唯一的,这个得看个人的选择,选择括号外面的加号或减号作为树根。然后将剩下的算式依次拆分。将算术符号用子二叉树的根节点代替,数值用二叉树的左右子节点代替,这样就得到了一棵所求算式的波兰树,然后将其变化为扩充二叉树,得出她的前序遍历序列。然后通过一个创建波兰树的函数   Get_bolantree();,从而得到一个由head 头指针所代表的二叉树,再通过后序优先次序遍历函数,在便利的过程中通过一个栈求出最终结果。。

我想着重说的是,整棵二叉树的连接是通过指针的形式连接的。。所以说在main();函数里要定义一个指向结构体名的指针。

刚开始做我是和创建单链表一样用结构体名创建了一个结构体的对象,但是Get_bolantree();中需要对指针的左或者右指针进行操作。所以说传参时要传指针的地址,然后形参则是用一个二级指针接收。在函数中的操作一定要记住是对treenode head; 这个指针进行操作的。所以说对data赋值时需要先“取值”再赋值。递归同理。(C语言思想)。

如果是用C++思想做的话,传实参时直接传对象就可以,但形参接收的时候就要改成引用的形式。。而且在Get _bolantree();中就可以直接用引用名对指针进行操作了。。。

主要的还是得好好理解一下指针以及二级指针的操作。

运行结果如下:

C思想下的操作:

请输入构建[a + b * (c – d) – e / f]波兰树的字符串:

-+ann*bnn-cnndnn/ennfnn

请输入字母及其所代表的数值:

a 1
b 2
c 3
d 4
e 6
f 3

该波兰树的后序优先次序、也就是逆波兰式为:

abcd-*+ef/-

最终结果为: -3

内存已被成功释放。

C++思想下的操作:

请输入构建[a + b * (c – d) – e / f]波兰树的字符串:

-+ann*bnn-cnndnn/ennfnn

请输入字母及其所代表的数值:

a 1
b 2
c 3
d 4
e 6
f 3

该波兰树的后序优先次序、也就是逆波兰式为:

abcd-*+ef/-

最终结果为: -3

Process returned 0 (0x0)   execution time : 39.540 s
Press any key to continue.

#include <iostream>
#include <cstdio>
#include <string>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <map>
#include <queue>
#include <stack>
#define INF 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a));
#define For(a,b) for(int i = a;i<b;i++)
#define LL long long
#define MAX_N 100010
using namespace std;
typedef struct treen *treenode;
typedef int Status;
struct treen
{
    treenode left;
    treenode right;
    treenode father;
    char data;
};
map<char,int> mp;
void postorder(treenode head,Status *ans)
{
    stack<int> ch;
    stack<treenode> sta;
    treenode p;
    p = head;
    printf("该波兰树的后序优先次序、也就是逆波兰式为:\n\n");
    while(p != nullptr || !sta.empty())
    {
        while(p != nullptr)
        {
            sta.push(p);
            p = p->left ? p->left : p->right;
        }
        p = sta.top();
        sta.pop();
        printf("%c",p->data);
        if(isalpha(p->data))
        {
            char e = p->data;
            int num = mp[e];
            ch.push(num);
        }
        else
        {
            int getc = 0;
            int num1 = ch.top();
            ch.pop();
            int num2 = ch.top();
            ch.pop();
            if(p->data == '+')
                getc = num1 + num2;
            else if(p->data == '-')
                getc = num2 - num1;
            else if(p->data == '*')
                getc = num2 * num1;
            else if(p->data == '/')
                getc = num2 / num1;
            ch.push(getc);
        }
        if(!sta.empty() && sta.top()->left == p)
            p = sta.top()->right;
        else
            p = nullptr;
    }
    printf("\n\n");
    *ans = ch.top();
    ch.pop();
    return ;
}
Status Get_bolantree_C(treenode *p)
{
    char s_c;
    scanf("%c",&s_c);
    //cout<<s_c<<endl;
    if(s_c == 'n') *p = nullptr;
    else
    {
        *p = (treenode)malloc(sizeof(treen));
        if(!(*p)) return 0;
        (*p)->data = s_c;
        Get_bolantree_C(& ((*p)->left));
        Get_bolantree_C(& ((*p)->right));
    }
    return 0;
}
Status Get_bolantree_CPP(treenode &q)
{
    char s;
    scanf("%c",&s);
    /*
        本来想着c与c++写两个程序来着。
        觉得麻烦,就放在了一起。我要感谢这个输出1的操作。。
        刚开始输出所输入的字符还没发现错误。(纠结的我都去打游戏了,蓝瘦啊)。
        改成输出1以后,我发现还没有输入字符呢,她自己就输出了一个1。
        让我想到了检验上面C的样例之后的   回车。回车。回车 ......
        香菇......
    */
    //cout<<1<<endl;
    if(s == 'n') q = nullptr;
    else
    {
        q = (treenode)malloc(sizeof(treen));
        if(!q) return 0;
        q->data = s;
        Get_bolantree_CPP(q->left);
        Get_bolantree_CPP(q->right);
    }
    return 1;
}
bool de_bolan(treenode head)
{
    treenode p = head;
    stack<treenode> st;
    if(p == nullptr) return false;
    else
        st.push(p);
    while(!st.empty())
    {
        treenode dele = st.top();
        st.pop();
        if(dele->left != nullptr)
        {
            st.push(dele->left);
        }
        if(dele->right != nullptr)
        {
            st.push(dele->right);
        }
        delete dele;
    }
    if(st.empty()) return true;
    return false;
}
int main()
{

    treenode head_c = nullptr;
    printf("C思想下的操作:\n\n");
    printf("请输入构建[a + b * (c - d) - e / f]波兰树的字符串:\n\n");
    Get_bolantree_C(&head_c);
    printf("\n");
    char ss_c[5];
    int val_c= 0;
    //cout<<head->data<<endl;
    printf("请输入字母及其所代表的数值:\n\n");
    for(int i = 1; i<=6; i++)
    {
        scanf("%s %d",ss_c,&val_c);
        mp[ss_c[0]] = val_c;
    }
    printf("\n");
    int res_c;
    postorder(head_c,&res_c);
    printf("最终结果为: %d\n\n",res_c);
    if(de_bolan(head_c))
        cout<<"内存已被成功释放。"<<endl<<endl;
    else
        cout<<"内存没有被成功释放或者说没有内存的占用。"<<endl<<endl;
    mp.clear();
    getchar();//吃上面剩下的回车。。不然下面多了一个'\n'没法检验...
    treenode head_cpp = nullptr;
    printf("C++思想下的操作:\n\n");
    printf("请输入构建[a + b * (c - d) - e / f]波兰树的字符串:\n\n");
    Get_bolantree_CPP(head_cpp);
    printf("\n");
    char ss_cpp[5];
    int val_cpp = 0;
    //cout<<head->data<<endl;
    printf("请输入字母及其所代表的数值:\n\n");
    for(int i = 1; i<=6; i++)
    {
        scanf("%s %d",ss_cpp,&val_cpp);
        mp[ss_cpp[0]] = val_cpp;
    }
    printf("\n");
    int res_cpp;
    postorder(head_cpp,&res_cpp);
    printf("最终结果为: %d\n",res_cpp);
    return 0;
}

/*

2016.10.28

测试样例:

-+ann*bnn-cnndnn/ennfnn

a 1
b 2
c 3
d 4
e 6
f 3

*/

    原文作者:B树
    原文地址: https://blog.csdn.net/sxtopc/article/details/52957986
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞