二叉树,波兰式,逆波兰式,二叉树的遍历

来源:互联网 发布:java 线程池 合并task 编辑:程序博客网 时间:2024/05/22 13:32

原博地址:http://lib.csdn.net/article/datastructure/15516

转载供以后研究

中缀表达式与后缀表达式

中缀表达式(或中缀记法)是一个通用的算术或逻辑公式表示方法, 操作符是以中缀形式处于操作数的中间(例:3 + 4),中缀表达式是人们常用的算术表示方法。
前缀表达式(例:+ 3 4)或后缀表达式(例:3 4 +)相比,中缀表达式不容易被计算机解析,但仍被许多程序语言使用,因为它符合人们的普遍用法。
与前缀或后缀记法不同的是,中缀记法中括号是必需的。计算过程中必须用括号将操作符和对应的操作数括起来,用于指示运算的次序。
例:
(1)8+4-6*2用后缀表达式表示为:
62*84+-
(2)2*(3+5)-4+7/1用后缀表达式表示为:
35+2*71/4-+

来源: <http://baike.baidu.com/link?url=mAvuPrzHlCr8qOnfwDTbaZON5ZhK69eZfrB0LbND917ZUJXtqrQYEg9tampLYGOEGgLfyTVisO-CjDC5TzZPsq>

 中缀表达式转为后缀表达式(又称逆波兰表达式)的方法

逆波兰算法-栈实现

