文档库 最新最全的文档下载
当前位置:文档库 › 汉诺塔问题非递归算法详解

汉诺塔问题非递归算法详解

汉诺塔问题非递归算法详解
汉诺塔问题非递归算法详解

Make By Mr.Cai

思路介绍:

首先,可证明,当盘子的个数为n 时,移动的次数应等于2^n - 1。

然后,把三根桩子按一定顺序排成品字型(如:C

..B .A ),再把所有的圆盘按至上而下是从小到大的顺序放在桩子A 上。

接着,根据圆盘的数量确定桩子的排放顺序:

若n 为偶数,按顺时针方向依次摆放C

..B .A ; 若n 为奇数,按顺时针方向依次摆放B

..C .A 。 最后,进行以下步骤即可:

(1)首先,按顺时针方向把圆盘1从现在的桩子移动到下一根桩子,即当n 为偶数时,若圆盘1在桩子A ,则把它移动到B ;若圆盘1在桩子B ,则把它移动到C ;若圆盘1在桩子C ,则把它移动到A 。

(2)接着,把另外两根桩子上可以移动的圆盘移动到新的桩子上。

即把非空桩子上的圆盘移动到空桩子上,当两根桩子都非空时,移动较小的圆盘。

(3)重复(1)、(2)操作直至移动次数为2^n - 1。

#include

#include

using namespace std;

#define Cap 64

class Stake //表示每桩子上的情况

{

public:

Stake(int name,int n)

{

this->name=name;

top=0;

s[top]=n+1;/*假设桩子最底部有第n+1个盘子,即s[0]=n+1,这样方便下面进行操作*/

}

int Top()//获取栈顶元素

{

return s[top];//栈顶

}

int Pop()//出栈

{ return s[top--];

}

void Push(int top)//进栈

{

s[++this->top]=top;

}

void setNext(Stake *p)

{

next=p;

}

Stake *getNext()//获取下一个对象的地址

{

return next;

}

int getName()//获取当前桩子的编号

{

return name;

}

private:

int s[Cap+1];//表示每根桩子放盘子的最大容量

int top,name;

Stake *next;

};

void main()

{

int n;

void hanoi(int,int,int,int);

cout<<"请输入盘子的数量:";

cin>>n;

if(n<1)

cout<<"输入的盘子数量错误!!!"<

else

{

cout<<"移动"<

if(n%2)

hanoi(n,1,3,2);

else

hanoi(n,1,2,3);

}

}

void hanoi(const int n,int A,int B,int C)

