文档库 最新最全的文档下载
当前位置:文档库 › 汉诺塔与栈

汉诺塔与栈

汉诺塔与栈
汉诺塔与栈

计算机科学与工程学院

《算法与数据结构》试验报告[三]

专业班级10级计算机工程01 试验地点计算机大楼计工专业机房403 学生学号 1 指导教师蔡琼

学生姓名晏佳益试验时间2012-4-14

试验项目算法与数据结构

试验类别基础性()设计性()综合性(√)其它()

试验目的及要求(1)掌握栈的特点及其存储方法;(2)掌握栈的常见算法以及程序实现;(3)了解递归的工作过程。

绩评定表

类别评分标准分值得分合计

上机表现积极出勤、遵守纪律

主动完成设计任务

30分

程序与报告程序代码规范、功能正确

报告详实完整、体现收获

70分

备注:

评阅教师:

日期:年月日

试验内容

一、实验目的和要求

1、实验目的:

(1)掌握栈的特点及其存储方法;

(2)掌握栈的常见算法以及程序实现;

(3)了解递归的工作过程。

2、实验内容

Hanoi塔问题。(要求4个盘子移动,输出中间结果)

3、实验要求:用栈与递归函数实现。

二、设计分析

该问题涉及到递归调用问题,同时要求运用栈的知识。

对于栈的递归调用,已经有经典函数,只需记住就行。

而对于栈的运用,主要是其基本操作:栈的建立,初始化,进栈,出栈,显示栈内元素,以及销毁栈。对于某个盘子从“A->B”:表示从A出栈,进栈到B;

同时,要注意的是输入报错机制。

三、源程序代码

#include

#include

using namespace std;

typedef int ElementType;

#define MaxSize 4

typedef struct

{

ElementType data[MaxSize];

int top;

}SqStack;//建立栈;

void InitStack(SqStack *&s) //栈的初始化;

{

s=(SqStack *)malloc(sizeof(SqStack));

s->top=-1;

}

void Push(SqStack * &s,int e) //进栈;

{

if((s->top)>(MaxSize-1))

{

cout<<"栈已满,不能再进栈!!!"<

return;

}

else

{

s->top++;

s->data[s->top]=e;

cout<<"\t"<

}

}

void Pop(SqStack *&s,ElementType e) //出栈;

{

if(s->top==-1)

cout<<"栈为空,没有元素出栈!!!"<

else

{

e=s->data[s->top];

s->top--;

cout<

}

}

int GetTop(SqStack *s) //取栈顶元素;

{

ElementType e;

if(s->top==-1)

return -1;

else

{

e=s->data[s->top];

return e;

}

}

void DispStack(SqStack *s) //显示栈中元素;

{

int i;

for(i=s->top;i>=0;i--)

cout<data[i]<<"\t";

cout<<"\n";

}

void ClearStack(SqStack *&s) //销毁栈;

{

free(s);

}

void Move(char A,char C,SqStack *&sa,SqStack *&sb,SqStack *&sc) {

int e;

cout<"<

if(A=='a')

{

e=GetTop(sa);

Pop(sa,e);

}

else if(A=='b')

{

e=GetTop(sb);

Pop(sb,e);

}

else if (A=='c')

{

e=GetTop(sc);

Pop(sc,e);

}

if(C=='a')

{

Push(sa,e);

}

else if(C=='b')

{

Push(sb,e);

}

else if(C=='c')

{

Push(sc,e);

}

cout<<"塔a内:";

DispStack(sa);

cout<<"塔b内:";

DispStack(sb);

cout<<"塔c内:";

DispStack(sc);

}

void Hanoi(int n, char A, char B, char C,SqStack *&sa,SqStack *&sb,SqStack *&sc) //第一列为语句行号

{

if (n==1)

Move(A,C,sa,sb,sc); //Move是一个抽象操作,表示将碟子从A移到C 上

else

{

Hanoi(n-1, A, C, B,sa,sb,sc);

Move(A,C,sa,sb,sc);

Hanoi(n-1, B, A, C,sa,sb,sc);

}

}

void main()

