zoukankan      html  css  js  c++  java
  • Dijkstra 调度场算法 Python实现 一

      调度场算法(Shunting Yard Algorithm)是一个用于将中缀表达式转换为后缀表达式的经典算法,由 Edsger Wybe Dijkstra 引入,因其操作类似于火车编组场而得名。
      ——维基百科

    目标阐述:
      将中缀表达式转换为后缀表达式(Reverse Polish Notation:RPN 逆波兰式)
      参与运算的数据的正则表示为:[0-9]{1,}形式的十进制数
    运算符优先级:(从高到低)
    ———————————————————————— ( ) 括号
    / * % 除乘余 + - 加减
    ————————————————————————

    解:


    第一步:使用正则词法分析器flex生成一个词法分析器,以处理输入的中缀表达式。
      从stdin接收输入,检测非法字符,并将处理后的中缀表达式输出到stdout。 

    %option noyywrap
    %{
    #include<stdio.h>
    #include<stdlib.h>%}
    
    %%
    [0-9]+ { printf("%s ",yytext); }
    [()*/%+-]  { printf("%s ",yytext); }
    [[:space:]]  {}
    .  { printf("
    Error
    ");exit(1);  }
    %%
    
    int main()
    {
      yylex();
      printf("
    ");
      return 0;
    } 

    第二步:使用Python进行转换。
      从stdin接收一定格式的中缀表达式字符流,检测是否在词法分析器处理过程中出错,然后使用调度场算法处理数据,得到rpn列表。

    import sys
    
    line=sys.stdin.readline()
    line2=sys.stdin.readline()
    
    if len(line2)>0:
      sys.stderr.write("Syntax Error after : ")
      sys.stderr.write(line)
      sys.stderr.write("
    ")
      exit(1)
    
    lis=line.split(' ')
    lis.pop()
    lis_old=lis[:]
    lis.reverse()
    
    oplis=[]
    rpnlis=[]
    str=''
    arith_op="+-*/%" # '(' ')' [0-9]+
    prior={ '/':1,'*':1,'%':1, '+':2,'-':2 }
    
    while len(lis)>0:
        str=lis.pop()
        if str=='(':
            oplis.append('(')
        elif str.isdigit():
            rpnlis.append(str)
        elif len(str)==1 and arith_op.find(str[0])!=-1:
            if len(oplis)==0 or oplis[len(oplis)-1]=='(':
                oplis.append(str)
            else:
                while len(oplis)>0 and oplis[len(oplis)-1]!='(' 
                                  and prior[oplis[len(oplis)-1]]<=prior[str]:
                    rpnlis.append(oplis.pop())
                oplis.append(str)
        elif str==')':
            while len(oplis)>0 and oplis[len(oplis)-1]!='(':
                rpnlis.append(oplis.pop())
            if len(oplis)>0:
                      oplis.pop()
                    else:
                      sys.stderr.write("Syntax Error while translating : Expected '('")
                      sys.stderr.write("
    ")
                      exit(2)
            else:
              sys.stderr.write("Syntax Error : unkown notation -->")
              sys.stderr.write(str)
              sys.stderr.write("
    ")
              exit(3)
    while len(oplis)>0 :
        if oplis[len(oplis)-1]!='(':
              rpnlis.append(oplis.pop())
            else:
              sys.stderr.write("Syntax Error while translating : Unexpected '('")
              sys.stderr.write("
    ")
              exit(1)
    
    print lis_old
    for i in lis_old:
        sys.stdout.write(i)
    print ''
    print rpnlis
    for i in rpnlis:
        print i,
    print ''
    
    exit(0)

    实验结果: 

    目前程序的局限:
      未进行语法检测。
      不支持函数、变量标识。

    附录:

     算法示意图,使用了3个空间。输入用符号代替,如果输入是一个数字则直接进输出队列,即图中 b),d),f),h)。如果输入是运算符,则压入操作符堆栈,即图中 c),e),但是,如果输入运算符的优先级低于或等于运算符栈顶的操作符优先级,则栈内元素进入输出队列(循环判定),输入操作符压入运算符堆栈,即图中 g)。 最后,运算符堆栈内元素入输出队列,算法结束。

      附录中资料摘自维基百科•调度场算法词条。

  • 相关阅读:
    第4月第1天 makefile automake
    第3月30天 UIImage imageWithContentsOfFile卡顿 Can't add self as subview MPMoviePlayerControlle rcrash
    第3月第27天 uitableviewcell复用
    learning uboot fstype command
    learning uboot part command
    linux command dialog
    linux command curl and sha256sum implement download verification package
    learning shell script prompt to run with superuser privileges (4)
    learning shell get script absolute path (3)
    learning shell args handing key=value example (2)
  • 原文地址:https://www.cnblogs.com/SwordTao/p/3574389.html
Copyright © 2011-2022 走看看