使用分治策略递归和非递归和递推算法解决循环赛日程表课程设计报告

使用分治策略递归和非递归和递推算法解决循环赛日程表课程设计报告
使用分治策略递归和非递归和递推算法解决循环赛日程表课程设计报告

《算法设计与分析》

课程设计报告

题目:循环赛日程表

院(系):信息科学与工程学院

专业班级:软工

学生姓名:

学号:

指导教师:

2018 年 1 月 8 日至 2018 年 1 月 19 日

算法设计与分析课程设计任务书

目录

1 常用算法 (1)

1.1分治算法 (1)

基本概念: (1)

1.2递推算法 (2)

2 问题分析及算法设计 (5)

2.1分治策略递归算法的设计 (5)

2.2 分治策略非递归算法的设计 (7)

2.3 递推策略算法的设计 (8)

3 算法实现 (9)

3.1分治策略递归算法的实现 (9)

3.2 分治策略非递归算法的实现 (10)

3.3 递推策略算法的实现 (12)

4 测试和分析 (15)

4.1分治策略递归算法测试 (15)

4.2分治策略递归算法时间复杂度的分析 (16)

4.3 分治策略非递归算法测试 (16)

4.4分治策略非递归算法时间复杂度的分析 (17)

时间复杂度为:O(5^(n-1)) (17)

4.5 递推策略算法测试 (17)

4.6 递推策略算法时间复杂度的分析 (18)

时间复杂度为:O(5^(n-1)) (18)

4.7 三种算法的比较 (18)

5 总结 (19)

参考文献 (20)

1 常用算法

1.1分治算法

基本概念:

在计算机科学中,分治法是一种很重要的算法。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。这个技巧是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)……

任何一个可以用计算机求解的问题所需的计算时间都与其规模有关。问题的规模越小,越容易直接求解,解题所需的计算时间也越少。例如,对于n个元素的排序问题,当n=1时,不需任何计算。n=2时,只要作一次比较即可排好序。n=3时只要作3次比较即可,…。而当n较大时,问题就不那么容易处理了。要想直接解决一个规模较大的问题,有时是相当困难的。

基本思想及策略:

分治法的设计思想是:将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。

分治策略是:对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。这种算法设计策略叫做分治法。

如果原问题可分割成k个子问题,1

分治法适用的情况:

分治法所能解决的问题一般具有以下几个特征:

1) 该问题的规模缩小到一定的程度就可以容易地解决

2) 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。

3) 利用该问题分解出的子问题的解可以合并为该问题的解;

4) 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。

1.2递推算法

递推算法是一种根据递推关系进行问题求解的方法。递推关系可以抽象为一个简单的数学模型,即给定一个数的序列a0,a1...,an若存在整数n0,使当n>n0时可以用等号将an与其前面的某些项ai联系起来,这样的式子成为递推公式。递推算法是一种简单的算法,通过已知条件利用特点的递推关系可以得出中间推论,直至得到问题的最终结果,递推算法分为顺推法和逆推法两种,顺推法则是在不知道初始条件的情况下,从问题的结果除非经递推关系逐步推算出问题的解,这个问题的解也是问题的初始条件。

递归法是从已知条件出发,一步步地递推出未知项,直到问题的解。递归也是递推的一种,只不过它是对待解问题的递推,知道把一个负责的问题递推为简单的易解问题,然后再一步步返回,从而得到原问题的解。严格来讲,递归不仅仅是一种问题求解方法,更是一种编程技术,许多算法可以通过递归技术来编程实现。在计算机科学中,人们把程序直接或间接调用自身的过程称为递归。过程或函数直接调用自身的递归成为直接递归,间接调用自身的递归称为间接递归。在问题求解中,采用递归算法有两个重要的好处:一是容易证明算法有两个重要的好处,其次是代码实现简洁,代码编程量少。不足是程序运行效率较低。

递推算法的基本思想是把一个复杂庞大的计算过程转化为简单过程的多次重复。该算法利用了计算机速度快和自动化的特点。

而递归法的思想是从已知条件出发,一步步地递推出未知项,直到问题的解。

五种典型的递推关系:

1.Fibonacci数列

在所有的递推关系中,Fibonacci数列应该是最为大家所熟悉的。在最基础的程序设计语言Logo语言中,就有很多这类的题目。而在较为复杂的Basic、Pascal、C语言中,Fibonacci数列类的题目因为解法相对容易一些,逐渐退出了竞赛的舞台。可是这不等于说Fibonacci数列没有研究价值,恰恰相反,一些此类的题目还是能给我们一定的启发的。

Fibonacci数列的代表问题是由意大利著名数学家Fibonacci于1202年提出的“兔子繁殖问题”(又称“Fibonacci问题”)。

问题的提出:有雌雄一对兔子,假定过两个月便可繁殖雌雄各一的一对小兔子。问过n个月后共有多少对兔子?

解:设满x个月共有兔子Fx对,其中当月新生的兔子数目为Nx对。第x-1个月留下的兔子数目设为Fx-1对。则:

Fx=Nx+ Fx-1

Nx=Fx-2 (即第x-2个月的所有兔子到第x个月都有繁殖能力)

∴ Fx=Fx-1+Fx-2 边界条件:F0=0,F1=1

由上面的递推关系可依次得到:

F2=F1+F0=1,F3=F2+F1=2,F4=F3+F2=3,F5=F4+F3=5,……。

Fabonacci数列常出现在比较简单的组合计数问题中,例如以前的竞赛中出现的“骨牌覆盖”问题。在优选法中,Fibonacci数列的用处也得到了较好的体现。

2.Hanoi塔问题

问题的提出:Hanoi塔由n个大小不同的圆盘和三根木柱a,b,c组成。开始时,这n个圆盘由大到小依次套在a柱上,如图3-11所示。

要求把a柱上n个圆盘按下述规则移到c柱上:

(1)一次只能移一个圆盘;

(2)圆盘只能在三个柱上存放;

(3)在移动过程中,不允许大盘压小盘。

问将这n个盘子从a柱移动到c柱上,总计需要移动多少个盘次?

解:设hn为n个盘子从a柱移到c柱所需移动的盘次。显然,当n=1时,只需把a 柱上的盘子直接移动到c柱就可以了,故h1=1。当n=2时,先将a柱上面的小盘子移动到b柱上去;然后将大盘子从a柱移到c 柱;最后,将b柱上的小盘子移到c柱上,共记3个盘次,故h2=3。以此类推,当a柱上有n(n2)个盘子时,总是先借助c柱把上面的n-1个盘子移动到b柱上,然后把a柱最下面的盘子移动到c柱上;再借助a柱把b柱上的n-1个盘子移动到c柱上;总共移动hn-1+1+hn-1个盘次。