{

SqStack *sa,*sb,*sc;

InitStack(sa);

InitStack(sb);

InitStack(sc);

for(int i=MaxSize;i>=1;i--)

Push(sa,i);

cout<<"塔a内:";

DispStack(sa);

cout<<"塔b内:";

DispStack(sb);

cout<<"塔c内:";

DispStack(sc);

Hanoi(MaxSize,'a','b','c',sa,sb,sc);

ClearStack(sa);

ClearStack(sb);

ClearStack(sc);

}

四、测试用例(尽量覆盖所有分支)当盘子为四个时,运行程序为:

五、实验总结

基于对c++语言学习的深刻点,所以我这次用c++语言来编写这个程序,在编程的过程中我个人认为,如果只是将该算法实现,找出整个过程的话,是很简单的。但是如果要加上栈,用栈实现盘子的移动,就把重心转移到了栈的实现上。

在此次实验中,更加深刻体会到了栈的用法,更加体会到了怎样去建立栈,初始化,进栈,出栈,显示栈中元素,销毁栈等。更重要的是体会到,栈是一个模型,主要运用于先进后出的类型。

通过这次编程我受益匪浅,学到了不少的课外知识,同时锻炼了动手能力和实践能力,对今后的学习起到良好的作用,对我以后学习这门课程有很大的帮助。我相信,通过这样一次次的实验会让自己对编程的实现更精通,更快,更简单,让我更快得掌握编程的实质与核心。

数据结构考研真题 栈和队列

第3章栈和队列 一选择题 1. 对于栈操作数据的原则是()。【青岛大学 2001 五、2(2分)】 A. 先进先出 B. 后进先出 C. 后进后出 D. 不分顺序 2. 在作进栈运算时,应先判别栈是否( ① ),在作退栈运算时应先判别栈是否( ② )。当栈中元素为n个,作进栈运算时发生上溢,则说明该栈的最大容量为( ③ )。 为了增加内存空间的利用率和减少溢出的可能性,由两个栈共享一片连续的内存空间时,应将两栈的( ④ )分别设在这片内存空间的两端,这样,当( ⑤ )时,才产生上溢。 ①, ②: A. 空 B. 满 C. 上溢 D. 下溢 ③: A. n-1 B. n C. n+1 D. n/2 ④: A. 长度 B. 深度 C. 栈顶 D. 栈底 ⑤: A. 两个栈的栈顶同时到达栈空间的中心点. B. 其中一个栈的栈顶到达栈空间的中心点. C. 两个栈的栈顶在栈空间的某一位置相遇. D. 两个栈均不空,且一个栈的栈顶到达另一个栈的栈底. 【上海海运学院 1997 二、1(5分)】【上海海运学院 1999 二、1(5分)】 3. 一个栈的输入序列为123…n,若输出序列的第一个元素是n,输出第i(1<=i<=n)个元素是()。 A. 不确定 B. n-i+1 C. i D. n-i 【中山大学 1999 一、9(1分)】 4. 若一个栈的输入序列为1,2,3,…,n,输出序列的第一个元素是i,则第j个输出元素是()。 A. i-j-1 B. i-j C. j-i+1 D. 不确定的 【武汉大学 2000 二、3】 5. 若已知一个栈的入栈序列是1,2,3,…,n,其输出序列为p 1,p 2 ,p 3 ,…,p N ,若p N 是n,则 p i 是( )。 A. i B. n-i C. n-i+1 D. 不确定 【南京理工大学 2001 一、1(1.5分)】 6. 有六个元素6,5,4,3,2,1 的顺序进栈,问下列哪一个不是合法的出栈序列?() A. 5 4 3 6 1 2 B. 4 5 3 1 2 6 C. 3 4 6 5 2 1 D. 2 3 4 1 5 6 【北方交通大学 2001 一、3(2分)】 7. 设栈的输入序列是1,2,3,4,则()不可能是其出栈序列。【中科院计算所2000一、10(2分)】 A. 1,2,4,3, B. 2,1,3,4, C. 1,4,3,2, D. 4,3,1,2, E. 3,2,1,4, 8. 一个栈的输入序列为1 2 3 4 5,则下列序列中不可能是栈的输出序列的是()。 A. 2 3 4 1 5 B. 5 4 1 3 2 C. 2 3 1 4 5 D. 1 5 4 3 2 【南开大学 2000 一、1】【山东大学 2001 二、4 (1分)】【北京理工大学 2000 一、2(2分)】 9. 设一个栈的输入序列是 1,2,3,4,5,则下列序列中,是栈的合法输出序列的是()。 A. 5 1 2 3 4 B. 4 5 1 3 2 C. 4 3 1 2 5 D. 3 2 1 5 4 【合肥工业大学 2001 一、1(2分)】 10. 某堆栈的输入序列为a, b,c ,d,下面的四个序列中,不可能是它的输出序列的是