将一个普通的中序表达式转换为逆波兰表达式的一般算法是:
首先需要分配2个栈,一个作为临时存储运算符的栈S1(含一个结束符号),一个作为输入逆波兰式的栈S2(空栈),S1栈可先放入优先级最低的运算符#,注意,中缀式应以此最低优先级的运算符结束。可指定其他字符,不一定非#不可。从中缀式的左端开始取字符,逐序进行如下步骤:
(1)若取出的字符是操作数,则分析出完整的运算数,该操作数直接送入S2栈
(2)若取出的字符是运算符,则将该运算符与S1栈栈顶元素比较,如果该运算符优先级大于S1栈栈顶运算符优先级,则将该运算符进S1栈,否则,将S1栈的栈顶运算符弹出,送入S2栈中,直至S1栈栈顶运算符低于(不包括等于)该运算符优先级,则将该运算符送入S1栈。
(3)若取出的字符是“(”,则直接送入S1栈底。
(4)若取出的字符是“)”,则将距离S1栈栈底最近的“(”之间的运算符,逐个出栈,依次送入S2栈,此时抛弃“(”。
(5)重复上面的1~4步,直至处理完所有的输入字符
(6)若取出的字符是“#”,则将S1栈内所有运算符(不包括“#”),逐个出栈,依次送入S2栈。
完成以上步骤,S2栈便为逆波兰式输出结果。不过S2应做一下逆序处理。便可以按照逆波兰式的计算方法计算了!

//#include<iostream>#include<stdlib.h>#include<stdio.h>#include<stack>#include<math.h>#include<string.h>#definemax100usingnamespacestd;charex[max];/*存储后缀表达式*/ void trans(){/*将算术表达式转化为后缀表达式*/    charstr[max];/*存储原算术表达式*/    charstack[max];/*作为栈使用*/    charch;    intsum,i,j,t,top=0;    printf("*****************************************\n");    printf("*输入一个求值的表达式,以#结束。*\n");    printf("******************************************\n");    printf("算数表达式:");    i=0;/*获取用户输入的表达式*/    do{        i++;        //cin>>str[i];/*此步我用的是C++C语言的话在后面之所以用这个有一点区别都*/        scanf("%c",&str[i]);    }while(str[i]!='#'&&i!=max);    sum=i;    t=1;i=1;    ch=str[i];i++;    //    while(ch!='#')    {        switch(ch)        {        case'(':/*判定为左括号*/            top++;stack[top]=ch;            break;        case')':/*判定为右括号*/            while(stack[top]!='(')            {                ex[t]=stack[top];top--;t++;            }            top--;            break;        case'+':/*判定为加减号*/        case'-':            while(top!=0&&stack[top]!='(')            {                ex[t]=stack[top];                top--;                t++;            }            top++;            stack[top]=ch;            break;        case'*':/*判定为乘除号*/        case'/':            while(stack[top]=='*'||stack[top]=='/')            {                ex[t]=stack[top];                top--;                t++;            }            top++;            stack[top]=ch;            break;        case'':break;        default:            while(ch>='0'&&ch<='9')            {/*判定为数字*/                ex[t]=ch;t++;                ch=str[i];i++;            }            i--;            ex[t]='';t++;            }            ch=str[i];i++;    }    while(top!=0)    {        ex[t]=stack[top];        t++;top--;    }    ex[t]='';    printf("\n\t原来表达式:");    for(j=1;j<sum;j++)    printf("%c",str[j]);    printf("\n\t逆波兰式:",ex);    for(j=1;j<t;j++)    printf("%c",ex[j]);} void compvalue(){/*计算后缀表达式的值*/    floatstack[max],d;/*作为栈使用*/    charch;    intt=1,top=0;/*t为ex下标,top为stack下标*/    ch=ex[t];t++;    while(ch!='')    {        switch(ch)        {        case'+':            stack[top-1]=stack[top-1]+stack[top];            top--;            break;        case'-':            stack[top-1]=stack[top-1]-stack[top];            top--;            break;        case'*':            stack[top-1]=stack[top-1]*stack[top];            top--;            break;        case'/':            if(stack[top]!=0)stack[top-1]=stack[top-1]/stack[top];            else            {                printf("\n\t除零错误!\n");                exit(0);/*异常退出*/            }            top--;            break;        default:            d=0;            while(ch>='0'&&ch<='9')            {                d=10*d+ch-'0';/*将数字字符转化为对应的数值*/                ch=ex[t];t++;            }            top++;            stack[top]=d;        }        ch=ex[t];        t++;    }    printf("\n\t计算结果:%g\n",stack[top]);} intmain(){    trans();    compvalue();    system("pause");    return0;}


来源: <http://baike.baidu.com/link?url=ta18MXKqCaKCW1-OFa1RxHkjXBZpVW3tjsNqoD6BvEwbK0GEfZpS5EB1Et9WPtppOZtC1YLou68aLm8hSQ1Xta>

逆波兰算法-二叉树实现

#include <string> #include <stack> #include <iostream>  #include <sstream> #include <iomanip> using namespace std;  //节点类 class TNode { public:     friend class calculator_tree;     string father;     TNode *left, *right;     TNode()     {         left = right = NULL;     }     TNode(string a)     {         father = a;         left = right = NULL;     } }; class calculator_tree { public:     calculator_tree() {     }     calculator_tree(string expression) {         getexpression(expression);     }     //获得算术表达式     void getexpression(string expression) {         e = expression;     }     ~calculator_tree() {     }     //返回中缀表达式     string ShowMiddleExpression() {         return e;     }     //计算函数, 输入为两个数和一个操作符, 返回值为计算结果(字符串形式)     string calculate(string num2, string num1, string op) {         double n2, n1;         string result;         stringstream x;         x << num2;         x >> n2;         x.clear();          x << num1;         x >> n1;         x.clear();         if (op == "+")             x << (n2 + n1);         if (op == "-")             x << (n2 - n1);         if (op == "*")             x << (n2 * n1);         if (op == "/")             x << (n2 / n1);         x >> result;         x.clear();         return result;     }     //判别符号的优先级     int Priority(char a) {         if (a == '(')             return 0;         else if (a == '+' || a == '-')             return 1;         else if (a == '*' || a == '/')             return 2;         return 0;     }     //用于去除输入中多余的空格 输入为要除去空格的算术表达式 返回去掉空格的算术表达式     string RidSpace(string origin) {         string transfer;         for (int i = 0; i < origin.length(); i++) {             if (origin[i] != ' ')                 transfer += origin[i];         }         return transfer;     }     //中缀表达式转后缀表达式, 因为要兼容多位数, 括号, 负数和小数等功能,     //由于多位数在转为后缀表达式时会分不清, 故在每个数和运算符后面加上一个空格作为区别     //expression为输出的后缀表达式     string MidToLast(string str) {         str = RidSpace(str);         string expression = "";         string number = "";         char x;         stack<char> op;         for (int i = 0; i < str.length(); ) {             //第一位做特殊处理 判断是否为负号             if (i == 0 && str[i] == '-') {                 number = "-";                 i++;             }             x = str[i];             //录入数字             if ((x >= '0' && x <= '9') || number == "-" || x == '.') {                 while ((str[i] >= '0' && str[i] <= '9') || str[i] == '.') {                     number += str[i];                     i++;                 }                 expression += number;                 //加空格以区别                 expression += " ";                 number = "";                 continue;             } else {                 //判断是括号还是运算符                 if (x == '(') {                     op.push(x);                     //判断是否为负号                     if (str[i+1] == '-') {                         number = "-";                         i++;                       }                 } else {                     //遇到右括号直接弹出运算符栈里的运算符到表达式中 运算符后加空格以区别                     if (x == ')') {                         while (op.top() != '(') {                             expression += op.top();                             expression += " ";                             op.pop();                         }                         //弹出右括号                         op.pop();                       } else {                         //弹出栈中优先级较高的运算符 运算符后加空格以区别                         while (!op.empty() && (Priority(op.top()) >= Priority(x))) {                             expression += op.top();                             expression += " ";                             op.pop();                         }                         //判断是否为负号                         if (str[i+1] == '-') {                         number = "-";                         i++;                         }                         //将运算符压入栈                         op.push(x);                       }                   }               }               i++;             }         while (!op.empty()) {             expression += op.top();             expression += " ";             op.pop();         }         return expression;     }      //获得后缀表达式     string GetLastExpression() {         return MidToLast(RidSpace(e));     }     //生成一棵二叉树     void makeTree(TNode *&p) {         stack <TNode*> Nodes;         string le = GetLastExpression();         string tem = "";             for (int i = 0; i < le.length(); ) {                 while (le[i] != ' ') {                     tem += le[i];                     i++;                 }                 //若为数字, 压入结点栈                 if (tem.length() > 1 || (tem.length() == 1 && tem[0] >= '0' && tem[0] <= '9'))                 {                     p =new TNode(tem);                     Nodes.push(p);                 } else {                     //若为运算符 且栈非空 将栈顶元素拿出来分别作为左子树跟右子树的结点                     //处理如-()的情况                     if (Nodes.empty()) {                         tem = "-";                         i++;                         continue;                    }                     p = new TNode(tem);                     if (!Nodes.empty()) {                         p -> right = Nodes.top();                         Nodes.pop();                     }                     if (!Nodes.empty()) {                         p -> left = Nodes.top();                         Nodes.pop();                     }                     Nodes.push(p);                 }                 i++;                 tem = "";             }     }      //后序遍历二叉树并计算 将计算结果返回     string PostOrder(TNode *p)     {         if(p) {           //假如为符号 执行计算后返回计算结果             if ((p->father).length() == 1 && Priority((p->father)[0])) {                 PostOrder(p->right);                 return calculate(PostOrder(p->left), PostOrder(p->right), p->father);             } else {                 //假如为数字, 直接返回                 return p->father;             }         }     } private:     //存放输入的表达式     string e; }; 



 

后缀表达式生成二叉树

转载请注明涞源chengyaogen.blog.chinaunix.net
 
一、定义
 
       二叉树(binary tree)是一棵每个结点都不能有多于两个儿子的树。

二、数据结构设计
    
        因为一个二叉树结点最多是有两个儿子,所以可以直接链接到他们。树结点的声明在结构上类似双向链表的声明。在声明中,一个结点就是由element(元素)的信息加上两个 到其他结点的引用(left和right)组成的结构

        struct BinaryNode
        {
              Object    element;                    //The data in the node  
              struct BinaryNode   *left;        //Left   child
              struct BinaryNode   *right;     //Right  child
        };    
  
三、表达式树
    
    表达式树的树叶是操作数(operand),加常数或变量名字,而其他的结点为操作数(operator)。由于这里所有的操作都是二元的,因此这棵特定的树正好是二叉树,虽然这是最简单的情况,但是结点还是有可能含有多于两个的儿子,这里我们不讨论。  


四、构造一棵表达式树

    之前我们实现过一个中缀表达式求值的具体程序,在求值过程中需要用两个栈,并且代码并不简单。而这里你会看到,对于表达式树的求值操作却非常简单,甚至只需要两条语句。因为这里大部分操作都是递归定义,二递归函数本身都是很简洁的,甚至比你想象的还要简单,甚至只需要两条语句。因为这里大部分操作都是递归定义,二递归函数本身都是很简洁的,甚至比你想象的还要简单!就像树的遍历操作。三种遍历分别是先序遍历、中序遍历与后序遍历,正好对应表达式的三种形式:前缀型、中缀型与后缀型。其中为大家熟知的是中缀形式,如2+3*(5-4)。前缀型表达式又叫波兰式(Polish Notation),后缀性表达式又叫逆波兰式(Reverse Polish Notation)。他们最早于1920年波兰数学家Jan Lukasiewicz发明,这两种表示方式的最大特点是不需要括号来表明优先级,他们经常用于计算机科学,特别是编译器设计方面。

    下面给出一种算法来把后缀表达式转变成表达式树。我们一次一个符号地读入表达式。如果符号是操作数,那么就建立一个单结点树并将它推入栈中。如果符号是操作符,那么就从栈中弹出两棵树T1和T2(T1先弹出)并形成一棵新的树,该树的根就是操作符,它的左、右儿子分别是T2和T1。然后将指向这颗树的指针压入栈中。

    下面来看一个例子。设输入为ab+cde+**

前两个符号是操作数,因此创建两棵单结点树并将指向它们的指针压入栈中。
 
 
接着,"+"被读入,因此指向两棵树的指针被弹出,形成一棵新的树,并将指向它的指针压入栈中。
 

然后,c,d和e被读入,在单个结点树创建后,指向对应的树的指针被压入栈中。
 
 
接下来读入"+"号,因此两棵树合并。
 
 
继续进行,读入"*"号,因此,弹出两棵树的指针合并形成一棵新的树,"*"号是它的根。
 
 
最后,读入一个符号,两棵树合并,而指向最后的树的指针被留在栈中。
 
 
下面我们来实现以下它吧
 
#include <stdio.h>#include <stdlib.h>#define MAX 100//树结点的设计typedef struct node{    //数字和运算符    union    {        char operator;        int data;    };    struct node *lchild;    struct node *rchild;        }TreeNode;//树栈的设计typedef struct{    TreeNode *buf[MAX];    int n;    }TreeStack;//创建空栈TreeStack *create_empty_stack(){    TreeStack *pstack;    pstack = (TreeStack *)malloc(sizeof(TreeStack));    pstack->n = -1;    return pstack;}//入栈int push_stack(TreeStack *p,TreeNode *data){    p->n ++;    p->buf[p->n] = data;    return 0;}//出栈TreeNode *pop_stack(TreeStack *p){    TreeNode *data;    data = p->buf[p->n];    p->n --;    return data;}//判断空栈int is_empty_stack(TreeStack *p){    if(p->n == -1)    {        return 1;            }else{        return 0;    }}//后缀表达式树的创建TreeNode *create_express_tree(char *str,TreeStack *p){    int i = 0;    TreeNode *current;    TreeNode *left,*right;        while(str[i])    {        if(str[i] == ' ')        {            i ++;            continue;        }                if(str[i] >= '0' && str[i] <= '9')        {            current = (TreeNode *)malloc(sizeof(TreeNode));            current->data = str[i] - '0';            current->lchild = current->rchild = NULL;            push_stack(p,current);                    }else{            current = (TreeNode *)malloc(sizeof(TreeNode));            current->operator = str[i];            right = pop_stack(p);            left = pop_stack(p);            current->lchild = left;            current->rchild = right;            push_stack(p,current);        }        i ++;    }    return p->buf[p->n];}//打印结点void print_node(TreeNode *p){    if(p->lchild == NULL && p->rchild == NULL)    {        printf("%d ",p->data);            }else{        printf("%c ",p->operator);    }    return;}//访问结点int vist_node(TreeNode *p){    print_node(p);    return 0;}//树的后序遍历int PostOrder(TreeNode *p){    if(p != NULL)    {        PostOrder(p->lchild);//左        PostOrder(p->rchild);//右        vist_node(p);//根    }    return 0;}//树的中序遍历int InOrder(TreeNode *p){    if(p != NULL)    {        InOrder(p->lchild);//左        vist_node(p);//根        InOrder(p->rchild);//右    }    return 0;}//树的前序遍历int PreOrder(TreeNode *p){    if(p != NULL)    {        vist_node(p);//根        PreOrder(p->lchild);//左        PreOrder(p->rchild);//右    }    return 0;}/队列的设计struct _node_{    TreeNode *data;    struct _node_ *next;};typedef struct{    struct _node_ *front;    struct _node_ *rear;    }Queue;//创建空队列Queue *create_empty_queue(){    struct _node_ *pnode;    Queue *qhead;    qhead = (Queue *)malloc(sizeof(Queue));    pnode = (struct _node_ *)malloc(sizeof(struct _node_));    pnode->next = NULL;    qhead->front = qhead->rear = pnode;    return qhead;    }//入队int EnterQueue(Queue *qhead,TreeNode *data){    struct _node_ *temp;    temp = (struct _node_ *)malloc(sizeof(struct _node_ *));    temp->data = data;    temp->next = NULL;    qhead->rear->next = temp;    qhead->rear = temp;    return 0;    }//出队TreeNode *DeleteQueue(Queue *qhead){    struct _node_ *temp;    temp = qhead->front;    qhead->front = temp->next;    free(temp);    temp = NULL;    return qhead->front->data;}//队列为空int is_empty_queue(Queue *qhead){    if(qhead->front == qhead->rear)        return 1;    else        return 0;}//树的层次遍历int NoOrder(TreeNode *p){    Queue *qhead;    TreeNode *pdata;    qhead = create_empty_queue();    EnterQueue(qhead, p);    while(!is_empty_queue(qhead))    {        pdata = DeleteQueue(qhead);        vist_node(pdata);        if(pdata->lchild)EnterQueue(qhead,pdata->lchild);        if(pdata->rchild)EnterQueue(qhead,pdata->rchild);    }        return 0;}int main(){    TreeNode *thead;    TreeStack *pstack;    int i = 0;    char buf[100];    while((buf[i++] = getchar()) != '\n' && i < 100);    buf[i-1] = 0;        pstack = create_empty_stack();    thead = create_express_tree(buf,pstack);    printf("PostOrder:: ");    PostOrder(thead);    printf("\n");    printf("InOrder:: ");    InOrder(thead);    printf("\n");    printf("PreOrder:: ");    PreOrder(thead);    printf("\n");    printf("NoOrder::");    NoOrder(thead);    printf("\n");    return 0;

}

0 0
原创粉丝点击