{

Stake a(A,n),b(B,n),c(C,n);

Stake *p,*ptr1,*ptr2,*pt;

int i,temp,max=pow(2,n)-1;

for(i=0;i

a.Push(n-i);

a.setNext(&b);

b.setNext(&c);//将3个桩子连在一起,就如同链表

c.setNext(&a);

for(i=0,p=&a;i

if(i%2)

{

ptr1=p->getNext();

ptr2=ptr1->getNext();

if(ptr1->Top()Top())

{

pt=ptr1;

ptr1=ptr2;

ptr2=pt;

}

ptr1->Push(ptr2->Pop());

cout<getName()<<"-->"

<getName()<

}

else

{

temp=p->Pop();

cout<getName()<<"-->";

p=p->getNext();

p->Push(temp);

cout<getName()<

}

}

}

《递归算法与递归程序》教学设计

递归算法与递归程序 岳西中学:崔世义一、教学目标 1知识与技能 (1) ?认识递归现象。 (2) ?使用递归算法解决冋题往往能使算法的描述乘法而易于表达 (3) ?理解递归三要素:每次递归调用都要缩小规模;前次递归调用为后次作准备:递归调用必须有条件进行。 (4) ?认识递归算法往往不是咼效的算法。 (5) ? 了解递归现象的规律。 (6) ?能够设计递归程序解决适用于递归解决的问题。 (7) ?能够根据算法写出递归程序。 (8) ? 了解生活中的递归现象,领悟递归现象的既有重复,又有变化的特点,并且从中学习解决问题的一种方法。 2、方法与过程 本节让同学们玩汉诺塔的游戏,导入递归问题,从用普通程序解决斐波那契的兔子问题入手,引导学生用自定义了一个以递归方式解决的函数过程解决问题,同时让同学们做三个递归练习,巩固提高。然后让学生做练习(2) 和练习(3)这两道题目的形式相差很远,但方法和答案却是完全相同的练习,体会其中的奥妙,加深对递归算法的了解。最后用子过程解决汉诺塔的经典问题。 3、情感态度和价值观 结合高中生想象具有较强的随意性、更富于现实性的身心发展特点,综合反映出递归算法的特点,以及递归算法解答某些实践问题通常得很简洁,从而激发学生对程序设计的追求和向往。 二、重点难点 1、教学重点 (1) 了解递归现象和递归算法的特点。 (2) 能够根据问题设计出恰当的递归程序。 2、教学难点 (1) 递归过程思路的建立。 (2) 判断冋题是否适于递归解法。 (3) 正确写出递归程序。 三、教学环境 1、教材处理 教材选自《浙江省普通高中信息技术选修:算法与程序设计》第五章,原教材的编排是以本节以斐波那契的兔子问题引人,导出递归算法,从而自 定义了一个以递归方式解决的函数过程。然后利用子过程解决汉诺塔的经典问题。 教材经处理后,让同学们玩汉诺塔的游戏,导入递归问题,从用普通程序解决斐波那契的兔子问题入手,引导学生用自定义了一个以递归方式解决的函数过程解决问题,同时让同学们做三个递归练习,巩固提高。然后让学生做练习⑵ 和练习

高中信息技术《算法与程序设计》试题

高中信息技术《算法与程序设计》试题 一、单选题(每小题3分,20小题,共60分) 1、用计算机解决问题时,首先应该确定程序“做什么?”,然后再确定程序“如何做?”请问“如何做?”是属于用计算机解决问题的哪一个步骤?() A、分析问题 B、设计算法 C、编写程序 D、调试程序 2、在调试程序过程中,下列哪一种错误是计算机检查不出来的?() A、编译错误 B、执行错误 C、逻辑错误 D、任何错误计算机都能检查出来 3、下列关于算法的叙述中,错误的是() A、一个算法至少有一个输入和一个输出 B、算法的每一个步骤必须确切地定义 C、一个算法在执行有穷步之后必须结束 D、算法中有待执行的运算和操作必须是相当基本的。 4、流程图中表示判断的是()。 A、矩形框B、菱形框C、圆形框D、椭圆形框 5、任何复杂的算法都可以用三种基本结构组成,下列不属于基本结构的是() A、顺序结构 B、选择结构 C、层次结构 D、循环结构 6、能够被计算机直接识别的语言是() A、伪代码 B、高级语言 C、机器语言 D、汇编语言 7、在VB语言中,下列数据中合法的长整型常量是() A、08A B、2380836E C、88.12345 D、1.2345E6 8、求Mid(“ABCDEFG”,3,2)的结果是() A、“ABC” B、“CD” C、“ABCDEF” D、“BCD” 9、表达式 A+B+C=3 OR NOT C<0 OR D>0 当A=3,B=4,C=-5,D=6时的运算结果是() A、0 B、1 C、TRUE D、FALSE 10、在循环语句 For x=1 to 100 step 2 …… Next x 中,x能达到的最大值是() A、100 B、99 C、98 D、97 11、在下列选项中,不属于VB的对象的是() A、窗体的背景颜色 B、命令按钮 C、文本框 D、标签 12、在调试程序的时候,经常要设置断点,设置断点的快捷键是()

递归算法和非递归算法的区别和转换

递归算法向非递归算法转换 递归算法实际上是一种分而治之的方法,它把复杂问题分解为简单问题来求解。对于某些复杂问题(例如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<=n;i++) s=s*i; //用s保存中间结果 return s; } 单向递归是指递归算法中虽然有多处递归调用语句,但各递归调用语句的参数之间没有关系,并且这些递归调用语句都处在递归算法的最后。显然,尾递归是单向递归的特例。例如求斐波那契数列的递归算法如下: int f(int n) {

树的遍历(递归和非递归)

二叉树的遍历 一、设计思想 二叉树的遍历分为三种方式,分别是先序遍历,中序遍历和后序遍历。先序遍历实现的顺序是:根左右,中序遍历实现的是:左根右,后续遍历实现的是:左右根。根据不同的算法分,又分为递归遍历和非递归遍历。 递归算法: 1.先序遍历:先序遍历就是首先判断根结点是否为空,为空则停止遍历,不为空则将左子作为新的根结点重新进行上述判断,左子遍历结束后,再将右子作为根结点判断,直至结束。到达每一个结点时,打印该结点数据,即得先序遍历结果。 2.中序遍历:中序遍历是首先判断该结点是否为空,为空则结束,不为空则将左子作为根结点再进行判断,打印左子,然后打印二叉树的根结点,最后再将右子作为参数进行判断,打印右子,直至结束。 3.后续遍历:指针到达一个结点时,判断该结点是否为空,为空则停止遍历,不为空则将左子作为新的结点参数进行判断,打印左子。左子判断完成后,将右子作为结点参数传入判断,打印右子。左右子判断完成后打印根结点。 非递归算法: 1.先序遍历:首先建立一个栈,当指针到达根结点时,打印根结点,判断根结点是否有左子和右子。有左子和右子的话就打印左子同时将右子入栈,将左子作为新的根结点进行判断,方法同上。若当前结点没有左子,则直接将右子打印,同时将右子作为新的根结点判断。若当前结点没有右子,则打印左子,同时将左子作为新的根结点判断。若当前结点既没有左子也没有右子,则当前结点为叶子结点,此时将从栈中出栈一个元素,作为当前的根结点,打印结点元素,同时将当前结点同样按上述方法判断,依次进行。直至当前结点的左右子都为

空,且栈为空时,遍历结束。 2.中序遍历:首先建立一个栈,定义一个常量flag(flag为0或者1),用flag记录结点的左子是否去过,没有去过为0,去过为1,默认为0.首先将指针指向根结点,将根结点入栈,然后将指针指向左子,左子作为新的结点,将新结点入栈,然后再将指针指向当前结点的左子,直至左子为空,则指针返回,flag置1,出栈一个元素,作为当前结点,打印该结点,然后判断flag,flag为1则将指针指向当前结点右子,将右子作为新的结点,结点入栈,再次进行上面的判断,直至当前结点右子也为空,则再出栈一个元素作为当前结点,一直到结束,使得当前结点右子为空,且栈空,遍历结束。 3.后续遍历:首先建立两个栈,然后定义两个常量。第一个为status,取值为0,1,2.0代表左右子都没有去过,1代表去过左子,2,代表左右子都去过,默认为0。第二个常量为flag,取值为0或者1,0代表进左栈,1代表进右栈。初始时指针指向根结点,判断根结点是否有左子,有左子则,将根结点入左栈,status置0,flag置0,若没有左子则判断结点有没有右子,有右子就把结点入右栈,status置0,flag置1,若左右子都没有,则打印该结点,并将指针指向空,此时判断flag,若flag为0,则从左栈出栈一个元素作为当前结点,重新判断;若flag为1则从右栈出栈一个元素作为当前结点,重新判断左右子是否去过,若status为1,则判断该结点有没有右子,若有右子,则将该结点入右栈,status置1,flag置1,若没有右子,则打印当前结点,并将指针置空,然后再次判断flag。若当前结点status为2,且栈为空,则遍历结束。若指针指向了左子,则将左子作为当前结点,判断其左右子情况,按上述方法处理,直至遍历结束。 二、算法流程图

汉诺塔问题的三种实现

// test_project.cpp : 定义控制台应用程序的入口点。//汉诺塔问题的 // //递归实现 /*#include "stdafx.h" #include using namespace std; int count=0;//记录移动到了多少步 void Move(int n,char From,char To); void Hannoi(int n,char From, char Pass ,char To); //把圆盘从From,经过pass,移动到To int main() { int n_count=0; cout<<"请输入圆盘个数:"; cin>>n_count; Hannoi(n_count,'A','B','C'); } void Move(int n,char From,char To)

{ count++; cout<<"第"<

/*后来一位美国学者发现一种出人意料的简单方法,只要轮流进行两步操作就可以了。首先把三根柱子按顺序排成品字型,把所有的圆盘按从大到小的顺序放在柱子A上,根据圆盘的数量确定柱子的排放顺序:若n为偶数,按顺时针方向依次摆放A B C; 若n为奇数,按顺时针方向依次摆放A C B。 ()按顺时针方向把圆盘从现在的柱子移动到下一根柱子,即当n为偶数时,若圆盘在柱子A,则把它移动到B;若圆盘在柱子B,则把它移动到C;若圆盘在柱子C,则把它移动到A。 ()接着,把另外两根柱子上可以移动的圆盘移动到新的柱子上。即把非空柱子上的圆盘移动到空柱子上,当两根柱子都非空时,移动较小的圆盘。这一步没有明确规定移动哪个圆盘,你可能以为会有多种可能性,其实不然,可实施的行动是唯一的。 ()反复进行()()操作,最后就能按规定完成汉诺塔的移动。 所以结果非常简单,就是按照移动规则向一个方向移动金片: 如阶汉诺塔的移动:A→C,A→B,C→B,A→C,B→A,B→C,A→C 汉诺塔问题也是程序设计中的经典递归问题,下面我们将给出递归和非递归的不同实现源代码。*/ /*#include "stdafx.h" #include #include

n!非递归算法的设计与实现

n!非递归算法的设计与实现 1 课题描述 尽管递归算法是一种自然且合乎逻辑的解决问题的方式,但递归算法的执行效率通常比较差。因此在求解许多问题时常采用递归算法来分析问题,用非递归方法来求解问题;另外一些程序不支持递归算法来求解问题,所以我们都会用非递归算法来求解问题。 本次课程设计主要内容是:用非递归算法实现n!的计算,由于计算机中数据的存储范围有限,而又要求出尽可能大的n的阶乘的值,用数组构造n的运算结果的存储结构,用栈的存储方式,最后输出n!的运算结果。 本次课程设计的目的是:通过本次课程设计,可以使大家了解缓存中数据的存储范围,提高自学能力,增强团队合作意识。

2 需求分析 本次n!非递归算法的课程设计中主要用到的知识有:数组、函数、栈,选择条件中的结构语句(if…else),和循环结构语句中的语句while()语句、do…while()语句和for()语句,选择语句if的运用。 对n!的非递归的算法,主要是运用非递归的算法实现n的阶乘。 限制条件: (1).要求的n必须是整数; (2). n的范围; (3). 数据类型和表数范围。

递归和非递归算法是相通的,递归是一种直接或间接调用自身的算法,而非递归不调用自身函数递推采用的是递归和归并法,而非递推只采用递归法。递推法一般容易溢出,所以一般都采用递推法分析,而用非递推法设计程序。 将n定义为float型,便于查看n是否为整数; 本次试验分为两个模块: (1).当n小于都等于12时,实现阶乘的模块m(n): 直接用sum*=i;实现求n的阶乘,相对简单,容易就算。 (2).当n大于12时,如果用long型结果就会溢出,所以实现阶乘需调用的模块f(n): 采用数组存放计算的结果,用队列输出运行结果。由于计算结果较大,将结果除以数组最大存储位数,将高位结果存放在数组的起始地址上,将低位的结果存放在数组的末端地址上,最后采用队列输出运行结果。 (3).模块调用关系如图3.1所示 图3.1 模块调用图

汉诺塔非递归算法C语言实现

汉诺塔非递归算法C语言实现 #include #include #define CSZL 10 #define FPZL 10 typedef struct hanoi { int n; char x,y,z; }hanoi; typedef struct Stack { hanoi *base,*top; int stacksize; }Stack; int InitStack(Stack *S) { S->base=(hanoi *)malloc(CSZL*sizeof(hanoi)); if(!S->base) return 0; S->top=S->base; S->stacksize=CSZL; return 1; } int PushStack(Stack *S,int n,char x,char y,char z) { if(S->top-S->base==S->stacksize) { S->base=(hanoi *)realloc(S->base,(S->stacksize+FPZL)*sizeof(hanoi)); if(!S->base) return 0; S->top=S->base+S->stacksize; S->stacksize+=FPZL; } S->top->n=n; S->top->x=x; S->top->y=y; S->top->z=z; S->top++; return 1; } int PopStack(Stack *S,int *n,char *x,char *y,char *z) { if(S->top==S->base)

汉诺塔问题与递归思想教学设计

一、教学思想(包括教学背景、教学目标) 1、教学背景 本课程“递归算法”,属于《数据结构与算法》课程中“栈和队列”章节的重点和难点。数据结构与算法已经广泛应用于各行各业的数据存储和信息处理中,与人们的社会生活密不可分。该课程是计算机类相关专业核心骨干课程,处于计算机学科的核心地位,具有承上启下的作用。不仅成为全国高校计算机类硕士研究生入学的统考科目,还是各企业招聘信息类员工入职笔试的必考科目。数据结构与算法课程面向计算机科学与技术、软件工程等计算机类学生,属于专业基础课。 2、教学大纲 通过本课程的学习,主要培养学生以下几个方面的能力: 1)理解递归的算法; 2)掌握递归算法的实现要素; 3)掌握数值与非数值型递归的实现方法。 根据学生在学习基础和能力方面的差异性,将整个课程教学目标分成三个水平:合格水平(符合课标的最低要求),中等以上水平(符合课标的基本要求),优秀水平(符合或超出课标提出的最高要求)。具体如下表:

二、课程设计思路(包括教学方法、手段) “递归算法”课程以故事引入、案例驱动法、示范模仿、启发式等多元化教学方法,设计课程内容。具体的课堂内容如下所示:

1 1 2 3 3 7 4 15 5 31 count = 2n-1 思考:若移动速度为1个/秒,则需要 (264-1)/365/24/3600 >= 5849亿年。 四、总结和思考 总结: 对于阶乘这类数值型问题,可以表达成数学公式,然后从相应的公式入手推导,解决这类问题的递归定义,同时确定这个问题的边界条件,找到结束递归的条件。 对于汉诺塔这类非数值型问题,虽然很难找到数学公式表达,但可将问题进行分解,问题规模逐渐缩小,直至最小规模有直接解。 思考: 数值型问题:斐波那契数列的递归设计。 非数值型问题:八皇后问题的递归设计。阐述总结知识拓展 三、教学特色(总结教学特色和效果) 递归算法课程主要讨论递归设计的思想和实现。从阶乘实例入手,由浅入深,层层深入介绍了递归的设计要点和算法的实现。从汉诺塔问题,通过“边提问,边思考”的方式逐层深入地给出算法的分析和设计过程。通过故事引入、案例导入、实例演示、PPT展示、实现效果等“多元化教学方式”,努力扩展课堂教学主战场。加上逐步引导、问题驱动,启发学生对算法的理解,并用实例演示展示算法的分析过程,在编译环境下实现该算法,加深对算法实现过程的认识。 1、知识点的引入使用故事诱导法讲授 通过“老和尚讲故事”引入函数的递归调用,并通过“世界末日问题” 故事引入非数值型问题的递归分析,激发学习积极性,挖掘学生潜能。

高中信息技术算法及程序设计

高中信息技术《算法与程序设计VB (选修)》 知识要点 相关知识点 (一)算法 1.定义 相关题解: 1算法:就是解决问题的方法和步骤。算法是程序设计的“灵魂”,算法+数据结构=程序。 单选题 1、运用计算机程序解决实际问题时,合理的步骤是(B )。 A 、设计算法→分析问题→编写程序→调试程序 B 、分析问题→设计算法→编写程序→调试程序 C 、分析问题→编写程序→设计算法→调试程序 D 、设计算法→编写程序→分析问题→调试程序 2.算法的描述方法: 1算法的描述:可分多种表达方法,一般用自然语言、流程图和伪代码进行描述。 2自然语言描述法:指用人们日常生活中使用的语言(本国语言),用自然语言描述符合我们的习惯,且容易理解。 3流程图描述:也称程序框图,它是算法的一种图形化表示方法。且描述算法形象、直观,更易理解。 4伪代码描述法:是介于自然语言和计算机程序语言之间的一种算法描述。是专业软件开发人员常用方法。 相关题解: 单选题 1、图形符号"在算法流程图描述中表示( B ). A 处理或运算的功能 B 输入输出操作 C D 算法的开始或结束 2、图形符号在算法流程图描述中表示( A ). A 输入输出操作 C 用来判断条件是否满足需求 D 算法的开始或结束 3、以下哪个是算法的描述方法( A ) A 流程图描述法 B 枚举法 C 顺序法 D 列表法 4、以下哪个是算法的描述方法( D ) A 顺序法 B 列表法 C 集合法 D 自然语言描述法 介于自然语言和计算机语言之间的一种算法描述是下列哪个选项( )

B、流程图 C、高级语言 D、VB 程序设计语言 (二)程序设计基础 (1)常用高级编程语言:BASIC、VB、Pascal、C、C++、Java 1面向对象的程序设计语言:其中的对象主要是系统设计好的对象,包括窗体等、控件等 2控件:是指工具箱中的工具在窗体中画出的、能实现一定功能的部件,如文本框,命令按钮等。 对象属性=属性值 对象中属性可以在设计界面时通过属性窗中设置,也可以在运行时通过程序代码设置,方法如下例:给文本框“Txt123”的“Text”属性赋值为字符串“20”,代码如下 =”20”

二叉树遍历C语言(递归,非递归)六种算法

数据结构(双语) ——项目文档报告用两种方式实现表达式自动计算 专业: 班级: 指导教师: 姓名: 学号:

目录 一、设计思想 (01) 二、算法流程图 (02) 三、源代码 (04) 四、运行结果 (11) 五、遇到的问题及解决 (11) 六、心得体会 (12)

一、设计思想 二叉树的遍历分为三种方式,分别是先序遍历,中序遍历和后序遍历。先序遍历实现的顺序是:根左右,中序遍历实现的是:左根右,后续遍历实现的是:左右根。根据不同的算法分,又分为递归遍历和非递归遍历。 递归算法: 1.先序遍历:先序遍历就是首先判断根结点是否为空,为空则停止遍历,不为空则将左子作为新的根结点重新进行上述判断,左子遍历结束后,再将右子作为根结点判断,直至结束。到达每一个结点时,打印该结点数据,即得先序遍历结果。 2.中序遍历:中序遍历是首先判断该结点是否为空,为空则结束,不为空则将左子作为根结点再进行判断,打印左子,然后打印二叉树的根结点,最后再将右子作为参数进行判断,打印右子,直至结束。 3.后续遍历:指针到达一个结点时,判断该结点是否为空,为空则停止遍历,不为空则将左子作为新的结点参数进行判断,打印左子。左子判断完成后,将右子作为结点参数传入判断,打印右子。左右子判断完成后打印根结点。 非递归算法: 1.先序遍历:首先建立一个栈,当指针到达根结点时,打印根结点,判断根结点是否有左子和右子。有左子和右子的话就打印左子同时将右子入栈,将左子作为新的根结点进行判断,方法同上。若当前结点没有左子,则直接将右子打印,同时将右子作为新的根结点判断。若当前结点没有右子,则打印左子,同时将左子作为新的根结点判断。若当前结点既没有左子也没有右子,则当前结点为叶子结点,此时将从栈中出栈一个元素,作为当前的根结点,打印结点元素,同时将当前结点同样按上述方法判断,依次进行。直至当前结点的左右子都为空,且栈为空时,遍历结束。 2.中序遍历:首先建立一个栈,定义一个常量flag(flag为0或者1),用flag记录结点的左子是否去过,没有去过为0,去过为1,默认为0.首先将指针指向根结点,将根结点入栈,然后将指针指向左子,左子作为新的结点,将新结点入栈,然后再将指针指向当前结点的左子,直至左子为空,则指针返回,flag置1,出栈一个元素,作为当前结点,打印该结点,然后判断flag,flag为1则将指针指向当前结点右子,将右子作为新的结点,结点入栈,再次进行上面的判断,直至当前结点右子也为空,则再出栈一个元素作为当前结点,一直到结束,使得当前结点右子为空,且栈空,遍历结束。 3.后续遍历:首先建立两个栈,然后定义两个常量。第一个为status,取值为0,1,2.0代表左右子都没有去过,1代表去过左子,2,代表左右子都去过,默认为0。第二个常量为flag,取值为0或者1,0代表进左栈,1代表进右栈。初始时指针指向根结点,判断根结点是否有左子,有左子则,将根结点入左栈,status置0,flag置0,若没有左子则判断结点有没有右子,有右子就把结点入右栈,status置0,flag置1,若左右子都没有,则打印该结点,并将指针指向空,此时判断flag,若flag为0,则从左栈出栈一个元素作为当前结点,重新判断;若flag为1则从右栈出栈一个元素作为当前结点,重新判断左右子是否去过,若status 为1,则判断该结点有没有右子,若有右子,则将该结点入右栈,status置1,flag置1,若没有右子,则打印当前结点,并将指针置空,然后再次判断flag。若当前结点status为2,且栈为空,则遍历结束。若指针指向了左子,则将左子作为当前结点,判断其左右子情况,按上述方法处理,直至遍历结束。

汉诺塔问题

实验二知识表示方法 梵塔问题实验 1.实验目的 (1)了解知识表示相关技术; (2)掌握问题规约法或者状态空间法的分析方法。 2.实验内容(2个实验内容可以选择1个实现) (1)梵塔问题实验。熟悉和掌握问题规约法的原理、实质和规约过程;理解规约图的表示方法; (2)状态空间法实验。从前有一条河,河的左岸有m个传教士、m个野人和一艘最多可乘n人的小船。约定左岸,右岸和船上或者没有传教士,或者野人数量少于传教士,否则野人会把传教士吃掉。搜索一条可使所有的野人和传教士安全渡到右岸的方案。 3.实验报告要求 (1)简述实验原理及方法,并请给出程序设计流程图。 我们可以这样分析: (1)第一个和尚命令第二个和尚将63个盘子从A座移动到B座; (2)自己将底下最大的盘子从A移动到C; (3)再命令第二个和尚将63个盘子从B座移动到C;(4)第二个和尚命令第三个和尚重复(1)(2)(3);以此类推便可以实现。这明显是个递归的算法科技解决的问

题。 (2)源程序清单: #include #include using namespace std; void main() { void hanoi(int n,char x,char y,char z);

int n; printf("input the number of diskes\n"); scanf("%d",&n); hanoi(n,'A','B','C'); } void hanoi(int n,char p1,char p2,char p3) { if(1==n) cout<<"盘子从"<

算法与程序设计模块(选择题)汇总

算法与程序设计模块(选择题) 1.用流程图描述算法中表示“条件判断”的图形符号是 A. B. C. D. 答案:A 2.以下为求0到1000以内所有奇数和的算法,从中选出描述正确的算法 A. ①s=0; ②i=1; ③s=s+i; ④i=i+2; ⑤如果i≤1000,则返回③; ⑥结束 B. ①s=0; ②i=1; ③i=i+2; ④s=s+i; ⑤如果i≤1000,则返回③; ⑥结束 C. ①s=1; ②i=1; ③s=s+i; ④i=i+2; ⑤如果i≤1000,则返回③; ⑥结束 D. ①s=1;

②i=1; ③i=i+2; ④s=s+i; ⑤如果i≤1000,则返回③; ⑥结束 答案:A 3.在VB语言中,下列数据中合法的长整型常量是 A. 123456 B. 1234.56 C. 12345A D. A12345 答案:A 4.在VB语言中可以作为变量名的是 A. Print B. ab=cd C. 123abc D. abc_123 答案:D 5.设置TextBox的字体时,应改变TextBox的 A. Text属性 B. Font属性 C. ForeColor属性 D. Name属性 答案:B 7.代数式a ac b 24 2 对应的VB表达式是 A. sqr(b*b-4*a*c)/2*a B. sqr(b*b-4*a*c)/2/a C. sqr(b*b-4*a*c)/(2/a) D. sqr(b*b-4*a*c)/2a

答案:B 8.在VB语言中,下列正确的赋值语句是 A. I=I+1 B. I+1=I C. I*3=I D. 2I=I+1 答案:A 9.下列计算机程序设计语言中不属于高级语言的是 A. C++ B. Visual Basic C.机器语言 D. Java 答案:C 计算机程序设计语言:机器语言010*******汇编语言高级语言10.在VB语言中,下列逻辑表达式的值为"假"的是 A. #1/11/2009# > #11/15/2008# B. #1/11/2009# < #11/15/2008# C. 5 > 3 and 6 < 9 D. 5 > 3 or 6 > 9 答案:B 11.用流程图描述算法中表示“开始/结束”的图形符号是 A. B. C. D. 答案:B

先序遍历的非递归算法 C语言

先序遍历的非递归算法 #include #include #define MS 10 struct BTreeNode { char data; struct BTreeNode * left; struct BTreeNode * right; }; void InitBTree(struct BTreeNode * * BT) { * BT=NULL; } void CreatBTree(struct BTreeNode * * BT,char * a) { struct BTreeNode * p; struct BTreeNode * s[MS]; int top=-1; int k; int i=0; * BT=NULL; while(a[i]) { switch(a[i]) { case ' ':break; case '(': if(top==MS-1) { printf("栈空间太小,需增加MS的值!\n"); exit(1); } top++;s[top]=p;k=1; break; case ')': if(top==-1) {

printf("二叉树广义表字符串有错!\n"); exit(1); } top--;break; case ',' : k=2;break; default : if((a[i]>='a'&&a[i]<='z')||(a[i]>='A'&&a[i]<='Z')) { p=malloc(sizeof(struct BTreeNode)); p->data=a[i];p->left=p->right=NULL; if(* BT==NULL) * BT=p; else { if(k==1) s[top]->left=p; else s[top]->right=p; } } else {printf("二叉树广义表字符串有错!\n");exit(1);} } i++; } } void Preorder(struct BTreeNode * BT) { struct BTreeNode * s[10]; int top=-1; struct BTreeNode * p=BT; printf("先序遍历结点的访问序列为:\n"); while(top!=-1||p!=NULL) { while(p!=NULL) { top++; s[top]=p; printf("%c",p->data); p=p->left; } if(top!=-1) {

汉诺塔问题实验报告

1.实验目的: 通过本实验,掌握复杂性问题的分析方法,了解汉诺塔游戏的时间复杂性和空间复杂性。 2.问题描述: 汉诺塔问题来自一个古老的传说:在世界刚被创建的时候有一座钻石宝塔(塔A),其上有64个金碟。所有碟子按从大到小的次序从塔底堆放至塔顶。紧挨着这座塔有另外两个钻石宝塔(塔B和塔C)。从世界创始之日起,婆罗门的牧师们就一直在试图把塔A 上的碟子移动到塔C上去,其间借助于塔B的帮助。每次只能移动一个碟子,任何时候都不能把一个碟子放在比它小的碟子上面。当牧师们完成任务时,世界末日也就到了。 3.算法设计思想: 对于汉诺塔问题的求解,可以通过以下三个步骤实现: (1)将塔A上的n-1个碟子借助塔C先移到塔B上。 (2)把塔A上剩下的一个碟子移到塔C上。 (3)将n-1个碟子从塔B借助于塔A移到塔C上。 4.实验步骤: 1.用c++ 或c语言设计实现汉诺塔游戏; 2.让盘子数从2 开始到7进行实验,记录程序运行时间和递 归调用次数; 3.画出盘子数n和运行时间t 、递归调用次数m的关系图, 并进行分析。 5.代码设计: Hanio.cpp #include"stdafx.h" #include #include #include void hanoi(int n,char x,char y,char z) { if(n==1) { printf("从%c->搬到%c\n",x,z); } else { hanoi(n-1,x,z,y); printf("从%c->%c搬到\n",x,z); hanoi(n-1,y,x,z); }

算法与程序设计教案

算法与程序设计思想 【基本信息】 【课标要求】 (一)利用计算机解决问题的基本过程 (1)结合实例,经历分析问题、确定算法、编程求解等用计算机解决问题的基本过程,认识算法和程序设计在其中的地位和作用。 (2)经历用自然语言、流程图或伪代码等方法描述算法的过程。 (4)了解程序设计语言、编辑程序、编译程序、连接程序以及程序开发环境等基本知识。 【学情分析】 高一年级的学生已具备了一定的观察、思考、分析和解决问题能力,也已有了顺序结构、分支结构、循环结构等知识的储备。因此,对于如何将解决问题的思路画成流程图已有一定的基础,但可能还不很熟练,尤其对刚学过的循环结构,教师在课堂上要注意引导。 『此处说“已有了顺序结构、分支结构、循环结构等知识的储备”,应该是指在必修部分对“计算机解决实际问题的基本过程”已有所体验与了解,或是指已学习过数学中相关模块的知识,这是本案例教学得以实施的必不可少的前提条件。』 【教学目标】 1.知识与技能: 建立求一批数据中最大值的算法设计思想,并将算法的设计思想用流程图表示出来。 2.过程与方法: 利用现实生活中比较身高的活动,以及对武术比赛中“打擂台”流程的逐步梳理,让学生学会从此类生活实际中提炼出求最大值的思想方法,即算法思想。 培养学生分析问题、解决问题的能力,让学生学会在面对问题时能梳理出解决问题的清晰思路,进而设计出解决某个特定问题的有限步骤,从而理解计算机是如何解决、处理某种问题的。 『在过程上,通过现实生活中的实例来引导学生总结“求最大值”的算法思想。过程的实现关键在于实例引用是否贴切,是否有利于学生向抽象结论的构建。本案例的实例选择是符合这一要求的。在方法上,注重培养学生分析、解决问题的一般能力,再次体验与理解应用计算机解决问题的基本过程,为后面更一步的学习打下基础,积累信心。』 3.情感态度与价值观:

汉诺塔问题的非递归算法分析

汉诺塔递归与非递归算法研究 作者1,作者2,作者33 (陕西师范大学计算机科学学院,陕西西安 710062) 摘要: 摘要内容(包括目的、方法、结果和结论四要素) 摘要又称概要,内容提要.摘要是以提供文献内容梗概为目的,不加评论和补充解释,简明,确切地记述文献重要内容的短文.其基本要素包括研究目的,方法,结果和结论.具体地讲就是研究工作的主要对象和范围,采用的手段和方法,得出的结果和重要的结论,有时也包括具有情报价值的其它重要的信息.摘要应具有独立性和自明性,并且拥有与文献同等量的主要信息,即不阅读全文,就能获得必要的信息. 关键词:关键词1; 关键词2;关键词3;……(一般可选3~8个关键词,用中文表示,不用英文 Title 如:XIN Ming-ming , XIN Ming (1.Dept. of ****, University, City Province Zip C ode, China;2.Dept. of ****, University, City Province Zip C ode, China;3.Dept. of ****, University, City Province Zip C ode, China) Abstract: abstract(第三人称叙述,尽量使用简单句;介绍作者工作(目的、方法、结果)用过去时,简述作者结论用一般现在时) Key words: keyword1;keyword2; keyword3;……(与中文关键词对应,字母小写(缩略词除外)); 正文部分用小5号宋体字,分两栏排,其中图表宽度不超过8cm.。设置为A4页面 1 引言(一级标题四号黑体加粗) 这个问题当时老和尚和众僧们,经过计算后,预言当所有的盘子都从基柱A移到基座B上时,世界就将在一声霹雳中消灭,而梵塔、庙宇和众生也都将同归于尽。其实,不管这个传说的可信度有多大,如果考虑把64个盘子,由一个塔柱上移到另一根塔柱上,并且始终保持上小下大的顺序。假设有n个盘子,移动次数是f(n).显然f(1)=1,f(2)=3,f(3)=7,且f(k+1)=2*f(k)+1。此后不难证明f(n)=2n-1。n=64时, f(64)= 2^64-1=18446744073709551615 假如每秒钟一次,共需多长时间呢?一年大约有 31536926 秒,计算表明移完这些金片需要5800多亿年,比地球寿命还要长,事实上,世界、梵塔、庙宇和众生都早已经灰飞烟灭。 对传统的汉诺塔问题,目前还有不少的学者继续研究它的非递归解法,本文通过对递归算法的研究……. 提示:(1)可以定义问题的规模n,如盘子的数量;(2)塔柱的数量(目前有部分理论可以支撑,不妨用计算机实现)分析规模的变化与算法的复杂度比较。(3)可以对经典的汉诺塔问题条件放松、加宽,如在经典的汉诺塔问题中大盘只能在小盘下面,放松其他条件可以定义相邻两个盘子必须满足大盘只能在小盘下面。其它盘子不作要求。 2 算法设计 2.1 汉诺塔递归算法描述(二级标题小五黑体加粗) 用人类的大脑直接去解3,4或5个盘子的汉诺塔问题还可以,但是随着盘子个数的增多,问题的规模变的越来越大。这样的问题就难以完成,更不用说吧问题抽象成循环的机器操作。所以类似的问题可用递归算法来求解。下面n个盘的汉

非递归方式建树并按任一种非递归遍历次序输出二叉树中

//非递归方式建树,并按任一种非递归遍历次序输出二叉树中的所有结点; #include #include #include #define MaxSize 50 typedef char ElemType; typedef struct TNode{ ElemType data; struct TNode *lchild,*rchild; }BTree; //------------------------------------------------------------------------------ ElemType str[]="A(B(C(D,E(F,G(,H))),I(J,K(L))),M)"; //"A(B(D,E(G,H(I))),C(F))"; //------------------------------------------------------------------------------ void CreateBTree(BTree **T,ElemType *Str); //非递归建树; void TraverseBTree(BTree *T); //选择非递归算法的遍历方式; void PreOrderUnrec(BTree *T); //先序遍历非递归算法; void InOrderUnrec(BTree *T); //中序遍历非递归算法; void PostOrderUnrec(BTree *T); //后序遍历非递归算法; //------------------------------------------------------------------------------ int main(void) { BTree *T = NULL; printf("\n二叉树的广义表格式为:\n\t"); puts(str); CreateBTree(&T,str); TraverseBTree(T); system("pause"); return 0; } //------------------------------------------------------------------------------ void CreateBTree(BTree **T,ElemType *Str) { //按二叉树广义表建立对应的二叉树存储结构; BTree *p = NULL,*Stack[MaxSize];//数组为存储树根结点指针的栈,p为指向树结点的指针; int top = -1; //top为Stack栈的栈顶指针; char flag; //flag为处理结点的左子树(L)和右子树(R)的标记; *T = NULL; while(*Str) { if (*Str == '(') {Stack[++top] = p;flag = 'L';} //入栈; else if(*Str == ')') --top; //出栈; else if(*Str == ',') flag = 'R'; else { if(!(p = (BTree *)malloc(sizeof(BTree)))) exit (1); p->data = *Str; p->lchild = p->rchild = NULL; //初始化新结点;

马踏棋盘非递归算法

#include struct point { int x,y;//马的位置 int dir;//这一次马行走的方向 }; struct stack { point p[64];//存储马的位置,方便回溯 }; int board [8][8]; int Htry1[8]={-2,-1,1,2,2,1,-1,-2}; int Htry2[8]={1,2,2,1,-1,-2,-2,-1}; bool chech[8][8]={0};//标记位置是否已经被占用 int main() { int i,j; int top=0; int z; cout<<"请输入马的初始位置"; cin>>i; cin>>j; stack sta; sta.p[top].x=i; sta.p[top].y=j; board [i][j]=top; chech [i][j]=true; int nx; int ny; for(int u=0;u<64;u++) sta.p[u].dir=0;//把每个结点的dir清零 for(z=0;;) { if(sta.p[top].x+Htry1[z]>=0&&sta.p[top].x+Htry1[z]<8&& sta.p[top].y+Htry2[z]>=0&&sta.p[top].y+Htry2[z]<8&& !chech [sta.p[top].x+Htry1[z]][sta.p[top].y+Htry2[z]]//检查要走的下个位置是否可行 ) { nx=sta.p[top].x+Htry1[z];

ny=sta.p[top].y+Htry2[z]; sta.p[top].dir=z; top++; sta.p[top].x=nx; sta.p[top].y=ny; board [nx][ny]=top; chech [nx][ny]=true; z=-1; } else if(z==7)//如果不可行,而且是最好一次检查 { chech [sta.p[top].x][sta.p[top].y]=false; top--; while(1) { z=sta.p[top].dir; if(z!=7) break; else { chech [sta.p[top].x][sta.p[top].y]=false; top--; } } } if(top==-1||top==63)break;//如果回溯到-1,或者栈满,则退出循环 z++; } for(i=0;i<8;i++) { for(j=0;j<8;j++) cout<

相关文档
相关文档 最新文档