• 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版)(普通高等教育"十一五"国家级规划教材)》读书笔记
    《自控力》读书记录
    计算机组成原理基础知识--《计算机组成原理与汇编语言程序设计(第4版)(高等学校规划教材)》读书笔记
    ansible自动部署模板文件中列表长度判断
    《股市稳赚》摘录
    yarn学习小结
  • 原文地址:https://www.cnblogs.com/SwordTao/p/3574389.html
Copyright © 2020-2023  润新知