精华内容
下载资源
问答
  • 算符优先算法中优先函数的构造

    千次阅读 2020-11-04 10:29:09
    算符优先分析中“优先函数的简单构造!”


            这里我介绍的是一种简单的方法,不是书本的那个方法。是我后面那个参考资料上面的作者想出来的。因为这个是在知网上面找到的,是1997年的一篇文章。我就是一个总结,然后画几个比较清楚的图而已(因为从知网上下载的的pdf上面的图有点不太清楚)

    优先函数树形构造法

            我们教材上面的就是陈火旺老师的那本,然后方法就是找节点。这个方法虽然简单,但是操作起来的却有些麻烦,因为我们作图的时候,难免就会看不清楚,或者数错。下面介绍的树形构造法就可以避免这个问题,仅仅只需要根据优先矩阵就可以得出正确结果。

    操作步骤

    对于一个优先表先做如下几个步骤(假设优先函数存在)
    1 ) 对于f(a)对应行中“a>=b 的所有终结符b , 把g(b)作为f(a) 的子树。
    2) 对g(a) 对应列中有b <=a 的. 把f(a) 作为g(b)的子树.
    3 ) 对f(a)重做第( 1 ) 步, 对g(b) 重做第( 2 ) 步。
    4) 重复出现的f或g , 作记号不再对其执行第( 1) , ( 2) 步
    方向图
    5) 构造f(a)函数时, 以f(a) 为根结点, 按( 1 ) ,(2 ),( 3),( 4) 执行.
    6) 构造g(b)函数时, 以g(b) 为根结点, 按(2 ) ,( 1 ) , ( 3 ) , ( 4 ) 执行.
    按照以上5步先画出树,然后查树的节点数(包括根节点,做记号的不查),即可以得到根节点的优先函数值。
    但是我觉得这个操作步骤2有点问题。应该是b>=a的时候,就把f(a)作为g(b)的子树。我也自己做了实验,发现这样做才是正确的。不过也可能是我没有理解原作者的意思。反正,就目前看来,我都是按照如果b<=a,就把f(a)作为g(b)的子树。
    所以,下面我举例的例子,第(2)步都是按照“b>=a的时候,就把f(a)作为g(b)的子树”这个来做的。

    举例操作

            假如现有一个优先矩阵是这样的:这个例子是《编译原理》陈火旺老师(下面我说的教材,没有特别说明也是指的这本教材)那本书上面的。在90页。
    在这里插入图片描述
    那么我们现在用树形构造法来试试怎么得到这个优先函数。因为最后的答案是去掉了 i 和 # 之后得到的,所以我下面也将不会考虑 i 和 # 号。至于为什么不考虑 i 和 #,,就是因为这两个不是算符,我们算符优先函数主要针对的就是算符直接的优先级。但是优先关系矩阵中是给出了 i 和 # 与其他算符之间的优先关系的。我这里其实是有一个疑问的:因为在优先函数这里没有 i 的优先关系,那么在使用优先函数来分析一个句子是不是这个文法定义的合法的句子的时候,那么什么时候该移进这个 i 呢?希望知道的小伙伴可以在下面留言,我们讨论一下。

            计算f(+)的优先函数值。

    1. 从优先矩阵中可以得到:’+‘ >= 的算符有;’+’,’)’,’#'三个。因为不考虑i 和 #(下面就不提醒这一点了),所以f(+)的孩子节点有两个,分别是g(+)和g()),如下图所示。
      在这里插入图片描述
    2. 现在就来找g(’+’) 的子树。我这里还是采用的是如果b>=a,就把f(a)作为g(b)的子树。从优先表中可以看到的就是’+‘ >= 的算符有:’(’。注意,我这里说的’+‘是g(’+‘),也就是从’+‘那一列中寻找。在这里插入图片描述
      所以,g(’+’)的子树就是f(’(’);在这里插入图片描述
    3. 然后找到g(’)’) >=的算符:在这里插入图片描述
      但是f(’(’)已经出现过了(作为g(’+’)子树出现的),所以就不用画出来了。
    4. 然后就是寻找f(’(’) >=的算符。在这里插入图片描述但是g(’)’)也已经出现过了,所以这里也不用画出来了。
    5. 最后每一个节点我们都已经检查过了,没有可以重新添加的了。也就是趋于稳定了(编译原理里面好多都是这样子的,得使所有都不再变化的时候,算法就算结束了)。我们数一下节点的个数,就是4个,和书本95页给出的答案是一样的。

            同理,g(’+’)的树也可以这样画出来。我就给出最后的树,就不一一分析了。
    在这里插入图片描述

    自己的思考

            本质上书本上的画图和这里的画一颗树,都是优先级高的指向优先级低的,所以入度为0的节点,给的优先函数值应大一点,出度为0的,给出的优先函数值应该小一点。

            上面提到的这个简单的方法其本质善和我们教材上的方法是一样的。你可以将教材上的方法中的图给截取一部分出来。例如,你截取以g(’+’)作为顶点的树去看,发现就是和我上面画的一样。

            还有注意的一点就是:我们求出一组优先函数之后,就可以构造出无数组优先函数。所以,如果你求出来的和参考答案给出的不是一样的,也不一定是你错了。只要你的优先函数之间的关系和参考答案上给出的关系是一样的就可以了。

    参考资料

    构造优先函数的更简单方法_树型构造_潘群娜
    这个知网上我找到的一篇关于这个优先函数构造比较简单的方法,如果大家对上面的博客解释的不太清楚的话,可以去知网上看这个原作者写的文章。

    展开全文
  • 算符优先分析 优先函数

    万次阅读 2011-05-05 17:59:00
    简单的方法,计算优先函数 手动计算比较麻烦,而且容易出错。 根据定义,用计算机实现,快捷方便,准确可扩充   // 0505优先函数.cpp : 定义控制台应用程序的入口点。 // /* 使用说明: 1、改#define N 的值 2...

    简单的方法,计算优先函数

    手动计算比较麻烦,而且容易出错。

    根据定义,用计算机实现,快捷方便,准确可扩充

     

    展开全文
  • 编译原理 优先函数实现表达式计算

    千次阅读 2020-04-23 00:36:27
    优先函数实现表达式计算 左/右 + * ( ) i # + ·> · · ·> · ·> * ·> ·> · ·> · ·> ( · · · = · ) ·> ·> ·> ·> i ·> ·> ·> ...

    优先函数实现表达式计算

    左/右 + * ( ) i #
    + ·> <· <· ·> <· ·>
    * ·> ·> <· ·> <· ·>
    ( <· <· <· <·
    ) ·> ·> ·> ·>
    i ·> ·> ·> ·>
    # <· <· <· <·

    由优先表构造优先函数

    优先函数 + * ( ) i #
    f 6 8 2 8 8 1
    g 4 7 9 2 9 1

    本程序使用C语言编写
    支持整数加减乘除带括号的运算
    核心部分和数据结构中利用栈实现表达式运算几乎相同
    程序的难点在于优先级<、=、>分类讨论

    #include<stdio.h>
    #include<stdlib.h>
    #include <string.h>
    //优先函数
    int fplus = 6;
    int gplus = 4;
    
    int fmul = 8;
    int gmul = 7;
    
    int fleft = 2;
    int gleft = 9;
    
    int fright = 8;
    int gright = 2;
    
    int fi = 8;
    int gi = 9;
    
    int fpound = 1;
    int gpound = 1;
    
    char expression[128];
    int flag = 1; 
    
    void Error()
    {
        printf("错误\n");
        exit(0);
    }
        
    void Input()
    {
    	//char over[] = {'#', '\0'};
        printf("请输入表达式,以#结尾:"); 
        gets(expression); 
    	//printf("Input: %s\n",expression);
    }
    
    int f(char opt)
    {
        if(opt == '+' || opt == '-')
        {
    		return fplus;
        }
        else if (opt == '*' || opt == '/')
        {
            return fmul;
        }
        else if (opt == '(')
        {
            return fleft;
        }
        else if (opt == ')')
        {
            return fright;
        }
        else if (opt == 'i')
        {
            return fi;
        }
        else if (opt == '#')
        {
            return fpound;
        }
        return -1;
    }
        
    int g(char opt)
    {
        if(opt == '+' || opt == '-')
        {
            return gplus;
        }
        else if (opt == '*' || opt == '/')
        {
            return gmul;
        }
        else if (opt == '(')
        {
            return gleft;
        }
        else if (opt == ')')
        {
            return gright;
        }
        else if (opt == 'i')
        {
            return gi;
        }
        else if (opt == '#')
        {
            return gpound;
        }
        return -1;
    }
        
    int In(char num)
    {
        if(num == '0' ||num == '1' || num == '2' || num == '3' || num == '4' || 
    	   num == '5'|| num == '6' || num == '7' || num == '8' || num == '9')
    	   return 1;
        else
            return -1;
    }
        
    int Operation(int a, char opt, int b) 
    {
    	switch(opt)
    	{
    		case '+': return a + b; 
    		case '-': return a - b; 
    		case '*': return a * b; 
    		case '/': return a / b; 
    		default : return 0;
    	} 
    } 
    
    int main() 
    {
    	int index_e = 0;	// 字符串下标
    	int	index_oprt = 0; // 算符栈下标
    	int index_opnd = 0; // 算量栈下标
        int Sn[100];
    	char Sp[100];
    	int num1;
    	int num2;
    	char temp[100];
        Sp[0] = '#';
    
        Input();
    	//printf("算符栈: %s\n",Sp);
        while( flag == 1 )
        {
    		int t = 0;
            if( Sp[index_oprt] == '#' && expression[index_e] == '#' )
            {
    			//printf("都为#,结束\n");
                flag = 0;
            }
            else if(Sp[index_oprt] == '(' && expression[index_e] == ')')
            {
    			//printf("读到括号\n");
                index_oprt--;
                index_e++;
            }
            else if(In(expression[index_e]) == 1)
            {
    			//printf("读到数字\n");
                while(In(expression[index_e]) == 1)
                {
                    temp[t] = expression[index_e];
    				t++;
                    index_e++;
                }
    			//printf("temp: %s\n",temp);
    			//atof()是把字符串转换成double
                Sn[index_opnd++] = atof(temp);
    			//printf("number %d\n",Sn[index_opnd-1]);
                //清空temp
    			for(int m=0; m<100; m++)
    				temp[m] = '\0';
            }
            else if(f(Sp[index_oprt]) < g(expression[index_e]))
            {
    			//printf("%d %d\n",f(Sp[index_oprt]),g(expression[index_e]));
    			//printf("小于\n");
                Sp[index_oprt + 1] = expression[index_e];
                index_oprt++;
                index_e++;
    			//printf("%c 入栈\n",Sp[index_oprt]);
    		}
            else if(f(Sp[index_oprt]) > g(expression[index_e]))
            {
    			//printf("大于\n");
    			//出栈两个数
                num2 = Sn[index_opnd - 1];
    			index_opnd--;
                num1 = Sn[index_opnd - 1];
                index_opnd--;
    			//算符栈出一个,算完了结果再入算量栈
    			Sn[index_opnd] = Operation(num1, Sp[index_oprt], num2);
                index_opnd++;
                index_oprt--;
            }
            else
            {
                Error();
            }
        }
        printf("表达式的值为:%d\n", Sn[0]);
    	return 0;
    }
    

    运行截图:
    在这里插入图片描述

    展开全文
  • 自底向上分析方法,也称移进-归约分析法。 实现思想: 对输入符号串自左向右进行扫描,并将输入符逐个移入一个栈中,...5.1 自底向上优先分析法概述 5.2 简单优先分析法 5.3 算符优先分析法 ...

    自底向上分析方法,也称移进-归约分析法。

    实现思想:

    • 对输入符号串自左向右进行扫描,并将输入符逐个移入一个栈中,边移入边分析,一旦栈顶符号串形成某个句型的句柄时,就用该产生式的左部非终结符代替相应右部的文法符号串,这称为归约
    • 重复这一过程,直到栈中只剩文法的开始符号时,则分析成功,也就确认输入串是文法的句子。
      在这里插入图片描述
      在这里插入图片描述

    5.1 自底向上优先分析法概述

    在这里插入图片描述

    5.2 简单优先分析法

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    5.3 算符优先分析法

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 若已知运算符之间的优先关系,可按如下步骤构造优先函数: 1、对每个运算符a(包括#在内)令f(a)=g(a)=1 2、如果a⋗b且f(a)<=g(b)令f(a)=g(b)+1 3、如果a⋖b且f(a)>=g(b)令g(b)= f(a)+1 4、如果a≐b而f(a)...
  • C++多态虚函数表详解(多重继承、多继承情况)

    万次阅读 多人点赞 2018-08-20 16:51:00
    本文关键词:C++ 多态 虚函数表 虚函数指针 动态绑定 概述:C++相对其他面向对象语言来说,之所以灵活、高效。很大程度的占比在于其多态技术和模板技术。C++虚函数表是支撑C++多态的重要技术,它是C++动态绑定...
  • C++学习之深入理解虚函数--虚函数表解析 标签: C++C++虚函数虚函数表解析虚函数表 2014-03-27 11:05 11838人阅读 评论(6) 收藏 举报  分类:   C++语言(79)  目录(?)[+] ...
  • 对象一建立就运行,而且优先于构造函数执行。 构造代码块与构造函数的区别: 构造代码块是给所有对象进行统一初始化, 而构造函数是给对应的对象初始化。 构造代码快中定义的是不同对象共性的初始化内容。 //...
  • 关于JS里面的函数优先

    千次阅读 2018-04-27 09:32:30
    由于JS编译器的作用,函数声明和变量声明都会被提升,但是一个值得注意的细节是函数会首先被提升,然后才是变量。 提升 变量和函数声明从它们在代码中出现的位置被“移动”到了最上面,这叫变量的提升。分为...
  • 深入理解多态虚函数--虚函数表解析

    千次阅读 2018-02-09 15:02:13
    C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”,这是一种泛型技术。...
  • C++_多态(深入理解虚函数表

    千次阅读 多人点赞 2021-05-08 13:23:17
    军人买票时是优先买票 怎么构成多态 并没有构成多态,形参p对象,全部调用了Person类的成员函数。 多态与重写 这时候就需要使用虚函数来构成多态。 梳理一下,多态的条件: 继承类中,需要对虚函数进行重写。 ...
  • js中的函数优先原则

    千次阅读 2018-04-21 22:56:37
    在js中函数声明和变量都会被提升,但是函数会被优先提升,然后才是变量下面我们贴出我们的示例代码foo();//1 var foo; function foo() { console.log( 1 ); } foo = function() { console.log( 2 ); }我们使用js引擎...
  • C++ 优先队列自定义比较函数

    千次阅读 2020-04-07 15:44:31
    C++中的优先队列实质是一种堆(最大堆或最小堆)
  • 有些STL 容器提供了一些与算法同名的成员函数。大多数情况下,应该使用这些成员函数,而不是相应的STL算法。 有两个理由: 成员函数往往速度快。 成员函数通常与容器结合地更紧密,这是算法所不能比的。 set容器的...
  • 对于派生类的构造 函数,在定义对象时构造函数的执行顺序为: 1:基类的构造函数 2:成员对象的构造函数 3:派生类本身的构造函数 public class IoTest { public static void main(String[] args) throws ...
  • 常用激活函数(激励函数)理解与总结

    万次阅读 多人点赞 2018-05-13 23:07:19
    学习神经网络的时候我们总是听到激活函数这个词,而且很多资料都会提到常用的激活函数,比如Sigmoid函数、tanh函数、Relu函数。那么我们就来详细了解下激活函数方方面面的知识。本文的内容包括几个部分: 什么是...
  • template <typename T>void f(T a){ cout ; } template <> void f(int & a){ cout ;...为什么输出aaaaaaa,不是应该输出fffffffffff吗,看书上说具体化优先于模板函数的 求知道的大神指点下啦,万分感谢
  • //定义一个优先队列默认从大到小排序,因为是优先队列呀 如果我们想从小到大排序就需要自定义排序函数了bool operator > ( Node a,Node b) //这里的参数如果是Node* 并不知道为什么 { return a.num > b.nu
  • 优先队列之自定义比较函数

    千次阅读 2019-02-27 22:32:35
    #include &lt;iostream&gt; #include &lt;vector&gt; #include &lt;unordered_map&gt; #include &lt;queue&gt; #include &lt;string&... * 默认使用le...
  • 关于优先队列priority_queue自定义比较函数用法整理 原来上不了网,写在word里了,代码什么的直接贴过来了,有空整理成高亮的形式。 0.0、首先注意一点,priority_queue没有front()方法,和一般的queue不一样,与...
  • sort以及qsort函数的cmp 转自 http://blog.csdn.net/lionel_d/article/details/41746135 写的很好,直接复制粘贴过来了,感谢一、sort 以及 qsort首先,我们来谈谈大名鼎鼎的void qsort(void *base,int nelem,int ...
  • 优先队列 (结构体自定义比较)(重载函数

    千次阅读 多人点赞 2018-12-23 14:10:37
    之前一直在 用 sort 的结构体自定义函数,感觉到 STL 强大,今天刷题遇见优先队列 的题 ,要求跟 以前一样,数据量大,要求对某个信息排序,并且 做相应的 操作,如果用 普通的结构体来模拟 ,但是这个sort 要每次...
  • 有几个例子要展示,以防万一:内联值CREATE FUNCTION MyNS.GetUnshippedOrders() RETURNS TABLE AS RETURN SELECT a.SaleId, a.CustomerID, b.Qty FROM Sales.Sales a INNER JOIN Sales.SaleDetail b ON a....
  • 46. 优先考虑流中无副作用的函数 如果你是一个刚开始使用流的新手,那么很难掌握它们。仅仅将计算表示为流管道是很困难的。当你成功时,你的程序将运行,但对你来说可能没有意识到任何好处。流不仅仅是一个 API,它...
  • C++ 优先队列用法自定义Compare函数

    千次阅读 2015-07-28 07:43:00
    第三个参数 _Compare : 比较函数,对于自定义类型有两种方法实现大小顶堆,第一个是重载操作符,第二个是写一个结构实现比较。 各个数据类型算法讲解如下: 1. 对于一般的基本数据类型,比如 int...
  • 浅谈模板函数的重载解析优先顺序

    千次阅读 2011-09-01 20:47:27
    函数模板可以被重载、显式特化重载、普通函数重载。如以下函数模板的重载声明: namespace LDQ_TEST {  //函数模板定义  template  T sum( T, int );  //T == double的显式特化  template( doubl
  • 要避免交成员费:尽可能将函数指定为非成员非友元函数。 非成员非友元函数通过尽量减少依赖提高了封装性:函数体不能依赖于类的非公用成员。它们还能够分离巨类,释放可分离的功能,进一步减少耦合。它们能够提高...
  • 如果要在优先队列中进行结构体排序该怎么办? 首先定义个结构体A typedef struct A { int l; int r; int label; }a; 接下来就可以定义优先队列,容器中的元素是结构体A #include <queue> priority_...
  • 普通函数函数模板的调用规则

    千次阅读 2019-07-01 14:14:41
    如果函数模板和普通函数都可以实现,优先调用普通函数 可以通过空模板参数列表来强制调用函数模板 函数模板也可以发生重载 如果函数模板可以产生更好的匹配,优先调用函数模板 测试代码: #include <iostream>...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 373,605
精华内容 149,442
关键字:

优先函数表