∴hn=2hn-1+1 边界条件:h1=1

3.平面分割问题

问题的提出:设有n条封闭曲线画在平面上,而任何两条封闭曲线恰好相交于两点,且任何三条封闭曲线不相交于同一点,问这些封闭曲线把平面分割成的区域个数。

解:设an为n条封闭曲线把平面分割成的区域个数。由图3-13可以看出:a2-a1=2;a3-a2=4;a4-a3=6。

从这些式子中可以看出an-an-1=2(n-1)。当然,上面的式子只是我们通过观察4幅图后得出的结论,它的正确性尚不能保证。下面不妨让我们来试着证明一下。当平面上已有n-1条曲线将平面分割成an-1个区域后,第n-1条曲线每与曲线相交一次,就会增加一个区域,因为平面上已有了n-1条封闭曲线,且第n条曲线与已有的每一条闭曲线恰好相交于两点,且不会与任两条曲线交于同一点,故平面上一共增加2(n-1)个区域,加上已有的an-1个区域,一共有an-1+2(n-1)个区域。所以本题的递推关系是an=an-1+2(n-1),边界条件是a1=1。

4.Catalan数

Catalan数首先是由Euler在精确计算对凸n边形的不同的对角三角形剖分的个数问题时得到的,它经常出现在组合计数问题中。

问题的提出:在一个凸n边形中,通过不相交于n边形内部的对角线,把n边形拆分成若干三角形,不同的拆分数目用hn表示,hn即为Catalan数。例如五边形有如下五种拆分方案(图3-14),故h5=5。求对于一个任意的凸n边形相应的hn。

5.第二类Stirling数

n个有区别的球放到m个相同的盒子中,要求无一空盒,其不同的方案数用S(n,m)表示,称为第二类Stirling数。

根据定义来推导带两个参数的递推关系——第二类Stirling数。

解:设有n个不同的球,分别用b1,b2,……bn表示。从中取出一个球bn,bn的放法有以下两种:

①bn独自占一个盒子;那么剩下的球只能放在m-1个盒子中,方案数为S2(n-1,m-1);

②bn与别的球共占一个盒子;那么可以事先将b1,b2,……bn-1这n-1个球放入m个盒子中,然后再将球bn可以放入其中一个盒子中,方案数为mS2(n-1,m)。

综合以上两种情况,可以得出第二类Stirling数定理:

【定理】S2(n,m)=mS2(n-1,m)+S2(n-1,m-1) (n>1,m1)

边界条件可以由定义2推导出:

S2(n,0)=0;S2(n,1)=1;S2(n,n)=1;S2(n,k)=0(k>n)。

2 问题分析及算法设计

2.1分治策略递归算法的设计

从本问题的具体情况出发,根据分治算法思想,设计出本问题的分治递归算法按分治策略,可将所有选手分成两组。n个选手的比赛日程表,可以通过n/2个选手的比赛日程表,可以通过n/4个选手设计日程表来决定;……;直到为2个选手的比赛日程表。这样比赛日程表的设计就变得很简单,这时只要让两个选手互相比赛即可,这样可以形成n/2组2个选手的比赛日程表(如表1、表2)。然后再反过来在两个选手的日程表上为4个选手设计比赛日程表(如表3)。然后再类推到8个、16个、……、2k个选手。

对所有运动员的赛程进行安排,并将其存入数组内:

由初始化的第一行填充第二行:(填充原则是对角线填充)

最后是第三部分的填充

递归算法解:

2.2 分治策略非递归算法的设计

分治策略同上。

非递归算法解:

2.3 递推策略算法的设计

递推策略:

3 算法实现

3.1分治策略递归算法的实现

#include

#include

#include

const int MAX = 1024;//

int a[MAX][MAX];//二位数组

int Number=2,g_K=1;

clock_t start, finish;//开始和结束时间

double duration;//程序运行时间

void Test1(int k,int m);//分治策略递归实现

int main(void)

