递归与非递归的比较

递归与非递归的比较

非递归效率高;递归代码写出来思路清晰,可读性强。

生成可执行文件大小应该和编译器有关吧。。。。

递归的话函数调用是有开销的,而且递归的次数受堆栈大小的限制。

以二叉树搜索为例:

bool search(btree* p, int v)

{

if (null == p)

return false;

if (v == p->v)

return true

else

{

if (v

v)

return search(p->left, v);

else

return search(p->right, v);

}

}

如果这个二叉树很庞大,反复递归函数调用开销就很大,万一堆栈溢出怎么办? 现在我们用循环改写:

bool search(btree* p, int v)

{

while (p)

{

if (v == p->v)

return true;

else

{

if (v

v)

p = p->left;

else

p = p->right;

}

}

return false;

}

---------------------------------------------------------------------------------------------------------

递归好处:代码更简洁清晰,可读性更好

递归可读性好这一点,对于初学者可能会反对。实际上递归的代码更清晰,但是从学习的角度要理解递归真正发生的什么,是如何调用的,调用层次和路线,调用堆栈中保存了什么,可能是不容易。但是不可否认递归的代码更简洁。一般来说,一个人可能很容易的写出前中后序的二叉树遍历的递归算法,要写出相应的非递归算法就比较考验水平了,恐怕至少一半的人搞不定。所以说递归代码更简洁明了。

递归坏处:由于递归需要系统堆栈,所以空间消耗要比非递归代码要大很多。而且,如果递归深度太大,可能系统撑不住。

楼上的有人说:

小的简单的用循环,,

太复杂了就递归吧,,免得循环看不懂

话虽然简单,其实非常有道理:对于小东西,能用循环干嘛要折腾?如果比较复杂,在系统撑的住的情况下,写递归有利于代码的维护(可读性好) 都可以用循环来避免递归,更复杂的情况则要引入栈来进行压栈出栈来改造成非递归,这个栈不一定要严格引入栈数据结构,只需要有这样的思路,用数组什么的就可以。

至于教科书上喜欢n!的示例,我想只是便于递归思路的引进和建立。真正做代码不可能的。 --------------------------------------------------------------------------------------------------------------------

循环方法比递归方法快, 因为循环避免了一系列函数调用和返回中所涉及到的参数传递和返回值的额外开销。

递归和循环之间的选择。一般情况下, 当循环方法比较容易找到时, 你应该避免使用递归。这在问题可以按照一个递推关系式来描述时, 是时常遇到的, 比如阶乘问题就是这种情况。 反过来, 当很难建立一个循环方法时, 递归就是很好的方法。实际上, 在某些情形下, 递归方法总是显而易见的, 而循环方法却相当难找到。当某些问题的底层数据结构本身就是递归时, 则递归也就是最好的方法了。

----------------------------------------------------------------------------------------------------------------------

递归其实是方便了程序员难为了机器。它只要得到数学公式就能很方便的写出程序。优点就是易理解,容易编程。但递归是用栈机制实现的(c++),每深入一层,都要占去一块栈数据区域,对嵌套层数深的一些算法,递归会力不从心,空间上会以内存崩溃而告终,而且递归也带来了大量的函数调用,这也有许多额外的时间开销。所以在深度大时,它的时空性就不好了。

循环其缺点就是不容易理解,编写复杂问题时困难。优点是效率高。运行时间只因循环次数增加而增加,没什么额外开销。空间上没有什么增加。

----------------------------------------------------------------------------------------------------------------------

递归算法与迭代算法的设计思路区别在于:函数或算法是否具备收敛性,当且仅当一个算法存在预期的收敛效果时,采用递归算法才是可行的,否则,就不能使用递归算法。 当然,从理论上说,所有的递归函数都可以转换为迭代函数,反之亦然,然而代价通常都是比较高的。