汉诺塔问题的三种实现

// 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

第三章栈和队列习题_数据结构电子教案

习题三栈和队列 一单项选择题 1. 在作进栈运算时,应先判别栈是否(① ),在作退栈运算时应先判别栈是否(② )。当栈中元素为n个,作进栈运算时发生上溢,则说明该栈的最大容量为(③ )。 ①, ②: A. 空 B. 满 C. 上溢 D. 下溢 ③: A. n-1 B. n C. n+1 D. n/2 2.若已知一个栈的进栈序列是1,2,3,…,n,其输出序列为p1,p2,p3,...,pn,若p1=3,则p2为( )。 A 可能是2 B 一定是2 C 可能是1 D 一定是1 3. 有六个元素6,5,4,3,2,1 的顺序进栈,问下列哪一个不是合法的出栈序列?() A. 5 4 3 6 1 2 B. 4 5 3 1 2 6 C. 3 4 6 5 2 1 D. 2 3 4 1 5 6 4.设有一顺序栈S,元素s1,s2,s3,s4,s5,s6依次进栈,如果6个元素出栈的顺序是s2,s3,s4, s6, s5,s1,则栈的容量至少应该是() A.2 B. 3 C. 5 D.6 5. 若栈采用顺序存储方式存储,现两栈共享空间V[1..m],top[i]代表第i个栈( i =1,2)栈顶,栈1的底在v[1],栈2的底在V[m],则栈满的条件是()。 A. |top[2]-top[1]|=0 B. top[1]+1=top[2] C. top[1]+top[2]=m D. top[1]=top[2] 6. 执行完下列语句段后,i值为:() int f(int x) { return ((x>0) ? x* f(x-1):2);} int i ; i =f(f(1)); A.2 B. 4 C. 8 D. 无限递归 7. 表达式3* 2^(4+2*2-6*3)-5求值过程中当扫描到6时,对象栈和算符栈为(),其中^为乘幂。 A. 3,2,4,1,1;(*^(+*- B. 3,2,8;(*^- C. 3,2,4,2,2;(*^(- D. 3,2,8;(*^(- 8. 用链接方式存储的队列,在进行删除运算时()。 A. 仅修改头指针 B. 仅修改尾指针 C. 头、尾指针都要修改 D. 头、尾指针可能都要修改 9. 递归过程或函数调用时,处理参数及返回地址,要用一种称为()的数据结构。 A.队列 B.多维数组 C.栈 D. 线性表 10.设C语言数组Data[m+1]作为循环队列SQ的存储空间, front为队头指针,rear为队尾指针,则执行出队操作的语句为() A.front=front+1 B. front=(front+1)% m C.rear=(rear+1)%(m+1) D. front=(front+1)%(m+1) 11.循环队列的队满条件为 ( ) A. (sq.rear+1) % maxsize ==(sq.front+1) % maxsize; B. (sq.front+1) % maxsize ==sq.rear C. (sq.rear+1) % maxsize ==sq.front D.sq.rear ==sq.front

汉诺塔非递归算法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.一个顺序栈一旦被声明,其占用空间的大小()。 A.已固定B.可以改变C.不能固定D.动态变化 2.链栈和顺序栈相比,有一个比较明显的缺点,即()。 A.插入操作更加方便B.通常不会出现栈满的情况 C.不会出现栈空的情况D.删除操作更加方便 3.用单链表表示的链式队列的队头在链表的()位置。 A.链头B.链尾C.链中D.任意位置 4.在解决计算机主机与打印机之间速度不匹配问题时通常设置一个打印数据缓冲区,主机将要输出的数据依次写入缓冲区中,而打印机则从缓冲区中取出数据打印,该缓冲区应该是一个()结构。 A.堆栈B.队列C.数组D.先性表 5.若已知一个栈的入栈序列是1,2,3,…,30,其输出序列是p1,p2,p3,…p n,若p1=30,则p10为()。 A.11 B.20 C.19 D.21 6.循环队列A[m] 存放其元素,用front和rear分别表示队头及队尾,则循环队列满的条件是()。 A.(rear+1)%m=front B.rear =front+1 C.rear=front D.(rear+1)%m-1=front 7.在一个栈顶指针为top的链栈中,将一个p指针所指的结点入栈,应执行()。 A.top->next=p; B.p->next=top->next; top->next=p; C.p->next=top; top=p; D.p->next=top->next; top=top->next; 8.在一个栈顶指针为top的链栈中删除一个结点时,用x保存被删结点的值,则执行()。 A.x=top;top=top->next; B.x=top->data;

c语言迷宫问题的求解(栈和递归)

实验报告 【实验名称】项目一迷宫问题的求解 【实验目的】 1.了解栈的基本操作以及充分理解栈的特点。熟悉掌握栈的基本操作和结构体 的运用。 2.学会用栈或者递归方法解决迷宫问题。 【实验原理】 1.本次实验中,以二维数组maze[row][col]表示迷宫,0表示通路,1表示墙,在构建迷宫时,为了清晰显示,在最外层添加一圈墙。 2.算法的核心思想是利用栈后进先出的特点,对迷宫进行探索,如果此路可行,则将此坐标的信息入栈,如果此路不通,则将此坐标的信息出栈。 3.输入形式:根据控制台的提示,依次输入迷宫的行数、列数,然后输入迷宫,再输入入口和出口坐标。 4.输出形式:由用户选择,由递归、非递归两种求解方式输出一条迷宫通路。以非递归方式会显示一种求解方案,并给出相应的三元组序列和迷宫方阵;以递归方式则会显示出所有的路线。 【实验内容】 1.需求分析 (1)问题描述 以一个m*n的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍。设计一个程序,对任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论。 要求以递归和非递归两种方式分别输出一条迷宫的通路,以带方向坐标和迷宫图像表示。

(2)基本要求 (1)首先实现一个以链表作存储结构的栈类型,然后编写一个求解迷宫的非递归程序。求得的通路以三元组(i,j,d)的形式输出。其中:(i,j)指示迷宫中的一个坐标,d表示走到下一坐标的方向。如,对于下列数据的迷宫,输出一条通路为:(1,1,1),(1,2,2),(2,2,2),(3,2,3),(3,1,2),…。 (2)编写递归形式的算法,求得迷宫中所有可能的通路。 (3)以方阵形式输出迷宫及其通路。 2.概要设计 (1)栈的抽象数据类型 ADT Stack{ 数据对象:D={ai|ai∈ElemSet, i=1,2, …,n, n≥0} 数据关系:R1={|ai-1,ai∈D, i=1,2, …,n } 约定an端为栈顶,a1端为栈底。 基本操作: InitStack( &S ) 操作结果:构造一个空栈S。 DestroyStack ( &S ) 初始条件:栈S已存在。 操作结果:销毁栈S。 ClearStack( &S ) 初始条件:栈S已存在。 操作结果:将S清为空栈。 StackEmpty( S ) 初始条件:栈S已存在。 操作结果:若S为空栈,则返回TRUE,否则返回FALSE。 StackLength( S ) 初始条件:栈S已存在。 操作结果:返回S的数据元素个数,即栈的长度。 GetTop( S, &e ) 初始条件:栈S已存在且非空。 操作结果:用e返回S的栈顶元素。 Push( &S, e ) 初始条件:栈S已存在。 操作结果:插入元素e为新的栈顶元素。 Pop( &S, &e ) 初始条件:栈S已存在且非空。 操作结果:删除S的栈顶元素,并用e返回其值。 }ADT Stack (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<<"盘子从"<

栈与递归的关系

栈与递归的关系 姓名:郭小兵 学号:1007010210 专业:信息与计算科学院系:理学院 指导老师:彭长根 2012年10月17日

栈与递归的关系 郭小兵 摘要递归是计算机科学中一个极为重要的概念,许多计算机高级语言都具有递归的功能,对于初学计算机者来讲,递归是一个简单易懂的概念,但真正深刻理解递归,正确自如的运用递归编写程序却非易事,本文通过一些实例来阐述递归在计算机内的实现及递归到非递归的转换,也许使读者能加深对递归的理解。 关键词栈递归非递归 引言递归是一种程序设计的方式和思想。计算机在执行递归程序时,是通过栈的调用来实现的。栈,从抽象层面上看,是一种线性的数据结构,这中结构的特点是“先进后出”,即假设有a,b,c三个元素,依次放某个栈式存储空间中,要从该空间中拿到这些元素,那么只能以c、b、a的顺序得到。递归程序是将复杂问题分解为一系列简单的问题,从要解的问题起,逐步分解,并将每步分解得到的问题放入“栈”中,这样栈顶是最后分解得到的最简单的问题,解决了这个问题后,次简单的问题可以得到答案,以此类推。分解问题是进栈(或者说压栈)的过程,解决问题是一个出栈的过程。 科学家对栈与递归都做了很多深入的研究,研究表明“递归算法

和栈都有后进先出这个性质,基本上能用递归完成的算法都可以用栈完成,都是运用后进先出这个性质的”这个性质可用于进制的转换。与汇编程序设计中主程序和子程序之间的链接及信息交换相类似,在高级语言编制的程序中,调用函数和被调用函数之间的链接及信息交换需过栈来进行。递归是计算科学中一个极为重要的概念。许多计算机高级语言都具有递归的功能,本文将通过一些是例来阐述递归在计算机内的实现及递归到非递归的转换,也许能加深对递归的理解。递归是某一事物直接或间接地由自己完成。一个函数直接或间接地调用本身,便构成了函数的递归调用,前者称之为直接递归调用,后者为间接递归调用。递归会使某些看起来不容易解决的问题变得容易解决。特别当一个问题蕴含递归特性且结构比较复杂时,采用递归算法往往要自然、简洁、清晰,写出的程序较为简短。在很多时候,程序结构简单,可读性好甚至比运行时间更重要,所以掌握递归算法也就存在一定的必要性。但许多人,特别是计算机专业低年级和一些初学者,往往觉得递归很难理解。为了更好地掌握他,了解递归过程的操作原理就更有意义了。

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

一、教学思想(包括教学背景、教学目标) 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、知识点的引入使用故事诱导法讲授 通过“老和尚讲故事”引入函数的递归调用,并通过“世界末日问题” 故事引入非数值型问题的递归分析,激发学习积极性,挖掘学生潜能。

第3章-栈与队列习题参考答案

习题三参考答案 备注: 红色字体标明的是与书本内容有改动的内容。 一、选择题 1.在栈中存取数据的原则是( B )。 A.先进先出 B. 先进后出 C. 后进后出 D. 没有限制 2.若将整数1、2、3、4依次进栈,则不可能得到的出栈序列是( D )。 A.1234 B. 1324 C. 4321 D. 1423 3.在链栈中,进行出栈操作时(B )。 A.需要判断栈是否满 B. 需要判断栈是否为空 C. 需要判断栈元素的类型 D. 无需对栈作任何差别 4.在顺序栈中,若栈顶指针top指向栈顶元素的下一个存储单元,且顺序栈的最大容量是maxSize,则顺序栈的判空条件是( A )。 A.top==0 B.top==-1 C. top==maxSize D.top==maxSize-1 5.在顺序栈中,若栈顶指针top指向栈顶元素的下一个存储单元,且顺序栈的最大容量是maxSize。则顺序栈的判满的条件是( C )。 A.top==0 B.top==-1 C. top==maxSize D.top==maxSize-1 6.在队列中存取数据元素的原则是( A )。 A.先进先出 B. 先进后出 C. 后进后出 D. 没有限制 7.在循环顺序队列中,假设以少用一个存储单元的方法来区分队列判满和判空的条件,front和rear分别为队首和队尾指针,它们分别指向队首元素和队尾元素的下一个存储单元,队列的最大存储容量为maxSize,则队列的判空条件是(A )。 A.front==rear B. front!=rear C. front==rear+1 D. front==(rear+1)% maxSize 8.在循环顺序队列中,假设以少用一个存储单元的方法来区分队列判满和判空的条件,front和rear分别为队首和队尾指针,它们分别指向队首元素和队尾元素的下一个存储单元,队列的最大存储容量为maxSize,则队列的判满条件是(D )。 A.front==rear B. front!=rear C. front==rear+1 D. front==(rear+1)% maxSize 9.在循环顺序队列中,假设以少用一个存储单元的方法来区分队列判满和判空的条件,front和rear分别为队首 和队尾指针,它们分别指向队首元素和队尾元素的下一个存储单元,队列的最大存储容量为maxSize,则队列的长度是(C )。 A.rear-front B. rear-front+1 C. (rear-front+maxSize)%maxSize D. (rear-front+1)%maxSize 10.设长度为n的链队列采用单循环链表加以表示,若只设一个头指针指向队首元素,则入队操作的时间复杂度 为( B )。 A.O(1) B.O(n) C.O(log2n) D.O(n2) 二、填空题 1.栈是一种操作受限的特殊线性表,其特殊性体现在其插入和删除操作都限制在表尾进行。允许插入和删除 操作的一端称为栈顶,而另一端称为栈底。栈具有后进先出的特点。 2.栈也有两种存储结构,一种是顺序存储,另一种是链式存储;以这两种存储结构存储的栈分别称为顺序 栈和链栈。 3.在顺序栈中,假设栈顶指针top是指向栈顶元素的下一个存储单元,则顺序栈判空的条件是 top==0 ; 栈顶

第三章+栈和队列(参考答案)

第三章栈和队列 一、判断题 1、链栈的初始化是指开辟足够多的结点,然后置栈顶指针为 NULL。(×) 2、递归定义的数据结构通常不需要用递归的算法来实现对它的操作。(×) 二、填空题 1、向一个链式栈插入一个新结点时,首先把栈顶指针的值赋给新结点的指针域,然后把新结点的存储位置赋给___栈顶指针_____。 2、迷宫问题是一个回溯控制的问题,最好使用____栈______的方法来解决。 3、有如下递归过程: Void Print(int w) { int i; if (w!=0) { Print(w?1); for (i=1;i<=w;i++) printf(“%3d”,w); printf(“\n”); } } 调用语句print(4)的结果是__________。 1 2 2 3 3 3 4 4 4 4 4、假设用循环单链表实现队列,若队列非空,且队尾指针为R, 则将新结点S加入队列时,需执行下面语句:_ S->next=R->next _________;___ R->next=S _______;R=S; 三、选择题 1、设有4个数据元素a1、a 2、a3和a4,对他们分别进行栈操作或队操作。在进栈或进队操作时,按a1、a2、a 3、a4次序每次进入一个元素。假设栈或队的初始状态都是空。 现要进行的栈操作是进栈两次,出栈一次,再进栈两次,出栈一次;这时,第一次出栈得到的元素是 A 2,第二次出栈得到的元素是 B 4;类似地,考虑对这四个数据元素进行的队操作是进队两次,出队一次,再进队两次,出队一次;这时,第一次出队得到的元素是 C 1,第二次出队得到的元素是 D 2。经操作后,最后在栈中或队中的元素还有 E 2个。 供选择的答案: A~D:①a1 ②a2 ③ a3 ④a4 E:①1 ②2 ③ 3 ④ 0 2、栈是一种线性表,它的特点是 A 2。设用一维数组A[1,…,n]来表示一个栈,A[n]为栈底,用整型变量T指示当前栈顶位置,A[T]为栈顶元素。往栈中推入(PUSH)一个新元素时,变量T的值 B 2;从栈中弹出(POP)一个元素时,变量T的值 C 1。设栈空时,有输入序列a,b,c,经过PUSH,POP,PUSH,PUSH,POP操作后,从栈中弹出的元素的序列是 D 6,变量T的值是 E 4。 供选择的答案: A:①先进先出②后进先出③进优于出④出优于进⑤随机进出 B,C:①加1 ②减1 ③不变④清⑤加2 ⑥减2 D:① a,b ②b,c ③c,a ④b,a ⑤ c,b ⑥a,c E:① n+1 ②n+2 ③ n ④ n-1 ⑤ n-2 3、在做进栈运算时,应先判别栈是否 A 2;在做退栈运算时,应先判别栈是否 B 1。当栈中元素为n个,做进栈运算时发生上溢,则说明该栈的最大容量为 C 2。

数据结构利用栈实现递归

利用栈实现递归参考程序1(Turbo2.0环境): #define MAXSIZE 100 #include struct stack{ int data[MAXSIZE]; int top; }; void init(struct stack *s){ s->top=-1; } int empty(struct stack *s){ if(s->top==-1) return 1; else return 0; } void push(struct stack *s,int i){ if(s->top==MAXSIZE-1){ printf("Stack is full\n"); return; } s->top++; s->data[s->top]=i; } int pop(struct stack *s){ if(empty(s)){ printf("stack is empty"); return -1; } return(s->data[s->top--]); } void trans(int num){ struct stack s; int k; init(&s); while(num){ k=num%16; push(&s,k); num=num/16; } while(!empty(&s)){ k=pop(&s); if(k<10)

printf("%d",k); else printf("%c",k+55); } printf("\n"); } main(){ int num; clrscr(); printf("Input a num,-1 to quit:\n"); scanf("%d",&num); while(num!=-1){ trans(num); scanf("%d",&num); } } 参考程序2:(C++/VC环境) #define STACK_INIT_SIZE 100//存储空间初始分配量 #define OVERFLOW -1 #define OK 1 #define STACKINCREMENT 10//存储空间分配增量 #define ERROR 0 #define TRUE 1 #define FALSE 0 #include "stdio.h" #include "stdlib.h" #include "malloc.h" #include "iostream.h" typedef int status; typedef char SElemType; typedef struct{//顺序栈的定义 SElemType *base; SElemType *top; int stacksize; }SqStack; status InitStack(SqStack &S){//构造一个空栈S S.base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType)); if(!S.base)exit(OVERFLOW);//存储分配失败 S.top=S.base; S.stacksize=STACK_INIT_SIZE; return OK; }

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

汉诺塔递归与非递归算法研究 作者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个盘的汉

递归算法工作栈的变化详解

通常,一个函数在调用另一个函数之前,要作如下的事情:a)将实在参数,返回地址等信息传递给被调用函数保存; b)为被调用函数的局部变量分配存储区;c)将控制转移到被调函数的入口. 从被调用函数返回调用函数之前,也要做三件事情:a)保存被调函数的计算结果;b)释放被调函数的数据区;c)依照被调函数保存的返回地址将控制转移到调用函数.所有的这些,不论是变量还是地址,本质上来说都是"数据",都是保存在系统所分配的栈中的. ok,到这里已经解决了第一个问题:递归调用时数据都是保存在栈中的,有多少个数据需要保存就要设置多少个栈,而且最重要的一点是:控制所有这些栈的栈顶指针都是相同的,否则无法实现同步. 下面来解决第二个问题:在非递归中,程序如何知道到底要转移到哪个部分继续执行?回到上面说的树的三种遍历方式,抽象出来只有三种操作:访问当前结点,访问左子树,访问右子树.这三种操作的顺序不同,遍历方式也不同.如果我们再抽象一点,对这三种操作再进行一个概括,可以得到:a)访问当前结点:对目前的数据进行一些处理;b)访问左子树:变换当前的数据以进行下一次处理;c)访问右子树:再次变换当前的数据以进行下一次处理(与访问左子树所不同的方式). 下面以先序遍历来说明: void preorder_recursive(Bitree T) /* 先序遍历二叉树的递归算法*/ { if (T) { visit(T); /* 访问当前结点*/ preorder_recursive(T->lchild); /* 访问左子树*/ preorder_recursive(T->rchild); /* 访问右子树*/ } } visit(T)这个操作就是对当前数据进行的处理, preorder_recursive(T->lchild)就是把当前数据变换为它的左子树,访问右子树的操作可以同样理解了. 现在回到我们提出的第二个问题:如何确定转移到哪里继续执行?关键在于一下三个地方:a)确定对当前数据的访问顺序,简单一点说就是确定这个递归程序可以转换为哪种方式遍历的树结构;b)确定这个递归函数转换为递归调用树时的分支是如何划分的,即确定什么是这个递归调用树的"左子树"和"右子树"c)确定这个递归调用树何时返回,即确定什么结点是这个递归调用树的"叶子结点".

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

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<<"输入的盘子数量错误!!!"<