{

printf("请输入指数k\n");

while(scanf("%d",&g_K)==0){

fflush(stdin);

}

for (int y=1;y

Number*=2;

printf("参赛人员");

for(int z=1;z

printf(" day%d",z);

}

system("cls");

start=clock();

for(int i=0;i<10000;i++)

Test1(1,Number);

finish=clock();

duration=finish-start;

//Menu();

for( i=1;i<=Number;i++)//

{

for(int j=1;j<=Number;j++)//第一列为参赛人员printf(" %d",a[i][j]);

printf("\n");

}

printf("程序循环10000次所用的时间:%lfms\n",duration);

return 0;

}

void Test1(int k,int m)//采用分治策略递归实现

{

int i,j;

if(m==2)//只有两个人的时候

{

a[k][1]=k;

a[k+1][1]=k+1;

}

else

{

Test1(k,m/2);

Test1(k+m/2,m/2);

}

for(i=k;i

a[i][j]=a[i+m/2][j-m/2];//填充表格

for(i=k+m/2;i

for(j=m/2+1;j<=m;j++)

a[i][j]=a[i-m/2][j-m/2];

}

3.2 分治策略非递归算法的实现

#include

#include

#include

const int MAX = 1024;//

int a[MAX][MAX];//二位数组

int Number=2,g_K=1;

clock_t start, finish;//开始和结束时间

double duration;//程序运行时间

void Test2(int k);//分治策略非递归实现

int main(void)

{

printf("请输入指数k\n");

while(scanf("%d",&g_K)==0){

fflush(stdin);

printf("请输入“整数”k\n");

}

for (int y=1;y

Number*=2;

printf("参赛人员");

for(int z=1;z

printf(" day%d",z);

}

system("cls");

start=clock();

for(int i=0;i<10000;i++)

Test2(g_K);

finish=clock();

duration=finish-start;

for( i=1;i<=Number;i++)

{

for(int j=1;j<=Number;j++)//第一列为参赛人员

printf(" %d",a[i][j]);

printf("\n");

}

printf("程序循环10000次所用的时间:%lfms\n",duration);

return 0;

}

void Test2(int k){//分治策略非递归方式实现

int i,j;

int n;

n=Number;//拷贝参赛选手人数

for(i=1;i<=n;i++)

a[1][i]=i;

int m=1; //填充初始位置

for(int s=1;s<=k;s++)

{

n/=2;

for(int t=1;t<=n;t++)

{

for(i = m+1 ; i <= 2*m ; i++)

{

for(j = m+1 ; j <=2*m ; j++)

{

a[i][j+(t-1)*m*2] = a[i-m][j+(t-1)*m*2-m];

a[i][j+(t-1)*m*2-m] = a[i-m][j+(t-1)*m*2]; }

}

}

m*=2;

}

}

3.3 递推策略算法的实现

#include

#include

#include

const int MAX = 1024;//

int a[MAX][MAX];//二位数组

int Number=2,g_K=1;

clock_t start, finish;//开始和结束时间

double duration;//程序运行时间

void Test3(int k);//对推策略实现

int main(void)

{

printf("请输入指数k\n");

while(scanf("%d",&g_K)==0){

fflush(stdin);

printf("请输入“整数”k\n");

}

for (int y=1;y

Number*=2;

printf("参赛人员");

for(int z=1;z

printf(" day%d",z);

}

system("cls");

start=clock();

for(int i=0;i<10000;i++)

Test3(Number);

finish=clock();

duration=finish-start;

for( i=1;i<=Number;i++)

{

for(int j=1;j<=Number;j++)//第一列为参赛人员printf(" %d",a[i][j]);

printf("\n");

}

printf("程序循环10000次所用的时间:%lfms\n",duration);

return 0;

}

void Test3(int num){//递推算法实现

a[1][1]=1;

int n,n0,i,j,k,k0;

n0=1;

n=2;

k=g_K;//人数

for (k0=1;k0<=k;k0++){

for (i=n0+1;i<=n;i++){

for (j=1;j<=n;j++){

a[i][j]=a[i-n0][j]+n0;

}

}

for (j=n0+1;j<=n;j++){

for (i=1;i<=n0;i++)

{

a[i][j]=a[i][j-n0]+n0;

}

}

for (j=n0+1;j<=n;j++){

for (i=n0+1;i<=n;i++){

a[i][j]=a[i][j-n0]-n0;

}

}

n0=n;

n=n*2;

}

}

4 测试和分析4.1分治策略递归算法测试

给出输入情况:

得到输出结果:

4.2分治策略递归算法时间复杂度的分析

递归算法的优点是结构清晰,可读性强,而且容易用数学归纳法来证明算法的正确性,赢此为设计算法、调试程序带来很大的方便。

递归算法的运行效率较低,无论是耗费计算时间的还是占用存储空间的都比非递归算法要多。

时间复杂度分析:

迭代处理的循环体内部3个循环语句,每个循环语句都是一个嵌套的for循环,且它们的执行次数相同,基本语句是最内层循环体的赋值语句,即填写比赛日程表的元素。基本执行语句的执行次数是:

T(n)= 21*21=41

所以时间复杂度为O(4k)

4.3 分治策略非递归算法测试

给出输入情况:

得到输出结果:

消除文法的左递归实验

编译原理实验报告 实验名称 _____________ 消除文法的左递归__________________________ 实验时间 _____________________________________________ 院系 _________________________________________ 班级 ______________________________________________ 学号 ____________________________________________ 姓名

1. 试验目的 ?掌握和理解消除左递归(包括直接左递归和间接左递归)在构建 LL(1)文法的作用和目的 ?掌握消除左递归(包括直接左递归和间接左递归)的方法和步骤。 ?写出对于输入任意的上下文无关文法可以输出消除了左递归的等 价文法。 2. 实验原理 ?直接左递归的消除 消除产生式中的直接左递归是比较容易的。例如假设非终结符 P的规则为 P—P a/ B 其中,B是不以P开头的符号串。那么,我们可以把P的规则改写为 如下的非直接左递归形式:P—尸’ P'—P'£ 考虑更一般的情况,假定关于非终结符P的规则为 P—P a / P o2 / …/ P a n / [31 / [32 / …/ p m 其中,a (I = 1, 2,…,n)都不为£而每个p j (j = 1, 2,…,m) 都不以P开头,将上述规则改写为如下形式即可消除P的直接左递归: P— p l P'/ 32 P'/…/p m P' P' — 01P' / a P'/…/ a n P'/£

实验报告 分治与递归

实验报告分治与递归 中国矿业大学计算机科学与技术学院孟靖宇 一、实验目的与要求 1、熟悉C/C++语言的集成开发环境; 2、通过本实验加深对递归过程的理解 二、实验内容: 掌握递归算法的概念和基本思想,分析并掌握“整数划分”问题的递归算法。 三、实验题 任意输入一个整数,输出结果能够用递归方法实现整数的划分。 四、算法思想 对于数据n,递归计算最大加数等于x 的划分个数+最大加数不大于x-1的划分个数。最大加数x 从n 开始,逐步变小为n-1, (1) 考虑增加一个自变量:对于数据n,最大加数n1不大于m 的划分个数记作),(m n q 。则有: ???????>>=<==-+--+=1 1,1),()1,()1,(1),(1),(m n m n m n m n m m n q m n q n n q n n q m n q 五、代码实现 #include "stdafx.h" #include #include #include using namespace std; int q(intn,int m); int main(){ int n; cout<<"请输入要划分的整数:"<>n; int p=q(n,n); cout<<"正整数"<

return 0; } int q(intn,int m){ if((n<1)||(m<1)) return 0; if((n==1)||(m==1)) return 1; if(n

算法分析实验报告--分治策略

《算法设计与分析》实验报告 分治策略 姓名:XXX 专业班级:XXX 学号:XXX 指导教师:XXX 完成日期:XXX

一、试验名称:分治策略 (1)写出源程序,并编译运行 (2)详细记录程序调试及运行结果 二、实验目的 (1)了解分治策略算法思想 (2)掌握快速排序、归并排序算法 (3)了解其他分治问题典型算法 三、实验内容 (1)编写一个简单的程序,实现归并排序。 (2)编写一段程序,实现快速排序。 (3)编写程序实现循环赛日程表。设有n=2k个运动员要进行网球循环赛。现 要设计一个满足以下要求的比赛日程表:(1)每个选手必须与其它n-1个选手各赛一次(2)每个选手一天只能赛一场(3)循环赛进行n-1天 四、算法思想分析 (1)编写一个简单的程序,实现归并排序。 将待排序元素分成大小大致相同的2个子集合,分别对2个子集合进行 排序,最终将排好序的子集合合并成为所要求的排好序的集合。 (2)编写一段程序,实现快速排序。 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有 数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数 据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据 变成有序序列。 (3)编写程序实现循环日赛表。 按分治策略,将所有的选手分为两组,n个选手的比赛日程表就可以通

过为n/2个选手设计的比赛日程表来决定。递归地用对选手进行分割, 直到只剩下2个选手时,比赛日程表的制定就变得很简单。这时只要让 这2个选手进行比赛就可以了。 五、算法源代码及用户程序 (1)编写一个简单的程序,实现归并排序。 #include #include #define MAX 10 using namespace std; void merge(int array[],int p,int q,int r) { int i,k; int begin1,end1,begin2,end2; int* temp = new int[r-p+1]; begin1 = p; end1 = q; begin2 = q+1; end2 = r; k = 0; while((begin1 <= end1)&&(begin2 <= end2)) { if(array[begin1] < array[begin2]) { temp[k] = array[begin1]; begin1++; } else { temp[k] = array[begin2]; begin2++; } k++; } while(begin1 <= end1) {

递归与分治实验报告

递归与分治实验报告 班级:计科1102 姓名:赵春晓学号:2011310200631 实验目的:进一步掌握递归与分治算法的设计思想,通过实际问题来应用递归与分治设计算法。 实际问题:1集合划分问题,2输油管道问题,3邮局选址问题,4整数因子分解问题,5众数问题。 问题1:集合划分 算法思想:对于n个元素的集合,可以划分为由m个子集构成的集合,例如{{1,2}{3,4}}就是由2个子集构成的非空子集。假设f(n,m)表示将n个元素划分成由m个子集构成的集合的个数。那么1)若m == 1 ,则f(n,m)= 1 ;2)若n == m ,则f(n,m)= 1 ;3)若不是上面两种情况则有下面两种情况构成:3.1)向n-1个元素划分成的m个集合里面添加一个新的元素,则有m*f(n-1,m)种方法;3.2)向n-1个元素划分成的m-1个集合里添加一个由一个元素形成的独立的集合,则有f(n-1,m-1)种方法。 实验代码: #include #include using namespace std ; int jihehuafen( int n , int m ) { if( m == 1 || n == m ) return 1 ; else return jihehuafen( n - 1 , m - 1 ) + m*jihehuafen( n - 1 , m ) ; } int main() { ifstream fin("C:/input.txt") ; ofstream fout("C:/output.txt") ; int N , M , num ; fin >> N >> M ; num = jihehuafen( N , M) ; fout << num << endl ; return 0 ; } 问题2:输油管道 算法思想:由于主管道由东向西铺设。故主管道的铺设位置只和各油井的y坐标有关。要使主管道的y坐标最小,主管道的位置y坐标应是各个油井y坐标的中位数。先用快速排序法把各个油井的y坐标排序,然后取其中位数再计算各个油

算法设计与分析实验报告

本科实验报告 课程名称:算法设计与分析 实验项目:递归与分治算法 实验地点:计算机系实验楼110 专业班级:物联网1601 学号:2016002105 学生姓名:俞梦真 指导教师:郝晓丽

2018年05月04 日 实验一递归与分治算法 1.1 实验目的与要求 1.进一步熟悉C/C++语言的集成开发环境; 2.通过本实验加深对递归与分治策略的理解和运用。 1.2 实验课时 2学时 1.3 实验原理 分治(Divide-and-Conquer)的思想:一个规模为n的复杂问题的求解,可以划分成若干个规模小于n的子问题,再将子问题的解合并成原问题的解。 需要注意的是,分治法使用递归的思想。划分后的每一个子问题与原问题的性质相同,可用相同的求解方法。最后,当子问题规模足够小时,可以直接求解,然后逆求原问题的解。 1.4 实验题目 1.上机题目:格雷码构造问题 Gray码是一个长度为2n的序列。序列无相同元素,每个元素都是长度为n的串,相邻元素恰好只有一位不同。试设计一个算法对任意n构造相应的Gray码(分治、减治、变治皆可)。 对于给定的正整数n,格雷码为满足如下条件的一个编码序列。 (1)序列由2n个编码组成,每个编码都是长度为n的二进制位串。 (2)序列中无相同的编码。 (3)序列中位置相邻的两个编码恰有一位不同。 2.设计思想:

根据格雷码的性质,找到他的规律,可发现,1位是0 1。两位是00 01 11 10。三位是000 001 011 010 110 111 101 100。n位是前n-1位的2倍个。N-1个位前面加0,N-2为倒转再前面再加1。 3.代码设计:

消除左递归实验报告

共享知识分享快乐 编译原理实验报告 实验名称消除文法左递归 实验时间2014年12月12日 院系软件工程 ______________ 班级软件工程(2)班 学号E01214215 __________ 姓名刘翼________________

实验目的: 输入:任意的上下文无关文法。输出:消除了左递归的等价文法。 实验原理: 1.直接左递归的消除 消除产生式中的直接左递归是比较容易的。例如假设非终结符P 的规则为 P—P a / B 其中,B是不以P开头的符号串。那么,我们可以把P的规则改写为如下的非直接左递归形式:P —B P' P'—a P' / £ 这两条规则和原来的规则是等价的,即两种形式从P推出的符号串是相同的。 设有简单表达式文法G[E] : E —E+T/ T T —T*F/ F F —(E)/ I 经消除直接左递归后得到如下文法: E —TE' E ' —+TE' / £ T —FT' T' —*FT' / £ F —(E)/ I 考虑更一般的情况,假定关于非终结符P的规则为 P—P a 1 / P a 2 / …/ P a n / B 1 / B 2 / …/ B m 其中,a i (I = 1,2,…,n)都不为£,而每个B j (j = 1,2,…,m都不以P开头,将上述规则改写为如下形式即可消除P的直接左递归: P—B 1 P' / B 2 P' / …/ B m P' P' —a 1P' / a 2 P' / …/ a n P' / £ 2.间接左递归的消除 直接左递归见诸于表面,利用以上的方法可以很容易将其消除,即把直接左递归改写成直接右递归。然而文法表面上不存在左递归并不意味着该文法就不存在左递归了。有些文法虽然表面上不存在左递归,但却隐藏着左递归。例如,设有文法G[S] : S—Qc/ c Q—Rb/ b R—Sa/ a 虽不具有左递归,但S、Q R都是左递归的,因为经过若干次推导有 S Qc Rbc Sabc Q Rb Sab Qcab R Sa Qca Rbca

编译原理-实验二-递归下降分析程序构造

集美大学计算机工程学院实验报告 课程名称:编译原理 指导教师:付永钢 实验成绩: 实验编号: 实验二 实验名称:递归下降分析程序构造 班级:计算12 姓名: 学号: 上机实践日期:2014.11 上机实践时间: 4学时 一、实验目的 通过设计、编制、调试一个递归下降语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,掌握常用的语法分析方法。通过本实验,应达到以下目标: (1) 掌握从源程序文件中读取有效字符的方法和产生源程序内部表示文件的方法; (2)掌握语法分析的实现方法; (3)上机调试编出的语法分析程序。 二、实验环境 Windows7 x64、VC6.0 三、实验原理 递归下降法是语法分析中最易懂的一种方法。它的主要原理是,对每个非终结符按其产生式结构构造相应语法分析子程序,其中终结符产生匹配命令,而非终结符则产生过程调用命令。因为文法递归相应子程序也递归,所以称这种方法为递归子程序下降法或递归下降法。其中子程序的结构与产生式结构几乎是一致的。 递归下降分析程序的实现思想是:识别程序由一组子程序组成。每个子程序对应于一个非终结符号。每一个子程序的功能是:选择正确的右部,扫描完相应的字。在右部中有非终结符号时,调用该非终结符号对应的子程序来完成。 自上向下分析过程中,如果带回溯,则分析过程是穷举所有可能的推导,看是否能推导出待检查的符号串。分析速度慢。而无回溯的自上向下分析技术,可根据输入串的当前符号以及各产生式右部首符,选择某非终结符的产生式,效率高,且不易出错。 无回溯的自上向下分析技术可用的先决条件是:无左递归和无回溯。即:假设A 的全部产生式为A →α1|α2|……|αn ,则必须满足如下条件才能保证可以唯一的选择合适的产生式 First(A →αi )∩First (A →αj )=Φ,当i≠j. 无左递归:既没有直接左递归,也没有间接左递归。 无回溯:对于人以非中介符号U 的产生式右部n x x x |...||21,其对应的字的首终结符号两两不相交。 如果一个文法不含回路(形如P P +?的推导),也不含以ε为右部的产生式,那么可以通过执行消除左递归的算法消除文法的一切左递归。 四、实验内容 完成以下描述算术表达式的LL(1)文法的递归下降分析程序构造 G[E]: E →TE ′ E ′→+TE ′|ε T →FT ′

算法之2章递归与分治

算法分析(第二章):递归与分治法 一、递归的概念 知识再现:等比数列求和公式: 1、定义:直接或间接地调用自身的算法称为递归算法。 用函数自身给出定义的函数称为递归函数。 2、与分治法的关系: 由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。这自然导致递归过程的产生。分治与递归经常同时应用在算法设计之中,并由此产生许多高效算法。 3、递推方程: (1)定义:设序列01,....n a a a简记为{ n a},把n a与某些个() i a i n <联系起来的等式叫做关于该序列的递推方程。 (2)求解:给定关于序列{n a}的递推方程和若干初值,计算n a。 4、应用:阶乘函数、Fibonacci数列、Hanoi塔问题、插入排序 5、优缺点: 优点:结构清晰,可读性强,而且容易用数学归纳法来证明算法的正确性,因此它为设计算法、调试程序带来很大方便。 缺点:递归算法的运行效率较低,无论是耗费的计算时间还是占用的存储空间都比非递归算法要多。 二、递归算法改进: 1、迭代法: (1)不断用递推方程的右部替代左部 (2)每一次替换,随着n的降低在和式中多出一项 (3)直到出现初值以后停止迭代 (4)将初值代入并对和式求和 (5)可用数学归纳法验证解的正确性 2、举例: -----------Hanoi塔算法----------- ---------------插入排序算法----------- ()2(1)1 (1)1 T n T n T =?+ = ()(1)1 W n W n n W =?+? (1)=0

分治法实验报告一

宁波工程学院电信学院计算机系 实验报告 课程名称:算法设计与分析实验项目:用分治法算法解 最接近点对问题 指导教师:崔迪 实验位置:软件工程实验室姓名: 班级: 学号: 日期: 2016/10/12 一、实验目的 通过上机实验,要求掌握分治法算法的问题描述、算法设计思想、程序设 计和算法复杂性分析等。 二、实验环境: Eclipse 三、实验内容:用分治法解最接近点对问题 (1)问题描述 给定平面S上n个点,找其中的一对点,使得在n(n-1)/2 个点对中,该 点对的距离最小。 (2)算法设计思想 1. n较小时直接求 (n=2). 2.将S上的n个点分成大致相等的2个子集S1和S2 3.分别求S1和S2中的最接近点对 4.求一点在S1、另一点在S2中的最近点对 5.从上述三对点中找距离最近的一对.

(3)程序设计(程序清单及说明) package closestpair; import java.util.Arrays; import https://www.360docs.net/doc/7a14704774.html,parator; import java.util.Random; import java.util.Scanner; //定义坐标点 class Point { double x; double y; public Point(double x, double y) { this.x = x; this.y = y; } } // 根据x坐标排序 class MyComparatorX implements Comparator { @Override public int compare(Point p1, Point p2) { if (p1.x < p2.x) { return -1; } else if (p1.x > p2.x) { return 1; } else { return 0; } } } // 根据Y坐标排序 class MyComparatorY implements Comparator { @Override public int compare(Point p1, Point p2) { if (p1.y < p2.y) { return -1; } else if (p1.y > p2.y) { return 1; } else {

(完整word版)分治法循环赛日程表实验报告

西北农林科技大学信息工程学院《算法分析与设计》综合训练实习报告 题目:分治法循环赛日程表 学号 姓名 专业班级 指导教师 实践日期2011年5月16日-5月20日

目录 一、综合训练目的与要求 (1) 二、综合训练任务描述 (1) 三、算法设计 (1) 四、详细设计及说明 (3) 五、调试与测试 (4) 六、实习日志 (6) 七、实习总结 (6) 八、附录:核心代码清单 (6)

一、综合训练目的与要求 本综合训练是软件工程专业重要的实践性环节之一,是在学生学习完《算法分析》课程后进行的综合练习。本课综合训练的目的和任务: (1)巩固和加深学生对算法分析课程基本知识的理解和掌握; (2)培养利用算法知识解决实际问题的能力; (3)掌握利用程序设计语言进行算法程序的开发、调试、测试的能力; (4)掌握书写算法设计说明文档的能力; (5)提高综合运用算法、程序设计语言、数据结构知识的能力。 二、综合训练任务描述 假设有n=2k 个运动员要进行网球循环赛。设计一个满足一下要求的比赛日程表:(1)每个选手必须与其他n-1个选手各赛一次 (2)每个选手一天只能赛一次 (3)循环赛一共进行n-1天 利用Java语言开发一个界面,输入运动员的个数,输出比赛日程表。对于输入运动员数目不满足n=2k时,弹出信息提示用户。 三、算法设计 (1) 文字描述 假设n位选手顺序编号为1,2,3……n,比赛的日程表是一个n行n-1列的表格。第i行j列表示第i号选手在第j天的比赛对手,根据分治法,要求n个选手的比赛日程,只要知道其中一半的比赛日程,所以使用递归最终可以分到计算两位选手的比赛日程,然后逐级合并,得出结果。 (2) 框图

编译原理实验报告

院系:计算机科学学院 专业、年级: 07计科2大班 课程名称:编译原理 学号姓名: 指导教师: 2010 年11月17 日 组员学号姓名

实验 名称 实验一:词法分析实验室9205 实验目的或要求 通过设计一个具体的词法分析程序,加深对词法分析原理的理解。并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。 编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值。 具体要求:输入为某语言源代码,达到以下功能: 程序输入/输出示例:如源程序为C语言。输入如下一段: main() { int a,b; a=10; b=a+20; } 要求输出如下(并以文件形式输出或以界面的形式输出以下结果)。 (2,”main”) (5,”(“) (5,”)“) (5,”{“} (1,”int”) (2,”a”) (5,”,”) (2,”b”) (5,”;”) (2,”a”) (4,”=”) (3,”10”) (5,”;”) (2,”b”) (4,”=”) (2,”a”) (4,”+”) (3,”20”) (5,”;”) (5,”}“) 要求: 识别保留字:if、int、for、while、do、return、break、continue等等,单词种别码为1。 其他的标识符,单词种别码为2。常数为无符号数,单词种别码为3。 运算符包括:+、-、*、/、=、>、<等;可以考虑更复杂情况>=、<=、!= ;单词种别码为4。分隔符包括:“,”“;”“(”“)”“{”“}”等等,单词种别码为5。

算法设计与分析:递归与分治法-实验报告

应用数学学院信息安全专业班学号姓名 实验题目递归与分治法 综合实验评分表

实验报告 一、实验目的与要求 1.掌握递归算法的设计思想 2.掌握分治法设计算法的一般过程 3.理解并掌握算法渐近时间复杂度的分析方法 二、实验内容 1、折半查找的递归算法 (1)源程序代码 #include #include using namespace std; int bin_search(int key[],int low, int high,int k) { int mid; if(low>high) return -1; else{ mid = (low+high) / 2; if(key[mid]==k) return mid; if(k>key[mid]) return bin_search(key,mid+1,high,k); else return bin_search(key,low,mid-1,k); } } int main() { int n , i , addr; int A[10] = {2,3,5,7,8,10,12,15,19,21}; cout << "在下面的10个整数中进行查找" << endl; for(i=0;i<10;i++){ cout << A[i] << " " ; } cout << endl << endl << "请输入一个要查找的整数" << endl; cin >> n; addr = bin_search(A,0,9,n);

if(-1 != addr) cout << endl << n << "是上述整数中的第" << addr << "个数" << endl; else cout << endl << n << "不在上述的整数中" << endl << endl; getchar(); return 0; } (2)运行界面 ①查找成功 ②查找失败

算法分析实验报告--分治策略

分治策略 姓名:XXX 专业班级:XXX 学号:XXX 指导教师:XXX 完成日期:XXX

一、试验名称:分治策略 (1)写出源程序,并编译运行 (2)详细记录程序调试及运行结果 二、实验目的 (1)了解分治策略算法思想 (2)掌握快速排序、归并排序算法 (3)了解其他分治问题典型算法 三、实验内容 (1)编写一个简单的程序,实现归并排序。 (2)编写一段程序,实现快速排序。 (3)编写程序实现循环赛日程表。设有n=2k个运动员要进行网球循环赛。现 要设计一个满足以下要求的比赛日程表:(1)每个选手必须与其它n-1个选手各赛一次(2)每个选手一天只能赛一场(3)循环赛进行n-1天 四、算法思想分析 (1)编写一个简单的程序,实现归并排序。 将待排序元素分成大小大致相同的2个子集合,分别对2个子集合进行 排序,最终将排好序的子集合合并成为所要求的排好序的集合。 (2)编写一段程序,实现快速排序。 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有 数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数 据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据 变成有序序列。 (3)编写程序实现循环日赛表。 按分治策略,将所有的选手分为两组,n个选手的比赛日程表就可以通 过为n/2个选手设计的比赛日程表来决定。递归地用对选手进行分割, 直到只剩下2个选手时,比赛日程表的制定就变得很简单。这时只要让

这2个选手进行比赛就可以了。 五、算法源代码及用户程序 (1)编写一个简单的程序,实现归并排序。 #include #include<> #define MAX 10 using namespace std; void merge(int array[],int p,int q,int r) { int i,k; int begin1,end1,begin2,end2; int* temp = new int[r-p+1]; begin1 = p; end1 = q; begin2 = q+1; end2 = r; k = 0; while((begin1 <= end1)&&(begin2 <= end2)) { if(array[begin1] < array[begin2]) { temp[k] = array[begin1]; begin1++; } else { temp[k] = array[begin2]; begin2++; } k++; } while(begin1 <= end1) { temp[k++] = array[begin1++]; }

编译原理实验报告

学生学号0120810680316 实验课成绩 武汉理工大学 学生实验报告书 实验课程名称《编译原理》 开课学院计算机科学与技术学院 指导老师姓名何九周 学生姓名刘洋 学生专业班级软件工程0803 2010 —2011 学年第二学期

实验课程名称:编译原理 实验项目名称单词的词法分析程序设计实验成绩实验者刘洋专业班级软件0803 组别 同组者实验日期 2011 年 5 月 17日 第一部分:实验分析与设计(可加页) 一、实验内容描述(问题域描述) 实验目的: 设计,编制并调试一个词法分析程序,加深对词法分析原理的理解。 实验要求: 在上机前应认真做好各种准备工作,熟悉机器的操作系统和语言的集成环境,独立完成算法编制和程序代码的编写;上机时应随带有关的高级语言教材或参考书;要学会程序调试与纠错;每次实验后要交实验报告。 实验题目: 对于给定的源程序(如C语言或Pascal等),要求从组成源程序的字符行中寻找出单词,并给出它们的种别和属性——输出二元组序列。以便提供给语法分析的时候使用。要求能识别所有的关键字,标志符等,并且能够对出先的一些词法规则的错误进行必要的处理。 二、实验基本原理与设计(包括实验方案设计,实验手段的确定,试验步骤等,用硬件逻辑或 者算法描述) 实验原理: 由于这是一个用高级语言编写一个词法分析器,使之能识别输入串,并把分析结果(单词符号,标识符,关键字等等)输出.输入源程序,输入单词符号,本词法分析器可以辨别关键字,标识符,常数,运算符号和某些界符,运用了文件读入来获取源程序代码,再对该源程序代码进行词法分析,这就是词法分析器的基本功能.当词法分析器调用预处理子程序处理出一串输入字符放进扫描缓冲区之后,分析器就从此缓冲区中逐一识别单词符号.当缓冲区里的字符串被处理完之后,它又调用预处理子程序来处理新串. 编写的时候,使用了文件的输入和输出,以便于词法分析的通用型,同时在文件输出时,并保存在输出文件output文件中。 从左到右扫描程序,通过初始化:1为关键字;2为标志符; 3为常数;4为运算符或界符。 三、主要仪器设备及耗材 计算机

算法实验报告

实验一分治与递归算法的应用 一、实验目的 1.掌握分治算法的基本思想(分-治-合)、技巧和效率分析方法。 2.熟练掌握用递归设计分治算法的基本步骤(基准与递归方程)。 3.学会利用分治算法解决实际问题。 二 . 实验内容 金块问题 老板有一袋金块(共n块,n是2的幂(n≥2)),最优秀的雇员得到其中最重的一块,最差的雇员得到其中最轻的一块。假设有一台比较重量的仪器,希望用最少的比较次数找出最重和最轻的金块。并对自己的程序进行复杂性分析。 三.问题分析: 一般思路:假设袋中有n 个金块。可以用函数M a x(程序 1 - 3 1)通过n-1次比较找到最重的金块。找到最重的金块后, 可以从余下的n-1个金块中用类似法通过n-2次比较找出最轻的金块。这样,比较的总次数为2n-3。

分治法:当n很小时,比如说,n≤2,识别出最重和最轻的金块,一次比较就足够了。当n 较大时(n>2),第一步,把这袋金块平分成两个小袋A和B。第二步,分别找出在A和B中最重和最轻的金块。设A中最重和最轻的金块分别为HA 与LA,以此类推,B中最重和最轻的金块分别为HB 和LB。第三步,通过比较HA 和HB,可以找到所有金块中最重的;通过比较LA 和LB,可以找到所有金块中最轻的。在第二步中,若n>2,则递归地应用分而治之方法 程序设计 据上述步骤,可以得出程序1 4 - 1的非递归代码。该程序用于寻找到数组w [ 0 : n - 1 ]中的最小数和最大数,若n < 1,则程序返回f a l s e,否则返回t r u e。 当n≥1时,程序1 4 - 1给M i n和M a x置初值以使w [ M i n ]是最小的重量,w [ M a x ]为最大的重量。 首先处理n≤1的情况。若n>1且为奇数,第一个重量w [ 0 ]将成为最小值和最大值的候选值,因此将有偶,数个重量值w [ 1 : n - 1 ]参与f o r循环。当n 是偶数时,首先将两个重量值放在for 循环外进行比较,较小和较大的重量值分别置为Min和Max,因此也有偶数个重量值w[2:n-1]参与for循环。 在for 循环中,外层if 通过比较确定( w [ i ] , w [ i + 1 ] )中的较大和较小者。此工作与前面提到的分而治之算法步骤中的2) 相对应,而内层的i f负责找出较小重量值和较大重量值中的最小值和最大值,

编译原理语法分析实验报告

编译原理实验报告 实验名称:编写语法分析程序 实验类型:设计性实验 指导教师:蒋勇 专业班级:软件工程1401 姓名:**** 学号:********** 实验地点:东六E座301 实验成绩:_________________ 日期:2016年5月17日

实验一 编写词法分析程序 一、实验目的: 1.设计、编写、调试一个递归下降分析程序,实现对词法分析程序提供的 单词序列进行语法检查和结构分析。 2.掌握递归下降语法分析方法。 3.巩固理论知识。 二、实验设计: 1.设计原理: 1)对于文法的每一个非终结符U的文法规则是一个识别U的过程定义, 为每一个非终结符构造子程序。 2)如果U的右部符号串只有一个候选式则从左到右依次构造U的识别 代码。 3)如果U的右部符号串有终结符号,则判断输入的符号是否匹配终结 符号,如果相等,则读入下一个符号;如果不相等,则有语法错误, 应当报错。 4)如果是非终结符号,则调用非终结符号的子程序即可。 5)如果U的右部有多个候选式,应该根据每个候选式的第一个符号来 确定该分支。 6)对于含有ε表达式的文法规则需要判断输入的符号是否在U的 FOLLOW集里面。 2.设计方法: (1)文法改造,消除二义性; (2)对含有左递归或者左公因子的文法消除左递归,提取左公因子; (3)求每一个右部符号串的FIRST集合,如果右部含有ε,则需要求出其 产生式左部非终结符的FOLLOW集。判断文法是否是LL(1)文法, 若不是LL(1)文法,说明文法的复杂性超过自顶向下方法的分析能力。 (4)根据改写后的文法设计程序,依据设计原理构造每一个非终结符的子 程序。 3.设计过程: (1)改写文法、消除左递归(将左递归改为右递归)、提取左公因子; (2)求出相应的First集和Follow集; (3)设计程序流程图,设计程序; (4)编写程序; 4.框架思路,错误信息输出: 对每一个非终结符构造其子程序,设定一个返回值。如果语法分析有错 则返回1,没有错误就返回0;对于错误,在程序的相应行数报错。各 个非终结符之间依据文法规则调用。每次遇到终结符函数都判断是否匹 配当前终结符号,如果不匹配则报错,返回1。如果匹配,则读入下一