但从算法结构来说,递归声明的结构并不总能够转换为迭代结构,原因在于结构的引申本身属于递归的概念,用迭代的方法在设计初期根本无法实现,这就像动多态的东西并不总是可以用静多态的方法实现一样。这也是为什么在结构设计时,通常采用递归的方式而不是采用迭代的方式的原因,一个极典型的例子类似于链表,使用递归定义及其简单,但对于内存定义(数组方式)其定义及调用处理说明就变得很晦涩,尤其是在遇到环链、图、网格等问题时,使用迭代方式从描述到实现上都变得很不现实。

===============================================================================

把递归函数转换成非递归程序的一般方法

把递归算法转化为非递归算法有如下三种基本方法:

(1). 通过分析,跳过分解过程,直接用循环结构的算法实现求解过程。

(2). 自己用栈模拟系统的运行时栈,通过分析只保存必须保存的信息,从而用非递归算法替代递归算法。

(3). 利用栈保存参数,由于栈的后进先出特性吻合递归算法的执行过程,因而可以用非递归算法替代递归算法。

● 递归函数的原理

用栈保存未完成的工作,在适当的时候从栈中取出并执行。

系统保存了工作的数据和状态,数据就是函数的局部变量,

状态就是程序指针。

● 非递归程序原理

1. 和递归函数的原理相同,只不过是把由系统负责保存工作

信息变为程序自己保存,这样能减少保存数据的冗余(主要是

节省了局部变量的空间),提高存储效率。

2. 把程序要完成的工作分成两类:手头工作和保存在栈中的

待完成的工作。手头工作指程序正在做的工作。由于某些工作

不能一步完成,必须暂缓完成,于是可把它保存在栈中,这就

是待完成的工作。

3. 手头工作必须有其结束条件,不能永远做下去;保存的

待完成工作必须含有完成该项工作的所有必要信息。

4. 程序必须有秩序地完成各项工作。如,可把手头工作恰当

处理(直接处理或暂时保存)后,才能继续接手下一步的工作。

5. 待完成工作必须转换成手头工作才能处理。

● 栈的大小

所有递归问题,其递归过程可以展开成一棵树,叶子节点是

可解的,按照问题的要求,处理所有叶子节点,就可解决

问题本身。可能需要保存(Data, Status),Data是工作数据,

Status是工作状态;(Data, Status)决定了整个工作。

栈的大小等于树的高度-1,-1是因为根节点不需保存。

● 举例

例1. 汉诺塔问题

递归函数:

void Hanoi(UINT x, UINT y, UINT n)

// x Source

// y Destination

// n Number of plates

{

if (n == 0) return;

Hanoi(x, x^y, n-1);

Move(x, y);

Hanoi(x^y, y, n-1);

}

说明:x、y可取1、2、3三数之一,并且x≠y,x^y表示x、y按位异或,

得到除x、y之外的第三个数。1^2=3, 1^3=2, 2^3=1

非递归程序:

#define N 5

tyepdef struct _HANOIDATA

{

UINT x;

UINT y;

UINT n;

}HANOIDATA;

void Hanoi(HANOIDATA hanoiData)

{

HANOIDATA stack[N];

int top = -1; // stack pointer

while (hanoiData.n || top != -1) // 存在手头工作或待完成工作

{

while (hanoiData.n) // 处理手头工作直到无现成的手头工作,

// 即下次的手头工作必须从栈中取得

{

hanoiData.n --;

stack[++top] = hanoiData; // 保存待完成工作

hanoiData.y ^= hanoiData.x; // 新的手头工作

}

if (top != -1) // 存在待完成工作

{

hanoiData = stack[top--]; // 从栈中取出

Move(hanoiData.x, hanoiData.y); // 直接处理

hanoiData.x ^= hanoiData.y; // 未处理完的转换成手头工作

}

}

}

例2. 后根序遍历二叉树

递归函数:

void PostTraverse(BINARYTREE root)

{

if (root == NULL) return;

PostTraverse(root->LChild);

PostTraverse(root->RChild);

Visit(root);

}

非递归程序:

void PostTraverse(BINARYTREE p)