第三章栈与队列 练习题

第三章栈与队列练习题 一、选择题 1、栈结构通常采用的两种存储结构是( A )。 A、顺序存储结构和链表存储结构 B、散列和索引 C、链表存储结构和数组 D、线性链表和非线性存储 2、设栈ST用顺序存储结构表示,则栈ST为空的条件是(B) A、ST.top-ST.base<>0 B、ST.top-ST.base==0 C、ST.top-ST.base<>n D、ST.top-ST.base==n 3、向一个栈顶指针为HS的链栈中插入一个s结点时,则执行() A、HS->next=s; B、s->next=HS->next;HS->next=s; C、s->next=HS;HS=s; D、s->next=HS;HS=HS->next; 4、从一个栈顶指针为HS的链栈中删除一个结点,用x保存被删除结点的值,则执行(C) A、x=HS;HS=HS->next; B、HS=HS->next;x=HS->data; C、 x=HS->data;HS=HS->next; D、s->next=Hs;Hs=HS->next; 7、一个队列的入列序列是1,2,3,4,则队列的输出序列是(B )//尾插入元素,头删除元素。 A、4,3,2,1 B、1,2,3,4 C、1,4,3,2 D、3,2,4,1 9、循环队列SQ采用数组空间SQ.base[0,n-1]存放其元素值,已知其头尾指针分别是front和rear,则判定此循环队列为满的条件是(C)//不懂啊!!! A、Q.front==Q.rear B、Q.front!=Q.rear C、Q.front==(Q.rear+1)%n D、Q.front!=(Q.rear+1)%n 11、用单链表表示的链式队列的队头在链表的(A)位置 A、链头 B、链尾 C、链中 12、判定一个链队列Q(最多元素为n个)为空的条件是( A) A、Q.front==Q.rear B、Q.front!=Q.rear C、Q.front==(Q.rear+1)%n D、Q.front!=(Q.rear+1)%n 14、在一个链队列Q中,删除一个结点需要执行的指令是(C) A、Q.rear=Q.front->next; B、Q.rear->next=Q.rear->next->next; C、 Q.front->next=Q.front->next->next; D、Q.front=Q.rear->next; 15、用不带头结点的单链表存储队列,其队头指针指向队头结点,队尾指针指向队尾结点,则在进行出队操作时(D) A、仅修改队头指针 B、仅修改队尾指针 C、队头尾指针都要修改 D、队头尾指针都可能要修改。 16、栈和队列的共同点是(C) A、都是先进后出 B、都是先进先出 C、只允许在端点处插入和删除元素 D、没有共同点 18、设有一顺序栈S,元素s1,s2,s3,s4,s5,s6依次进栈,如果6个元素出栈的顺序是s2,s3,s4,s6,s5,s1,则栈的容量至少应该是(B) A、2 B、 3 C、 5 D、 6 20、设有一顺序栈已经含有3个元素,如图3.1所示元素a4正等待进栈。下列不可能出现的出栈序列是(A) 0 maxsize-1

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