分治算法实验报告

算法分析与设计实验报告 第 1 次实验

附录:完整代码 SelectMaxMin.cpp: #include #include #include #include #include using namespace std; void SelectMaxMin(int *a,inti,intj,int&max,int&min) { if(i==j) { max= a[i]; min =a[i]; return; } else { int mid=(i+j)/2; intmaxi,maxj,mini,minj; SelectMaxMin(a,i,(i+j)/2,maxi,mini); SelectMaxMin(a,((i+j)/2)+1,j,maxj,minj); if(maxi>maxj) max=maxi; else max=maxj; if(mini

else min=minj; return; } } intmain() { clock_tstart,end,over; start=clock(); end=clock(); over=end-start; start=clock(); //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int m; cout<<"Please input the number : "; cin>> m; int a[m]; srand((unsigned int)time(NULL)); cout<< "随机产生的数据(0-100):"; for(inti=0; i

LL1语法分析实验报告

LL(1)语法分析 一,实验名称: 实现LL分析。 二,实验要求: 输入任意文法 消除左递归 消除左因子 测试任意输入语句是否合法 数据结构描述 算法说明 输出first集合 输出follow集合 输出LL(1)表 三.设计原理及算法描述 所谓LL(1)分析法,就是指从左到右扫描输入串(源程序),同时采用最左推导,且对每次直接推导只需向前看一个输入符 号,便可确定当前所应当选择的规则。实现LL(1)分析的程 序又称为LL(1)分析程序或LL1(1)分析器。 一个文法要能进行LL(1)分析,那么这个文法应该满足:无 二义性,无左递归,无左公因子。当文法满足条件后,再分别

构造文法每个非终结符的FIRST和FOLLOW集合,然后根据FIRST和FOLLOW集合构造LL(1)分析表,最后利用分析表,根据LL(1)语法分析构造一个分析器。LL(1)的语法分析程序包含了三个部分,总控程序,预测分析表函数,先进先出的语法分析栈,本程序也是采用了同样的方法进行语法分析,该程序是采用了C语言来编写,其逻辑结构图如下: LL(1)预测分析程序的总控程序在任何时候都是按STACK栈顶符号X和当前的输入符号a做哪种过程的。对于任何(X,a),

总控程序每次都执行下述三种可能的动作之一: (1)若X = a =‘#’,则宣布分析成功,停止分析过程。(2)若X = a ‘#’,则把X从STACK栈顶弹出,让a指向下一个输入符号。 (3)若X是一个非终结符,则查看预测分析表M。若M[A,a]中存放着关于X的一个产生式,那么,首先把X弹出STACK 栈顶,然后,把产生式的右部符号串按反序一一弹出STACK 栈(若右部符号为ε,则不推什么东西进STACK栈)。若M[A,a]中存放着“出错标志”,则调用出错诊断程序ERROR。 事实上,LL(1)的分析是根据文法构造的,它反映了相应文法所定义的语言的固定特征,因此在LL(1)分析器中,实际上是以LL(1)分析表代替相应方法来进行分析的。 2.构造LL(1)分析表 考查文法G[E]: E→E+T | T T→T*F | F F→( E ) | i | x | y 我们容易看出此文法没有左公因子也没有二义性,但却存在两个直接左递归,这里我们利用引入新非终结符的方法来消除它使方法满足要求,即: 对形如:U→Ux|y的产生式(其中x,y V+ ,y不以U开头),引入一个新的非终结符U’后,可以等价地改写成为:

实验二--LL(1)分析法实验报告

实验二LL(1)分析法 一、实验目的 通过完成预测分析法的语法分析程序,了解预测分析法和递归子程序法的区别和联系。使学生了解语法分析的功能,掌握语法分析程序设计的原理和构造方法,训练学生掌握开发应用程序的基本方法。有利于提高学生的专业素质,为培养适应社会多方面需要的能力。 二、实验内容及设计原理 所谓LL(1)分析法,就是指从左到右扫描输入串(源程序),同时采用最左推导,且对每次直接推导只需向前看一个输入符号,便可确定当前所应当选择的规则。实现LL(1)分析的程序又称为LL(1)分析程序或LL1(1)分析器。 我们知道一个文法要能进行LL(1)分析,那么这个文法应该满足:无二义性,无左递归,无左公因子。当文法满足条件后,再分别构造文法每个非终结符的FIRST和FOLLOW集合,然后根据FIRST和FOLLOW集合构造LL(1)分析表,最后利用分析表,根据LL(1)语法分析构造一个分析器。LL(1)的语法分析程序包含了三个部分,总控程序,预测分析表函数,先进先出的语法分析栈,本程序也是采用了同样的方法进行语法分析,该程序是采用了C++语言来编写,其逻辑结构图如下: LL(1)预测分析程序的总控程序在任何时候都是按STACK栈顶符号X和当前的输入符号a做哪种过程的。对于任何(X,a),总控程序每次都执行下述

三种可能的动作之一: (1)若X = a =‘#’,则宣布分析成功,停止分析过程。 (2)若X = a ‘#’,则把X从STACK栈顶弹出,让a指向下一个输入符号。 (3)若X是一个非终结符,则查看预测分析表M。若M[A,a]中存放着关于X的一个产生式,那么,首先把X弹出STACK栈顶,然后,把产生式的右部符号串按反序一一弹出STACK栈(若右部符号为ε,则不推什么东西进STACK栈)。若M[A,a]中存放着“出错标志”,则调用出错诊断程序ERROR。 三、程序结构描述 1、定义的变量 初始化预测分析表: LL E[8]={"TG","TG","error","error","error","error","error","error"}; LL G[8]={"error","error","null","+TG","-TG","error","error","null"}; LL T[8]={"FS","FS","error","error","error","error","error","error"}; LL S[8]={"error","error","null","null","null","*FS","/FS","null"}; LL F[8]={"i","(i)","error","error","error","error","error","error"}; const int MaxLen=10; 初始化栈的长度 const int Length=10; 初始化数组长度 char Vn[5]={'E','G','T','S','F'}; 非终结符数组 char Vt[8]={'i','(',')','+','-','*','/','#'}; 终结符数组 char ch,X; /全局变量,ch用于读当前字符,X用于获取栈顶元素 char strToken[Length]; 存储规约表达式 2、定义的函数

实验1++递归与分治算法

淮海工学院计算机工程学院实验报告书 课程名:《算法分析与设计》 题目:实验1 递归与分治算法 班级: 学号: 姓名:

实验1 递归与分治算法 实验目的和要求 (1)进一步掌握递归算法的设计思想以及递归程序的调试技术; (2)理解这样一个观点:分治与递归经常同时应用在算法设计之中。 (3)分别用蛮力法和分治法求解最近对问题; (4)分析算法的时间性能,设计实验程序验证分析结论。 实验内容 设p1=(x1, y1), p2=(x2, y2), …, pn=(xn, yn)是平面上n个点构成的集合S,设计算法找出集合S中距离最近的点对。 实验环境 Turbo C 或VC++ 实验学时 2学时,必做实验 数据结构与算法 核心源代码 蛮力法: #include #include #include int ClosestPoints(int x[ ], int y[ ], int n); int main() { int x[3],y[3]; printf("请输入各点的横坐标: "); for(int i=0;i<4;i++) { scanf("%d",&x[i]); } printf("请输入各点的纵坐标: "); for(int j=0;j<4;j++)

{ scanf("%d",&y[i]); } ClosestPoints(x,y,4); return 0; } int ClosestPoints(int x[ ], int y[ ], int n) { int index1, index2; //记载最近点对的下标 int d, minDist = 1000; //假设最大距离不超过1000 for (int i = 0; i < n - 1; i++) for (int j = i + 1; j < n; j++) //只考虑i<j的点对 { d =sqrt ((x[i]-x[j])* (x[i]-x[j]) + (y[i]-y[j])* (y[i]-y[j])); if (d < minDist) { minDist = d; index1 = i; index2 = j; } } cout<<"最近的点对是:"< #include const int n = 4; struct point //定义点的结构体 { int x, y; };

相关文档
最新文档