{

while ( p != NULL || !Stack.IsEmpty() )// 存在工作(手头或待完成)

{

while (p != NULL) // 处理手头工作,直到无现成手头工作

{

Stack.Push(p, RCHILD_AND_ITSELF);

p = p->LChild;

}

if (!Stack.IsEmpty()) // 是否存在待完成工作

{

Stack.Pop(p, Tag);

if (Tag == RCHILD_AND_ITSELF) // 情况一: RChild & Itself {

Stack.Push(p, ONLY_ITSELF) // 保存待完成工作

p = p->RChild; // 新的手头工作

}

else // tag == ONLY_ITSELF, 情况二: Only Itself

{

visit(p);

p = NULL; // 已无现成的手头工作

}

}

}

}

● 总结

非递归程序的设计应注意:

1. 保存暂缓执行的工作

2. 无现成手头工作的条件

3. 无待完成工作的条件

程序模式

void NonRecursiveFunction(DATATYPE Data)

{

while ( ExistHandyWork() || ExistSavedWork() )

{

while ( ExistHandyWork() )

{

Process(Work, Status) // Probably push work onto stack

NewHandyWork();

}

if ( ExistSavedWork() )

{

Pop(Work, Status);

Process(Work, Status); // Probably generate new handy work }

}

}

===================================================================

递归算法向非递归算法转换

递归算法实际上是一种分而治之的方法,它把复杂问题分解为简单问题来求解。对于某些复杂问题(例如hanio塔问题),递归算法是一种自然且合乎逻辑的解决问题的方式,但是递归算法的执行效率通常比较差。因此,在求解某些问题时,常采用递归算法来分析问题,用非递归算法来求解问题;另外,有些程序设计语言不支持递归,这就需要把递归算法转换为非递归算法。

将递归算法转换为非递归算法有两种方法,一种是直接求值,不需要回溯;另一种是不能直接求值,需要回溯。前者使用一些变量保存中间结果,称为直接转换法;后者使用栈保存中间结果,称为间接转换法,下面分别讨论这两种方法。

1. 直接转换法

直接转换法通常用来消除尾递归和单向递归,将递归结构用循环结构来替代。

尾递归是指在递归算法中,递归调用语句只有一个,而且是处在算法的最后。例如求阶乘的递归算法:

long fact(int n)

{

if (n==0) return 1;

else return n*fact(n-1);

}

当递归调用返回时,是返回到上一层递归调用的下一条语句,而这个返回位置正好是算法的结束处,所以,不必利用栈来保存返回信息。对于尾递归形式的递归算法,可以利用循环结构来替代。例如求阶乘的递归算法可以写成如下循环结构的非递归算法:

long fact(int n)

{

int s=0;

for (int i=1; i

s=s*i; //用s保存中间结果

return s;

}

单向递归是指递归算法中虽然有多处递归调用语句,但各递归调用语句的参数之间没有关系,并且这些递归调用语句都处在递归算法的最后。显然,尾递归是单向递归的特例。例如求斐波那契数列的递归算法如下:

int f(int n)

{

if (n= =1 | | n= =0) return 1;

else return f(n-1)+f(n-2);

}

对于单向递归,可以设置一些变量保存中间结构,将递归结构用循环结构来替代。例如求斐波那契数列的算法中用s1和s2保存中间的计算结果,非递归函数如下:

int f(int n)

{

int i, s;

int s1=1, s2=1;

for (i=3; i

{

s=s1+s2;

s2=s1; // 保存f(n-2)的值

s1=s; //保存f(n-1)的值

}

return s;

}

2. 间接转换法

该方法使用栈保存中间结果,一般需根据递归函数在执行过程中栈的变化得到。其一般过程如下:

将初始状态s0进栈

while (栈不为空)

{

退栈,将栈顶元素赋给s;

if (s是要找的结果) 返回;

else

{

寻找到s的相关状态s1;

将s1进栈

}

}

间接转换法在数据结构中有较多实例,如二叉树遍历算法的非递归实现、图的深度优先遍历算法的非递归实现等等。

使用非递归方式实现递归问题的算法程序,不仅可以节省存储空间,而且可以极大地提高算法程序的执行效率。本文将递归问题分成简单递归问题和复杂递归问题;简单递归问题的非

递归实现采用递推技术加以求解,复杂递归问题则根据问题求解的特点采用两类非递归实现算法,使用栈加以实现。

递归与非递归的比较

非递归效率高;递归代码写出来思路清晰,可读性强。

生成可执行文件大小应该和编译器有关吧。。。。

递归的话函数调用是有开销的,而且递归的次数受堆栈大小的限制。

以二叉树搜索为例:

bool search(btree* p, int v)

{

if (null == p)

return false;

if (v == p->v)

return true

else

{

if (v

v)

return search(p->left, v);

else

return search(p->right, v);

}

}

如果这个二叉树很庞大,反复递归函数调用开销就很大,万一堆栈溢出怎么办? 现在我们用循环改写:

bool search(btree* p, int v)

{

while (p)

{

if (v == p->v)

return true;

else

{

if (v

v)

p = p->left;

else

p = p->right;

}

}

return false;

}

---------------------------------------------------------------------------------------------------------

递归好处:代码更简洁清晰,可读性更好

递归可读性好这一点,对于初学者可能会反对。实际上递归的代码更清晰,但是从学习的角度要理解递归真正发生的什么,是如何调用的,调用层次和路线,调用堆栈中保存了什么,可能是不容易。但是不可否认递归的代码更简洁。一般来说,一个人可能很容易的写出前中后序的二叉树遍历的递归算法,要写出相应的非递归算法就比较考验水平了,恐怕至少一半的人搞不定。所以说递归代码更简洁明了。

递归坏处:由于递归需要系统堆栈,所以空间消耗要比非递归代码要大很多。而且,如果递归深度太大,可能系统撑不住。

楼上的有人说:

小的简单的用循环,,

太复杂了就递归吧,,免得循环看不懂

话虽然简单,其实非常有道理:对于小东西,能用循环干嘛要折腾?如果比较复杂,在系统撑的住的情况下,写递归有利于代码的维护(可读性好) 都可以用循环来避免递归,更复杂的情况则要引入栈来进行压栈出栈来改造成非递归,这个栈不一定要严格引入栈数据结构,只需要有这样的思路,用数组什么的就可以。

至于教科书上喜欢n!的示例,我想只是便于递归思路的引进和建立。真正做代码不可能的。 --------------------------------------------------------------------------------------------------------------------

循环方法比递归方法快, 因为循环避免了一系列函数调用和返回中所涉及到的参数传递和返回值的额外开销。

递归和循环之间的选择。一般情况下, 当循环方法比较容易找到时, 你应该避免使用递归。这在问题可以按照一个递推关系式来描述时, 是时常遇到的, 比如阶乘问题就是这种情况。 反过来, 当很难建立一个循环方法时, 递归就是很好的方法。实际上, 在某些情形下, 递归方法总是显而易见的, 而循环方法却相当难找到。当某些问题的底层数据结构本身就是递归时, 则递归也就是最好的方法了。

----------------------------------------------------------------------------------------------------------------------

递归其实是方便了程序员难为了机器。它只要得到数学公式就能很方便的写出程序。优点就是易理解,容易编程。但递归是用栈机制实现的(c++),每深入一层,都要占去一块栈数据区域,对嵌套层数深的一些算法,递归会力不从心,空间上会以内存崩溃而告终,而且递归也带来了大量的函数调用,这也有许多额外的时间开销。所以在深度大时,它的时空性就不好了。

循环其缺点就是不容易理解,编写复杂问题时困难。优点是效率高。运行时间只因循环次数增加而增加,没什么额外开销。空间上没有什么增加。

----------------------------------------------------------------------------------------------------------------------

递归算法与迭代算法的设计思路区别在于:函数或算法是否具备收敛性,当且仅当一个算法存在预期的收敛效果时,采用递归算法才是可行的,否则,就不能使用递归算法。 当然,从理论上说,所有的递归函数都可以转换为迭代函数,反之亦然,然而代价通常都是比较高的。

但从算法结构来说,递归声明的结构并不总能够转换为迭代结构,原因在于结构的引申本身属于递归的概念,用迭代的方法在设计初期根本无法实现,这就像动多态的东西并不总是可以用静多态的方法实现一样。这也是为什么在结构设计时,通常采用递归的方式而不是采用迭代的方式的原因,一个极典型的例子类似于链表,使用递归定义及其简单,但对于内存定义(数组方式)其定义及调用处理说明就变得很晦涩,尤其是在遇到环链、图、网格等问题时,使用迭代方式从描述到实现上都变得很不现实。

===============================================================================

把递归函数转换成非递归程序的一般方法

把递归算法转化为非递归算法有如下三种基本方法:

(1). 通过分析,跳过分解过程,直接用循环结构的算法实现求解过程。

(2). 自己用栈模拟系统的运行时栈,通过分析只保存必须保存的信息,从而用非递归算法替代递归算法。

(3). 利用栈保存参数,由于栈的后进先出特性吻合递归算法的执行过程,因而可以用非递归算法替代递归算法。

● 递归函数的原理

用栈保存未完成的工作,在适当的时候从栈中取出并执行。

系统保存了工作的数据和状态,数据就是函数的局部变量,

状态就是程序指针。

● 非递归程序原理

1. 和递归函数的原理相同,只不过是把由系统负责保存工作

信息变为程序自己保存,这样能减少保存数据的冗余(主要是

节省了局部变量的空间),提高存储效率。

2. 把程序要完成的工作分成两类:手头工作和保存在栈中的

待完成的工作。手头工作指程序正在做的工作。由于某些工作

不能一步完成,必须暂缓完成,于是可把它保存在栈中,这就

是待完成的工作。

3. 手头工作必须有其结束条件,不能永远做下去;保存的

待完成工作必须含有完成该项工作的所有必要信息。

4. 程序必须有秩序地完成各项工作。如,可把手头工作恰当

处理(直接处理或暂时保存)后,才能继续接手下一步的工作。

5. 待完成工作必须转换成手头工作才能处理。

● 栈的大小

所有递归问题,其递归过程可以展开成一棵树,叶子节点是

可解的,按照问题的要求,处理所有叶子节点,就可解决

问题本身。可能需要保存(Data, Status),Data是工作数据,

Status是工作状态;(Data, Status)决定了整个工作。

栈的大小等于树的高度-1,-1是因为根节点不需保存。

● 举例

例1. 汉诺塔问题

递归函数:

void Hanoi(UINT x, UINT y, UINT n)

// x Source

// y Destination

// n Number of plates

{

if (n == 0) return;

Hanoi(x, x^y, n-1);

Move(x, y);

Hanoi(x^y, y, n-1);

}

说明:x、y可取1、2、3三数之一,并且x≠y,x^y表示x、y按位异或,

得到除x、y之外的第三个数。1^2=3, 1^3=2, 2^3=1

非递归程序:

#define N 5

tyepdef struct _HANOIDATA

{

UINT x;

UINT y;

UINT n;

}HANOIDATA;

void Hanoi(HANOIDATA hanoiData)

{

HANOIDATA stack[N];

int top = -1; // stack pointer

while (hanoiData.n || top != -1) // 存在手头工作或待完成工作

{

while (hanoiData.n) // 处理手头工作直到无现成的手头工作,

// 即下次的手头工作必须从栈中取得

{

hanoiData.n --;

stack[++top] = hanoiData; // 保存待完成工作

hanoiData.y ^= hanoiData.x; // 新的手头工作

}

if (top != -1) // 存在待完成工作

{

hanoiData = stack[top--]; // 从栈中取出

Move(hanoiData.x, hanoiData.y); // 直接处理

hanoiData.x ^= hanoiData.y; // 未处理完的转换成手头工作

}

}

}

例2. 后根序遍历二叉树

递归函数:

void PostTraverse(BINARYTREE root)

{

if (root == NULL) return;

PostTraverse(root->LChild);

PostTraverse(root->RChild);

Visit(root);

}

非递归程序:

void PostTraverse(BINARYTREE p)

{

while ( p != NULL || !Stack.IsEmpty() )// 存在工作(手头或待完成)

{

while (p != NULL) // 处理手头工作,直到无现成手头工作

{

Stack.Push(p, RCHILD_AND_ITSELF);

p = p->LChild;

}

if (!Stack.IsEmpty()) // 是否存在待完成工作

{

Stack.Pop(p, Tag);

if (Tag == RCHILD_AND_ITSELF) // 情况一: RChild & Itself {

Stack.Push(p, ONLY_ITSELF) // 保存待完成工作

p = p->RChild; // 新的手头工作

}

else // tag == ONLY_ITSELF, 情况二: Only Itself

{

visit(p);

p = NULL; // 已无现成的手头工作

}

}

}

}

● 总结

非递归程序的设计应注意:

1. 保存暂缓执行的工作

2. 无现成手头工作的条件

3. 无待完成工作的条件

程序模式

void NonRecursiveFunction(DATATYPE Data)

{

while ( ExistHandyWork() || ExistSavedWork() )

{

while ( ExistHandyWork() )

{

Process(Work, Status) // Probably push work onto stack

NewHandyWork();

}

if ( ExistSavedWork() )

{

Pop(Work, Status);

Process(Work, Status); // Probably generate new handy work }

}

}

===================================================================

递归算法向非递归算法转换

递归算法实际上是一种分而治之的方法,它把复杂问题分解为简单问题来求解。对于某些复杂问题(例如hanio塔问题),递归算法是一种自然且合乎逻辑的解决问题的方式,但是递归算法的执行效率通常比较差。因此,在求解某些问题时,常采用递归算法来分析问题,用非递归算法来求解问题;另外,有些程序设计语言不支持递归,这就需要把递归算法转换为非递归算法。

将递归算法转换为非递归算法有两种方法,一种是直接求值,不需要回溯;另一种是不能直接求值,需要回溯。前者使用一些变量保存中间结果,称为直接转换法;后者使用栈保存中间结果,称为间接转换法,下面分别讨论这两种方法。

1. 直接转换法

直接转换法通常用来消除尾递归和单向递归,将递归结构用循环结构来替代。

尾递归是指在递归算法中,递归调用语句只有一个,而且是处在算法的最后。例如求阶乘的递归算法:

long fact(int n)

{

if (n==0) return 1;

else return n*fact(n-1);

}

当递归调用返回时,是返回到上一层递归调用的下一条语句,而这个返回位置正好是算法的结束处,所以,不必利用栈来保存返回信息。对于尾递归形式的递归算法,可以利用循环结构来替代。例如求阶乘的递归算法可以写成如下循环结构的非递归算法:

long fact(int n)

{

int s=0;

for (int i=1; i

s=s*i; //用s保存中间结果

return s;

}

单向递归是指递归算法中虽然有多处递归调用语句,但各递归调用语句的参数之间没有关系,并且这些递归调用语句都处在递归算法的最后。显然,尾递归是单向递归的特例。例如求斐波那契数列的递归算法如下:

int f(int n)

{

if (n= =1 | | n= =0) return 1;

else return f(n-1)+f(n-2);

}

对于单向递归,可以设置一些变量保存中间结构,将递归结构用循环结构来替代。例如求斐波那契数列的算法中用s1和s2保存中间的计算结果,非递归函数如下:

int f(int n)

{

int i, s;

int s1=1, s2=1;

for (i=3; i

{

s=s1+s2;

s2=s1; // 保存f(n-2)的值

s1=s; //保存f(n-1)的值

}

return s;

}

2. 间接转换法

该方法使用栈保存中间结果,一般需根据递归函数在执行过程中栈的变化得到。其一般过程如下:

将初始状态s0进栈

while (栈不为空)

{

退栈,将栈顶元素赋给s;

if (s是要找的结果) 返回;

else

{

寻找到s的相关状态s1;

将s1进栈

}

}

间接转换法在数据结构中有较多实例,如二叉树遍历算法的非递归实现、图的深度优先遍历算法的非递归实现等等。

使用非递归方式实现递归问题的算法程序,不仅可以节省存储空间,而且可以极大地提高算法程序的执行效率。本文将递归问题分成简单递归问题和复杂递归问题;简单递归问题的非

递归实现采用递推技术加以求解,复杂递归问题则根据问题求解的特点采用两类非递归实现算法,使用栈加以实现。


相关内容

  • 二叉树遍历
  • 二叉树遍历 姓名:左伟民 学号:12714046 班级:12医药软件1班 一.选题的背景和意义? 现实世界中很多问题都可归纳称为树的模型,在树这种数据结构中,所有数据元素 之间的关系具有明显的层次特性.其中以树和二叉树最为常用,它可以很好地描述客观世界中广泛存在的具有分支关系或层次特性的对象,因此在 ...

  • 9.9.2 快速排序复杂度分析
  • 我们来分析一下快速排序法的性能.快速排序的时间性能取决于快速排序递归的深度,可以用递归树来描述递归算法的执行情况.如图9‐9‐7所示,它是{50,10,90,30, 70,40,80,60,20}在快速排序过程中的递归过程.由于我们的第一个关键字是50,正好是待排序的序列的中间值,因此递归树是平衡的 ...

  • 全国计算机等级二级VB考试题型与解题技巧
  • 一.上机考点 由于上机考试的方式和主要考点没有很大变化,因此可以通过分析历届上机考题来归纳总结上机考试考核的重点,我们下面来介绍近几年二级Visual Basic上机考试所考知识点的分布情况. (1)对象及其操作:控件的画法.基本操作及控件值. (2)数据类型及其运算:涉及到关系运算符.算术运算符. ...

  • 编译原理大作业(哈工大)
  • 编译原理大作业 论文 学号:1093710411 姓名:周国栋 哈尔滨工业大学软件学院 2012年1月 第一章 综述 第1章 综述 1.1 语法分析概述 语法分析是编译过程的一个逻辑阶段.语法分析的任务是在词法分析的基础上将单词序列组合成各类语法短语 1.2 分析方法 语法分析主要有两种:自顶向下的 ...

  • 递归下降语法分析实验报告
  • 编 译 原 理 实 验 报 告 一. 实验目的: (1)掌握自上而下语法分析的要求与特点. (2)掌握递归下降语法分析的基本原理和方法. (3)掌握相应数据结构的设计方法. 二. 实验内容: 编程实现给定算术表达式的递归下降分析器. 算术表达式文法如下: S→a|∧|(T) T→T,S|S 三. 设 ...

  • 全排列算法1
  • 全排列以及相关算法 在程序设计过程中,我们往往要对一个序列进行全排列或者对每一个排列进行分析.全排列算法便是用于产生全排列或者逐个构造全排列的方法.当然,全排列算法不仅仅止于全排列,对于普通的排列,或者组合的问题,也可以解决.本文主要通过对全排列以及相关算法的介绍和讲解.分析,让读者更好地了解这一方 ...

  • 课程设计题目A
  • 数据结构课程设计题目 (A) 1. 文章编辑(限1 人完成) 功能:输入一页文字,程序可以统计出文字.数字.空格的个数. 静态存储一页文章,每行最多不超过80个字符,共N行:要求(1)分别统计出其中英文字母数和空格数及整篇文章总字数:(2)统计某一字符串在文章中出现的次数,并输出该次数:(3)删除某 ...

  • 树与二叉树的转换的实现_课程设计 (2)
  • XXXXX 学院计算机与信息工程学院 课程设计报告 课程名称 课题名称树与二叉树的转换的实现_课程设计 专 业 计算机软件工程 班 级 XXXXXXXXXXXXXXX 学 号 XXXXXXX 姓 名 XXXX 联系方式 XXXXXXXXXXXX 指导教师 XXXX 20 14 年 6 月 17 日 ...

  • 汉诺塔递归与非递归算法研究
  • 标题(汉诺塔递归与非递归算法研究) 作者1,作者2,作者33 (陕西师范大学 计算机科学学院,陕西 西安 710062) 摘 要: 摘要内容(包括目的.方法.结果和结论四要素) 摘要又称概要,内容提要.摘要是以提供文献内容梗概为目的,不加评论和补充解释,简明,确切地记述文献重要内容的短文.其基本要素 ...