汉诺塔栈c语言
数据结构——用C语言描述(第3版)教学课件第3章 栈和队列

if(S->top==-1) /*栈为空*/
return(FALSE);
else
{*x = S->elem[S->top];
return(TRUE);
}
返回主目录}[注意]:在实现GetTop操作时,也可将参数说明SeqStack *S 改为SeqStack S,也就是将传地址改为传值方式。传 值比传地址容易理解,但传地址比传值更节省时间、 空间。
返回主目录
算法:
void BracketMatch(char *str) {Stack S; int i; char ch; InitStack(&S); For(i=0; str[i]!='\0'; i++) {switch(str[i])
{case '(': case '[': case '{':
3.1.3 栈的应用举例
1. 括号匹配问题
思想:在检验算法中设置一个栈,若读入的是左括号, 则直接入栈,等待相匹配的同类右括号;若读入的是 右括号,且与当前栈顶的左括号同类型,则二者匹配, 将栈顶的左括号出栈,否则属于不合法的情况。另外, 如果输入序列已读尽,而栈中仍有等待匹配的左括号, 或者读入了一个右括号,而栈中已无等待匹配的左括 号,均属不合法的情况。当输入序列和栈同时变为空 时,说明所有括号完全匹配。
return(TRUE);
}
返回主目录
【思考题】
如果将可利用的空闲结点空间组织成链栈来管理,则申 请一个新结点(类似C语言中的malloc函数)相当于链 栈的什么操作?归还一个无用结点(类似C语言中的 free函数)相当于链栈的什么操作?试分别写出从链栈 中申请一个新结点和归还一个空闲结点的算法。
C语言程序设计课程设计报告---汉诺塔问题

XXXX大学计算机科学与技术学院课程设计报告2012 — 2013学年第一学期课程名称C/C++高级语言程序设计课程设计设计题目小游戏和图形处理汉诺塔问题学生姓名XXX学号XXXXXXX专业班级XXXXXXXXXXX指导教师XX2012 年X 月XX 日目录一、课程设计问题描述 (1)1、课程设计题目 (1)2、设计任务要求 (1)二、总体设计 (1)1、设计思路 (1)2、汉诺塔求解流程图 (2)三、详细设计 (2)1、汉诺塔问题描述 (2)2、算法分析 (3)3、实现递归的条件 (4)4、用C语言实现 (4)四、程序运行结果测试与分析 (4)1、打开Microsoft Visual C++ 6.0操作平台输入以下的源代码 (4)2、编译源代码 (5)3、组建 (5)4、执行 (5)5、运行结果 (6)6、按任意键结束程序 (7)五、结论与心得 (7)六、参考文献 (8)七、附录:程序源代码 (8)一、课程设计问题描述1、课程设计题目汉诺塔问题2、设计任务要求输入盘子数(2个以上有效),移动速度,开始演示汉诺塔移动的步骤,要求:盘子A,B,C柱需要自己绘制,初始时盘子在A柱上通过B柱最终移动到C 柱上,显示出盘子在几个柱之间的移动过程。
二、总体设计1、设计思路对于一个类似的这样的问题,任何一个人都不可能直接写出移动盘子的每一个具体步骤。
可以利用这样的统筹管理的办法求解:我们假设把该任务交给一个僧人,为了方便叙述,将他编号为64。
僧人自然会这样想:假如有另外一个僧人能有办法将63个盘子从一个座移到另一个座,那么问题就解决了,此时僧人A B C64只需这样做:(1).命令僧人63将63个盘子从A座移到C座(2).自己将最底下的最大的一个盘子从A座移到C座(3).再命令僧人63将63个盘子从B座移到C座为了解决将63个盘子从A座移到B座的问题,僧人63又想:如果能再有一个僧人62能将62个盘子移动到另一座,我就能将63个盘子从A座移动到B座。
scratch汉诺塔递归算法

Scratch汉诺塔递归算法1. 引言汉诺塔(Hanoi Tower)是一种经典的数学问题,它可以帮助我们理解递归算法的原理和应用。
在这个任务中,我们将使用Scratch编程语言来实现汉诺塔递归算法。
2. 汉诺塔问题简介汉诺塔问题源于印度传说中的一个故事。
据说,在一个庙里有三根针,第一根针上套着64个不同大小的金盘子,大的在下面,小的在上面。
庙里的和尚每天都要将这些金盘子从第一根针移动到第三根针上,但是移动时必须遵守以下规则:1.每次只能移动一个盘子;2.每次移动必须将较小的盘子放在较大的盘子上面;3.可以借助第二根针作为中转。
3. 算法设计思路要解决汉诺塔问题,我们可以使用递归算法。
递归是一种函数调用自身的方法。
对于汉诺塔问题来说,我们可以将其分解为三个步骤:1.将n-1个盘子从第一根针移动到第二根针(借助第三根针作为中转);2.将第n个盘子从第一根针移动到第三根针;3.将n-1个盘子从第二根针移动到第三根针(借助第一根针作为中转)。
这样,我们可以通过递归调用这三个步骤来解决汉诺塔问题。
4. Scratch实现在Scratch中实现汉诺塔递归算法,我们需要创建以下角色和代码块:4.1 角色设计我们需要创建三个角色来表示三根针,以及一个角色来表示金盘子。
每个角色都应该有一个变量来表示当前所在的位置。
4.2 代码块设计我们需要设计以下代码块来实现汉诺塔递归算法:4.2.1 初始化代码块在初始化时,我们需要将金盘子放置在第一根针上,并设置好每个金盘子的大小。
当绿旗被点击时把金盘子放置在第一根针上设置金盘子大小4.2.2 移动代码块移动一个金盘子的过程可以分为以下几步:1.判断当前金盘子是否在目标针上;2.如果在目标针上,结束移动;3.如果不在目标针上,找到下一个需要移动到的位置(借助另外一根针);4.将当前金盘子移动到下一个位置;5.递归调用移动代码块,将剩余的金盘子移动到目标针上。
当收到 [移动金盘子 v] 消息时如果 [当前位置 v] = [目标位置 v] ?那么结束此脚本否则设置 [下一个位置 v] 为 (3 - [当前位置 v] - [目标位置 v])把金盘子放置在第 [下一个位置 v] 根针上把金盘子移到第 [目标位置 v] 根针上发送消息 (移动金盘子) 给自己并等待 (0.5) 秒4.2.3 触发移动代码块为了触发整个移动过程,我们可以创建一个按钮,并在其点击事件中调用移动代码块。
汉诺塔游戏-----用C++编的

#ifndef HANIO_H_#define HANIO_Hclass Stack{private:enum{ MAX=50 };int m_node[MAX];int m_top;int m_size;int m_index;public:Stack();~Stack() { };bool Isfull() { return m_top==MAX-1 ;}; //堆栈满则返回TRUE bool Isempty() { return m_top==-1;}; //堆栈空则返回TRUE int Top() { return m_top; };int TopValue() { return m_node[m_top];};int GetDataFromIndex(int i) { return m_node[i]; };int GetIndex() { return m_index; } ;void SetIndex(int index) { m_index = index; };int Size() { return m_top+1; };bool Push(int data);bool Pop(int * pData);int MoveToNext();void OutPrint();};class Hanio{Stack m_stack[3];int m_num; //盘数int m_steps; //移动次数int m_times; //完成所用时间void print(char ch,int n);public:Hanio(int num=3);~Hanio() {};void GameStart();bool MoveFromTo(int x,int y); //从x号盘移动到y号盘void DrawPaletes(char ch='*'); //打印3个堆的盘子bool IsFinished() ; //结束返回TURE;int Solve(char from,char to,char auxiliary,int n); //求解其解法路径};#endif//hanio.cpp#include "hanio.h"#include <iostream>#include<cstdlib>#include<cstring>#include<cctype>#include<windows.h>Stack::Stack(){m_top=-1;m_index=m_top;for(int i=0;i<MAX;i++)m_node[i]=0;}bool Stack::Push(int data){if(Isfull())return false;m_top++;m_node[m_top]=data;m_index=m_top;return true;}bool Stack::Pop(int *pData){if(Isempty())return false;*pData=m_node[m_top];m_node[m_top]=0;m_top--;m_index=m_top;return true;}int Stack::MoveToNext(){int temp=m_index;m_index--;return m_node[temp];}void Stack::OutPrint(){if(m_top!=-1){for(int i=0;i<=m_top;i++)std::cout<<"["<<m_node[i]<<"]";}}///////////////////////////////////////Hanio::Hanio(int num){m_num=num;m_steps=0;m_times=0;for(int i=num;i>=1;i--)m_stack[0].Push(i);//m_stack[0].OutPrint();}void Hanio::print(char ch,int n){for(int i=1;i<=n;i++)std::cout<<ch;}void Hanio::DrawPaletes(char ch){int max;max=m_stack[0].Size()>m_stack[1].Size() ? m_stack[0].Size() : m_stack[1].Size();max=m_stack[2].Size()>max ? m_stack[2].Size() : max;//std::cout<<"Max:"<<max<<std::endl;m_stack[0].SetIndex(max-1);m_stack[1].SetIndex(max-1);m_stack[2].SetIndex(max-1);for(int i=1;i<=max;i++){int data1=m_stack[0].MoveToNext();int data2=m_stack[1].MoveToNext();int data3=m_stack[2].MoveToNext();if(data1==0)print(' ',20);else{print(' ',10-data1);print(ch,2*data1);print(' ',10-data1);}if(data2==0)print(' ',20);else{print(' ',10-data2);print(ch,2*data2);print(' ',10-data2);}if(data3==0)print(' ',20);else{print(' ',10-data3);print(ch,2*data3);print(' ',10-data1);}std::cout<<std::endl;}}bool Hanio::MoveFromTo(int x,int y){m_steps++; //计算所走的步数if(m_stack[x].Isempty()){std::cout<<x<<" pallete is empty ! continue !"<<std::endl; std::cin.get();return false;}if(m_stack[y].Isempty()){int data;m_stack[x].Pop(&data);m_stack[y].Push(data);return true;}else{if(m_stack[x].TopValue()>m_stack[y].TopValue()){std::cout<<"The board can't move from "<<x<<" plate to " <<y<<" plate!"<<std::endl;std::cin.get();return false;}else{int data;m_stack[x].Pop(&data);m_stack[y].Push(data);return true;}}}bool Hanio::IsFinished(){return m_stack[2].Top()==m_num-1;}void Hanio::GameStart(){using namespace std;UINT StartTime=::GetTickCount();UINT EndTime;while(1){system("cls");print('-',80);cout<<"steps: "<<m_steps; print(' ',20);cout<<"Used time: "<<m_times<<endl;print('-',80);cout<<endl; cout<<endl; print(' ',10); cout<<"A";print(' ',19); cout<<"B"; print(' ',19);cout<<"C"<<endl<<endl;Hanio::DrawPaletes();cout<<endl; cout<<endl;print('-',80);//测试游戏是否结束if(Hanio::IsFinished()){cout<<"你好强呀!从今天开始,维护世界和平的任务就交给你那!"<<endl;cin.get();break;}//输入命令并左相应的处理char szCommand[50];cout<<">>";cin.getline(szCommand,50);if(stricmp(szCommand,"QUIT")==0 || stricmp(szCommand,"Q")==0)break;if(stricmp(szCommand,"HELP")==0 || stricmp(szCommand,"H")==0){cout<<" 本游戏说明:"<<endl;cout<<" 该游戏由DAVID用C++编程,花费了一个多下午的时间呢!!!,由命令行来控制铁饼的移动:"<<endl;cout<<" QUIT / Q : 退出程序"<<endl;cout<<" HELP / H : 查看该说明"<<endl;cout<<" XY : X,Y的取值为A,B,C,意思时把X木桩最上面的铁饼移到Y 木桩"<<endl;cout<<" SOLVE / S : 显示求解该问题(移动铁饼)的最优路径..."<<endl; cin.get();}char ch1=toupper(szCommand[0]);char ch2=toupper(szCommand[1]);if( ch1=='A' && ch2=='B')Hanio::MoveFromTo(0,1);else if ( ch1=='A' && ch2=='C')MoveFromTo(0,2);else if ( ch1=='B' && ch2=='A')MoveFromTo(1,0);else if ( ch1=='B' && ch2=='C')MoveFromTo(1,2);else if ( ch1=='C' && ch2=='A')MoveFromTo(2,0);else if ( ch1=='C' && ch2=='B')MoveFromTo(2,1);else{cout<<"Bad command !"<<endl;cin.get();}//统计游戏所用时间EndTime=GetTickCount();m_times=(EndTime-StartTime)/1000;}}int Hanio::Solve(char from,char to,char auxiliary,int n) {if(n==1)return 0;}//main.cpp#include<iostream>#include"hanio.h"#include<cstdlib>using namespace std;int StartPicture();//返回选择的盘数int main(){int number;number=StartPicture();Hanio hanio(number);hanio.GameStart();return 0;}void print(char ch,int n){for(int i=1;i<=n;i++)std::cout<<ch;}int StartPicture(){using namespace std;int number;system("cls");system("color fc");print(' ',20);print('-',25);cout<<endl;print(' ',20);cout<<" Hanio(汉诺塔)"<<endl;print(' ',20);print('-',25);cout<<endl;print(' ',40);print('-',5);cout<<"By David"<<endl;print('=',80);cout<<" 相传在某一座古庙中有3根木桩,有24个铁盘由小到大放置在一根木柱上,庙中流传者一个传说:\"如果能把24个铁盘, 从一根木桩移动到另一个木桩,且必须遵守如下规则:"<<endl;cout<<endl;print(' ',5);cout<<"1. 每天只能动一个盘,而且只能从最上面的铁盘开始搬动."<<endl; print(' ',5);cout<<"2. 必须维持较小的铁盘在上方的原则"<<endl;cout<<endl;cout<<"这两个原则,则当24个铁盘完全般到另一个木桩时,世界就回永久和平!!"<<endl;cout<<"游戏的玩法可以在命令行中输入HELP查看"<<endl;cout<<endl;cout<<endl;cout<<endl;cout<<endl;cout<<endl;cout<<"再此输入你要搬的铁盘数(建议在1--10值间,太多回花费很长时间的)"<<endl;print('=',80);cout<<">>";cin>>number;cin.get();system("cls");return number;}。
数据结构(C语言)

广义表
由一个大的表像数组中一样存储元素,但内部的元素可以使结构不一样的,或者是所谓的子广义表。(树和有向图也可以用广义表来表示)
树
树的存储结构:
1、双亲表示法(用一组连续的存储空间(一维数组)存储树中的各个结点,数组中的一个元素表示树中的一个结点,数组元素为结构体类型,其中包括结点本身的信息以及结点的双亲结点在数组中的序号,但是这样并不能反映出孩子结点之间的兄弟关系来,所以,得利用一些手法来区别兄弟,可在结点结构中增设存放第一个孩子的域和存放第一个右兄弟的域,就能较方便地实现上述操作了,在实际存储的时候,第一列是序号,第二列是数据的具体内容,第三列则是通过固定的数字关系来反映这是第几代父母,第一代也就是根结点,其为-1,一下慢慢变大。这种存储方法比较适应存储数据和查找父结点。)
队列也是一种特殊的线性表。它所有的插入操作均限定在表的一端进行,而所有的删除操作则限定在表的另一端进行。允许删除元素的一端称为队头,允许插入元素的一端称为队尾,删除元素称为出队,插入元素称为进队。(假如是一个循环队列是会出现队满和队空的情况)
队列的顺序存储结构:利用连续的存储单元存储队列。
队列的链式存储结构:利用地址对队列中的数据进行连接,但存储的数据不一定连续。
数据组织(数据、数据元素、数据项)的三个层次:数据可由若干个数据元素构成,而数据元素又可以由一个或若干个数据项组成。
四种基本的数据结构:集合、线性结构、树形结构、图状结构。
顺序存储的特点是在内存中开辟一组连续的空间来存放数据,数据元素之间的逻辑关系通过元素在内存中存放的相对位置来确定。
汉诺塔问题非递归算法c语言

汉诺塔问题非递归算法c语言汉诺塔问题是一个经典的数学问题,也是一个常见的编程练习题。
在这个问题中,有三根柱子和一些圆盘,圆盘的大小不一,从小到大依次叠放在一根柱子上。
目标是将所有的圆盘从一根柱子移动到另一根柱子,移动过程中要保证大的圆盘在小的圆盘上面。
同时,每次只能移动一个圆盘,且不能把一个大的圆盘放在一个小的圆盘上面。
在解决汉诺塔问题时,通常采用递归算法。
但是递归算法的效率并不高,因为每次递归都会产生额外的函数调用,增加了系统的开销。
因此,我们可以通过非递归的方式来解决汉诺塔问题,提高算法的效率。
以下是一个用C语言实现的汉诺塔问题的非递归算法:```c#include <stdio.h>#include <stdlib.h>typedef struct {int n;char start, end, temp;} StackNode;typedef struct {StackNode data[100];int top;} Stack;void push(Stack *s, StackNode node) {s->data[s->top++] = node;}StackNode pop(Stack *s) {return s->data[--s->top];}void hanoi(int n, char start, char end, char temp) {Stack s;s.top = 0;StackNode node;node.n = n;node.start = start;node.end = end;node.temp = temp;push(&s, node);while (s.top > 0) {node = pop(&s);if (node.n == 1) {printf("Move disk 1 from %c to %c\n", node.start, node.end); } else {StackNode node1, node2, node3;node1.n = node.n - 1;node1.start = node.temp;node1.end = node.end;node1.temp = node.start;push(&s, node1);node2.n = 1;node2.start = node.start;node2.end = node.end;node2.temp = node.temp;push(&s, node2);node3.n = node.n - 1;node3.start = node.start;node3.end = node.end;node3.temp = node.temp;push(&s, node3);}}}int main() {int n;printf("Enter the number of disks: "); scanf("%d", &n);hanoi(n, 'A', 'C', 'B');return 0;}```在这个非递归算法中,我们使用了一个栈来模拟递归的过程。
数据结构C语言

数据结构(C语言)数据组织(数据、数据元素、数据项)的三个层次:数据可由若干个数据元素构成,而数据元素又可以由一个或若干个数据项组成。
四种基本的数据结构:集合、线性结构、树形结构、图状结构。
顺序存储的特点是在内存中开辟一组连续的空间来存放数据,数据元素之间的逻辑关系通过元素在内存中存放的相对位置来确定。
链式存储的特点是通过指针反映数据元素之间的逻辑关系。
数据类型:原子类型、结构类型。
线性表定义:线性表是n个数据元素的有限序列。
线性表的顺序存储结构:表中相邻的元素a和b所对应的存储地址A和B 也是相邻的。
(也就是数据都是按照表中情况进行连续存储的情况)线性表的链式存储结构:该线性表中的数据元素可以用任意的存储单元来存储。
表中的各个相邻的数据(元素)是通过一个指针地址来进行链接的,以找到下一个数据(元素)在哪。
其形式一般为:数据地址线性表的顺序和链式存储结构的比较:在线性表的长度变化比较大,预先难以确定的情况下,最好采用动态链表作为存储结构。
当线性表的长度变化不大时,采用顺序存储结构比较节省存储空间。
在顺序表结构的线性表上主要进行查找、读取而很少做插入和删除的操作。
链式结构的线性表中比较适应做插入和删除的操作。
一元多项式的加减法运算可先将一元多项式进行了改变存储之后再进行运算比较适宜,将一元多项式转换为用在内存中的前一项表示阶数,后一项表示对应该阶数的系数。
然后利用这种形式进行加减运算。
栈和队列栈是限定在表的同一端进行插入或删除操作的线性表,即进栈、出栈。
(特殊的线性表)栈的顺序存储结构:利用一组地址连续的存储单元依次从栈底到栈顶存放数据元素,栈底位置固定不变,可将栈底设在向量低下标的一端。
栈的链式存储结构:用单链表作为存储结构的栈称为链栈,链表的最后一个结点表示栈底,第一个结点表示栈顶。
队列也是一种特殊的线性表。
它所有的插入操作均限定在表的一端进行,而所有的删除操作则限定在表的另一端进行。
允许删除元素的一端称为队头,允许插入元素的一端称为队尾,删除元素称为出队,插入元素称为进队。
汉诺塔汇编作业

摘要:本课程设计的主要内容是Hanoi 塔游戏的移动步骤。
程序的主要功能就是在有三个塔座的情况下,用户输入要移动的圆盘数后,计算机计算出所用步骤,并把一步的移动分别输出。
而且能够显示总共需要移动的的次数。
Hanoi塔的移动规则是:⑴每次只能移动一个圆盘;⑵圆盘可以插在A,B和C中任意塔上;⑶任何时刻都不能将个较大的圆盘压在较小的圆盘之上。
Hanoi塔的游戏大家都玩过。
在圆盘数很小时很容易实现,但是当圆盘数不断增加时,移动起来也不再容易。
所以,用计算机来计算当圆盘数变大时的移动次数显得简单而明了。
关键字:Hanoi 塔塔座圆盘目录一、设计目的 (2)1.1 Hanoi 塔传说 (2)1.2Hanoi 塔的问题描述 (2)1.3要求: (3)二、正文 (3)2.1功能设计模块图 (3)2.2算法设计 (4)2.2.1算法的思想描述 (4)2.2.2算法的流程图 (6)2.3编译截图 (8)2.4连接截图 (8)2.5运行结果截图 (9)2.6相关界面的截图 (9)三、课程设计体会 (10)四、参考文献 (10)五、附录(源程序及其注释) (11)一、设计目的1.1 Hanoi 塔传说汉诺塔(又称河内塔)问题是印度的一个古老的传说。
开天辟地的神勃拉玛在一个庙里留下了三根金刚石的棒,第一根上面套着64个圆的金片,最大的一个在底下,其余一个比一个小,依次叠上去,庙里的众僧不倦地把它们一个个地从这根棒搬到另一根棒上,规定可利用中间的一根棒作为帮助,但每次只能搬一个,而且大的不能放在小的上面。
僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,而梵塔、庙宇和众生也都将同归于尽。
假设有n片,移动次数是f(n).显然f(1)=1,f(2)=3,f(3)=7,且f(k+1)=2*f(k)+1。
此后不难证明f(n)=2^n-1。
n=64时,f(64)= 2^64-1=18446744073709551615假如每秒钟一次,共需多长时间呢?一个平年365天有 31536000 秒,闰年366天有31622400秒,平均每年31556952秒,计算一下,18446744073709551615/31556952=584554049253.855年这表明移完这些金片需要5845亿年以上,而地球存在至今不过45亿年,太阳系的预期寿命据说也就是数百亿年。
c语言必做100题

c语言必做100题1. 编写一个C程序,输出“Hello, World!”。
2. 编写一个C程序,计算并输出1到100的和。
3. 编写一个C程序,判断一个数是否为素数。
4. 编写一个C程序,将一个字符串反转。
5. 编写一个C程序,实现二分查找算法。
6. 编写一个C程序,实现插入排序算法。
7. 编写一个C程序,实现选择排序算法。
8. 编写一个C程序,实现冒泡排序算法。
9. 编写一个C程序,实现快速排序算法。
10. 编写一个C程序,实现希尔排序算法。
11. 编写一个C程序,将一个二维数组转置。
12. 编写一个C程序,计算一个数的阶乘。
13. 编写一个C程序,实现斐波那契数列。
14. 编写一个C程序,计算两个数的最大公约数。
15. 编写一个C程序,计算两个数的最小公倍数。
16. 编写一个C程序,计算一个数的平方根。
17. 编写一个C程序,计算一个数的立方根。
18. 编写一个C程序,实现矩阵乘法运算。
19. 编写一个C程序,实现字符串的查找和替换。
20. 编写一个C程序,实现栈的基本操作(入栈、出栈、查看栈顶元素)。
21. 编写一个C程序,实现队列的基本操作(入队、出队、查看队首元素)。
22. 编写一个C程序,实现链表的基本操作(插入、删除、倒置)。
23. 编写一个C程序,实现二叉树的前序、中序和后序遍历。
24. 编写一个C程序,实现图的深度优先搜索算法。
25. 编写一个C程序,实现图的广度优先搜索算法。
26. 编写一个C程序,实现最短路径算法(Dijkstra算法或Floyd算法)。
27. 编写一个C程序,实现最小生成树算法(Prim算法或Kruskal算法)。
28. 编写一个C程序,实现拓扑排序算法。
29. 编写一个C程序,实现优先队列。
30. 编写一个C程序,实现哈希表的基本操作(插入、查找、删除)。
31. 编写一个C程序,实现堆的基本操作(插入、删除、查找最大值)。
32. 编写一个C程序,实现最大堆排序算法。
C|用递归和非递归方法求解汉诺塔问题

C|用递归和非递归方法求解汉诺塔问题汉诺塔(Tower of Hanoi,又称河内塔)问题是源于印度一个古老传说的益智玩具。
大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。
大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。
并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
当盘子的个数为n时,移动的次数应等于2^n – 1。
后来一位美国学者发现一种出人意料的简单方法,只要轮流进行两步操作就可以了。
首先把三根柱子按顺序排成品字型,把所有的圆盘按从大到小的顺序放在柱子A上,根据圆盘的数量确定柱子的排放顺序:若n为偶数,按顺时针方向依次摆放 A、B、C;若n为奇数,按顺时针方向依次摆放 A、C、B。
① 按顺时针方向把圆盘1从现在的柱子移动到下一根柱子,即当n为偶数时,若圆盘1在柱子A,则把它移动到B;若圆盘1在柱子B,则把它移动到C;若圆盘1在柱子C,则把它移动到A。
② 接着,把另外两根柱子上可以移动的圆盘移动到新的柱子上。
即把非空柱子上的圆盘移动到空柱子上,当两根柱子都非空时,移动较小的圆盘。
这一步没有明确规定移动哪个圆盘,你可能以为会有多种可能性,其实不然,可实施的行动是唯一的。
③ 反复进行①②操作,最后就能按规定完成汉诺塔的移动。
所以结果非常简单,就是按照移动规则向一个方向移动金片:如3阶汉诺塔的移动:A→C,A→B,C→B,A→C,B→A,B→C,A→C// 用递归求解汉诺塔问题int step=1; // 整型全局变量,预置1,步数void move(int, char, char, char);// 声明要用到的被调用函数void main(){int n;// 整型变量,n为盘数,printf("请输入盘数 n=");// 提示信息scanf("%d",&n);// 输入正整数nprintf("在3根柱子上移%d只盘的步骤为: ",n);move(n,'a','b','c');// 调用函数move(n,'a','b','c')system("pause");}void move(int m, char p, char q, char r){// 自定义函数体开始if (m==1)// 如果m为1,则为直接可解结点,{// 直接可解结点,输出移盘信息printf("[%d] move 1# from %c to %c ",step,p,r);step++;// 步数加1}else// 如果不为1,则要调用move(m-1){move(m-1,p,r,q);// 递归调用move(m-1)//直接可解结点,输出移盘信息printf("[%d] move %d# from %c to %c ", step, m, p, r);step++;// 步数加1move(m-1,q,p,r);// 递归调用move(m-1)}}//自定义函数体结束运行结果:请输入盘数 n=4在3根柱子上移4只盘的步骤为:[1] move 1# from a to b[2] move 2# from a to c[3] move 1# from b to c[4] move 3# from a to b[5] move 1# from c to a[6] move 2# from c to b[7] move 1# from a to b[8] move 4# from a to c[9] move 1# from b to c[10] move 2# from b to a[11] move 1# from c to a[12] move 3# from b to c[13] move 1# from a to b[14] move 2# from a to c[15] move 1# from b to c非递归方法:#include <iostream>using namespace std;//圆盘的个数最多为64const int MAX = 64;//用来表示每根柱子的信息struct st{int s[MAX]; //柱子上的圆盘存储情况int top; //栈顶,用来最上面的圆盘char name; //柱子的名字,可以是A,B,C中的一个int Top()//取栈顶元素{return s[top];}int Pop()//出栈{return s[top--];}void Push(int x)//入栈{s[++top] = x;}} ;long Pow(int x, int y); //计算x^yvoid Creat(st ta[], int n); //给结构数组设置初值void Hannuota(st ta[], long max); //移动汉诺塔的主要函数int main(void){int n;cout << "输入圆盘的个数:" << endl;cin >> n; //输入圆盘的个数st ta[3]; //三根柱子的信息用结构数组存储Creat(ta, n); //给结构数组设置初值long max = Pow(2, n) - 1;//动的次数应等于2^n - 1Hannuota(ta, max);//移动汉诺塔的主要函数system("pause");return 0;}void Creat(st ta[], int n){ta[0].name = 'A';ta[0].top = n-1;//把所有的圆盘按从大到小的顺序放在柱子A上for (int i=0; i<n; i++)ta[0].s[i] = n - i;//柱子B,C上开始没有没有圆盘ta[1].top = ta[2].top = 0;for (i=0; i<n; i++)ta[1].s[i] = ta[2].s[i] = 0;//若n为偶数,按顺时针方向依次摆放 AB Cif (n%2 == 0){ta[1].name = 'B';ta[2].name = 'C';}else //若n为奇数,按顺时针方向依次摆放 A C B{ta[1].name = 'C';ta[2].name = 'B';}}long Pow(int x, int y){long sum = 1;for (int i=0; i<y; i++)sum *= x;return sum;}void Hannuota(st ta[], long max){int k = 0; //累计移动的次数int i = 0;int ch;while (k < max){//按顺时针方向把圆盘1从现在的柱子移动到下一根柱子ch = ta[i%3].Pop();ta[(i+1)%3].Push(ch);cout << ++k << ": " <<"Move disk " << ch << " from " << ta[i%3].name <<" to " << ta[(i+1)%3].name << endl;i++;//把另外两根柱子上可以移动的圆盘移动到新的柱子上if (k < max){ //把非空柱子上的圆盘移动到空柱子上,当两根柱子都为空时,移动较小的圆盘if (ta[(i+1)%3].T op() == 0 ||ta[(i-1)%3].Top() > 0 &&ta[(i+1)%3].T op() > ta[(i-1)%3].Top()){ch = ta[(i-1)%3].Pop();ta[(i+1)%3].Push(ch);cout << ++k << ": " << "Move disk "<< ch << " from " << ta[(i-1)%3].name<< " to " << ta[(i+1)%3].name << endl;}else{ch = ta[(i+1)%3].Pop();ta[(i-1)%3].Push(ch);cout << ++k << ": " << "Move disk "<< ch << " from " << ta[(i+1)%3].name<< " to " << ta[(i-1)%3].name << endl;}}}}运行结果:输入圆盘的个数:5步骤:1: Move disk 1 from A to C 2: Move disk 2 from A to B 3: Move disk 1 from C to B 4: Move disk 3 from A to C 5: Move disk 1 from B to A 6: Move disk 2 from B to C 7: Move disk 1 from A to C 8: Move disk 4 from A to B 9: Move disk 1 from C to B 10: Move disk 2 from C to A 11: Move disk 1 from B to A 12: Move disk 3 from C to B 13: Move disk 1 from A to C 14: Move disk 2 from A to B 15: Move disk 1 from C to B 16: Move disk 5 from A to C 17: Move disk 1 from B to A 18: Move disk 2 from B to C 19: Move disk 1 from A to C 20: Move disk 3 from B to A 21: Move disk 1 from C to B 22: Move disk 2 from C to A23: Move disk 1 from B to A24: Move disk 4 from B to C25: Move disk 1 from A to C26: Move disk 2 from A to B27: Move disk 1 from C to B28: Move disk 3 from A to C29: Move disk 1 from B to A30: Move disk 2 from B to C31: Move disk 1 from A to C -End-。
C语言递归调用实例——汉诺塔问题动画实现(附完整代码)

二、程序框架
古人云,不谋全局者,不足谋一域。同样,在编写代码之前,我们必 须得有个大体的思路和整体上的把握。不能一上来就稀里糊涂地乱敲一通。 当然,这里我也只能仅仅谈自己的个人想法,不一定就是最优的解决方案, 还希望能和大家一起相互交流,共同进步。整个程序的框架,我把它分为 动画效果和核心算法两大部分。我首先实现的是动画效果部分,等能够实 现盘子的随意移动后,我才开始研究核心算法的实现。这样一来,在核心 算法部分,我们正好可以利用前面的动画效果来直观地反映出我们的思路, 有助于代码的调试和缩短程序的开发周期。为了尽量减少废话,我们可以 用一张图来进行表示:
图 1-1 移动第一个圆盘..................................................................................................................... 4 图 1-2 移动第二个圆盘...................................................................................................................... 5 图 1-3 移动最后一个圆盘................................................................................................................. 6
能移动一个圆盘,且圆盘在放到棒上时,大的不能放在小的上面。中间的一根
棒作为辅助移动用。” 事实上,对此曾经有人作过分析,按这个规则,众僧耗尽毕生精力也
不可能完成圆盘的移动,因为需要移动圆盘的次数是一个天文数字 18446744073709551615(64 个圆盘需要移动的次数为 2 的 64 次方)。假设 1us 进行一次移动,也需要约一百万年的时间,使用计算机也很难解决 64
hanoi塔递归算法c语言

hanoi塔递归算法c语言Hanoi塔是一种经典的数字益智游戏,它来源于法国数学家Lucas的BrainVita游戏,被称为“汉诺威塔问题”或“汉诺塔问题”。
该游戏由三个柱子和几个圆盘组成,最初时,圆盘按半径从大到小依次放在一个柱子上(逆序排列),游戏的目标则是将这些圆盘移动到另一个柱子上,最终使得其按半径从小到大依次排列。
在移动整个圆盘的过程中,必须遵循以下规定:1. 每次只能移动一个圆盘;2. 圆盘可以放置在任何柱子上;3. 不能将一个大的圆盘放在较小的圆盘之上。
为了解决这一难题,Hanoi塔问题引入了递归算法,这也是大多数编程语言中最常使用的算法之一。
在C语言中,Hanoi塔问题可以用以下代码实现:```c#include<stdio.h>void move(int n, char x, char y, char z){if(n == 1){printf("%c-->%c\n", x, z);}else{move(n-1, x, z, y);printf("%c-->%c\n", x, z);move(n-1, y, x, z);}}int main(){int n;printf("请输入盘子数:");scanf("%d", &n);printf("移动的步骤如下:\n");move(n, 'A', 'B', 'C');return 0;}```在这个程序中,我们首先定义了一个函数`move()`,该函数接受四个参数:圆盘的数量`n`和字母标识符`x`、`y`、`z`,它们分别代表三个柱子。
在函数中,我们使用了条件判断语句,如果只有一个圆盘,我们直接将其从柱子`x`移动至柱子`z`上。
否则,我们需要进行3个步骤:1. 将n-1个圆盘从柱子`x`移动至柱子`y`上;2. 将第n个圆盘从柱子`x`移动至柱子`z`上;3. 将n-1个圆盘从柱子`y`移动至柱子`z`上。
汉诺塔问题——精选推荐

汉诺塔问题汉诺塔问题是⼀个经典的问题。
汉诺塔(Hanoi Tower),⼜称河内塔,源于印度⼀个古⽼传说。
⼤梵天创造世界的时候做了三根⾦刚⽯柱⼦,在⼀根柱⼦上从下往上按照⼤⼩顺序摞着64⽚黄⾦圆盘。
⼤梵天命令婆罗门把圆盘从下⾯开始按⼤⼩顺序重新摆放在另⼀根柱⼦上。
并且规定,任何时候,在⼩圆盘上都不能放⼤圆盘,且在三根柱⼦之间⼀次只能移动⼀个圆盘。
问应该如何操作?分析如果是初次接触类似的问题,乍看之下肯定会感觉⽆从下⼿。
要把64个圆盘从a柱⼦移动到c柱⼦上,第⼀步应该怎么做?虽然可以肯定,第⼀步唯⼀的选择是移动a最上⾯的那个圆盘,但是应该将其移到b还是c呢?很难确定。
因为接下来的第⼆步、第三步……直到最后⼀步,看起来都是很难确定的。
能⽴即确定的是最后⼀步:最后⼀步的盘⼦肯定也是a最上⾯那个圆盘,并且是由a或b移动到c——此前已经将63个圆盘移动到了c上。
也许你会说,管他呢,先随便试着移动⼀下好了。
如果你这么做,你会发现,接下来你会⾯临越来越多类似的选择,对每⼀个选择都“试”⼀下的话,你会偏离正确的道路越来越远,直到你发现你接下来⽆法进⾏为⽌。
如果将这个问题的盘⼦数量减为10个或更少,就不会有太⼤的问题了。
但盘⼦数量为64的话,你⼀共需要移动约1800亿亿步(18,446,744,073,709,551,615),才能最终完成整个过程。
这是⼀个天⽂数字,没有⼈能够在有⽣之年通过⼿动的⽅式来完成它。
即使借助于计算机,假设计算机每秒能够移动100万步,那么约需要18万亿秒,即58万年。
将计算机的速度再提⾼1000倍,即每秒10亿步,也需要584年才能够完成。
注:在我的笔记本电脑上,每秒⼤约能够移动6~8百万步。
虽然64个盘⼦超出了⼈⼒和现代计算机的能⼒,但⾄少对于计算机来说,这不是⼀个⽆法完成的任务,因为与我们⼈类不同,计算机的能⼒在不断提⾼。
分解问题⼀股脑地考虑每⼀步如何移动很困难,我们可以换个思路。
数据结构(C语言版)第3章 栈和队列

typedef struct StackNode {
SElemType data;
S
栈顶
struct StackNode *next;
} StackNode, *LinkStack;
LinkStack S;
∧
栈底
链栈的初始化
S
∧
void InitStack(LinkStack &S ) { S=NULL; }
top
C
B
base A
--S.top; e=*S.top;
取顺序栈栈顶元素
(1) 判断是否空栈,若空则返回错误 (2) 否则通过栈顶指针获取栈顶元素
top C B base A
Status GetTop( SqStack S, SElemType &e) { if( S.top == S.base ) return ERROR; // 栈空 e = *( S.top – 1 ); return OK; e = *( S.top -- ); ??? }
目 录 导 航
Contents
3.1 3.2 3.3 3.4 3.5
栈和队列的定义和特点 案例引入 栈的表示和操作的实现 栈与递归 队列的的表示和操作的实现
3.6
案例分析与实现
3.2 案例引入
案例3.1 :一元多项式的运算
案例3.2:号匹配的检验
案例3.3 :表达式求值
案例3.4 :舞伴问题
目 录 导 航
top B base A
清空顺序栈
Status ClearStack( SqStack S ) { if( S.base ) S.top = S.base; return OK; }
汉诺塔程序设计报告

VC++作业电信学院电子0801班张海滨20809050汉诺塔程序设计报告一、题目汉诺塔(Towers of Hanoi)问题二、设计要求1、在窗口中画出初始时塔和碟子的状态。
2、可以以自动或手动两种方式搬移碟子。
3、自动搬移可以通过定时器或多线程的方法,每一次移动的时间间隔可以自定,以人眼观察比较舒服为宜,每一次的移动过程如能实现动画最好。
4、定义塔的描述类和碟子的描述类。
5、在程序中,碟子的数目及每次移动的时间间隔可以通过对话框设置(也应该有默认值)。
6、支持暂停功和继续的功能(在自动搬移过程中可以暂停,并继续)。
7、暂停后,可以将当前的状态保存(碟子和塔的组合关系)。
8、可以从7中保存的文件中读出某个状态,并继续移动。
三、问题分析1、已知有三个塔(1、2、3)和n个从大到小的金碟子,初始状态时n个碟子按从大到小的次序从塔1的底部堆放至顶部。
2、要求把碟子都移动到塔2(按从大到小的次序从塔2的底部堆放至顶部)。
3、每次移动一个碟子。
4、任何时候、任何一个塔上都不能把大碟子放到小碟子的上面。
5、可以借助塔3。
(图1-1)图1-1首先考虑a杆下面的盘子而非杆上最上面的盘子,于是任务变成了:1、将上面的63个盘子移到b杆上;2、将a杆上剩下的盘子移到c杆上;3、将b杆上的全部盘子移到c杆上。
将这个过程继续下去,就是要先完成移动63个盘子、62个盘子、61个盘子....1个盘的工作。
四、算法选择汉诺塔程序设计算法的实质就是递归递归思想的运用。
现将其算法简述如下:为了更清楚地描述算法,可以定义一个函数hanoi(n,a,b,c)。
该函数的功能是:将n个盘子从塔a上借助塔b移动到塔c上。
这样移动n 个盘子的工作就可以按照以下过程进行:1) hanoi(n-1,a,c,b);//将n-1个金盘由a借助c移到b2) 将最下面的金盘从a移动到c上;3) hanoi(n-1,b,a,c);//将b上的n-1个盘借助a移到c重复以上过程,直到将全部的盘子移动到塔c上时为止。
汉诺塔c语言程序代码

汉诺塔c语言程序代码(通过vc++6.0验证)(附讲解)让我们先看看代码吧#include <stdio.h>int hj(int a,int b, int c,int i){int t;if(i==1)printf("%d->%d\n",a,c);else{t=c;c=b;b=t;hj(a,b,c,i-1);printf("%d->%d\n",a,b);t=a;a=c;c=t;t=b;b=c;c=t;hj(a,b,c,i-1);return 0;}}main(){int a,b,c,i;a=1;b=2;c=3;printf("请输入汉诺塔的盘数");scanf("%d",&i);hj(a,b,c,i);return 0;}以上是汉诺塔的代码,该程序主要是运用了递归的思想,比如数学中的f(x)=f(x-1)+f(x-2),在本程序中为:int hj(int a,int b, int c,int i){int t;if(i==1)printf("%d->%d\n",a,c);else{t=c;c=b;b=t;hj(a,b,c,i-1);也就是说,我们在这个函数中再次调用这个函数,相当于一个循环,而在再次调用的过程中,i的值变成i-1,就类似于f(x-1),这样层层调用,最终就变成当i=1的时候的值,然后通过运算,计算出想要得到的值。
汉诺塔的数值分析:我们可以发现,当只有一个盘的时候,我们只需要做1->3(就是把第一个柱子上的最顶端的盘移动到第三根柱子,以下不再解释)当有两个盘的时候,是1->2 1->3 2->3三个盘子是:1->3 1->2 3->2 1->3 2->1 2->3 1->3分析一下可以得出以下结论:初始值a=1 b=2 c=3一个盘子就是a->c两个盘子与一个盘子的关系是:第一步:b与c交换值,然后打印a->c第二步:打印a->b第三步:a与c交换值,b与c交换值,打印a->c进一步分析,便可以得出以下结论只要盘子数量为i(i大于1),那么它就有三部分第一部分,b与c交换值,然后运行i-1第二部分,打印a->b第三部分,a与c交换值,b与c交换值,然后运行i-1程序表示便是:if(i==1)printf("%d->%d\n",a,c);else{t=c;c=b;(交换值)b=t;hj(a,b,c,i-1);printf("%d->%d\n",a,b);t=a;a=c;c=t;(a c交换)t=b;b=c;c=t;(b c交换)hj(a,b,c,i-1);。
c语言顺序栈实现表达式求值

c语言顺序栈实现表达式求值下面是C语言顺序栈实现表达式求值的代码示例:```c#include <stdio.h>#include <stdlib.h>#define MAX_EXPR_LEN 100typedef struct {double* data; // 存储数据的数组指针int top; // 栈顶指针int maxSize; // 栈的最大容量} Stack;// 初始化栈void init(Stack* stack, int maxSize) {stack->data = (double*)malloc(maxSize * sizeof(double));stack->top = -1;stack->maxSize = maxSize;}// 判断栈是否为空int isEmpty(Stack* stack) {return stack->top == -1;}// 判断栈是否已满int isFull(Stack* stack) {return stack->top == stack->maxSize - 1;}// 入栈void push(Stack* stack, double value) {if (isFull(stack)) {printf("Stack is full.\n");return;}stack->data[++stack->top] = value;}// 出栈double pop(Stack* stack) {if (isEmpty(stack)) {printf("Stack is empty.\n");return -1;}return stack->data[stack->top--];}// 获取栈顶元素double top(Stack* stack) {if (isEmpty(stack)) {printf("Stack is empty.\n");return -1;}return stack->data[stack->top];}// 运算符优先级比较int priority(char op) {switch(op) {case '+':case '-':return 1;case '*':case '/':return 2;case '(':case ')':return 0;default:return -1;}}// 执行操作double operate(double operand1, double operand2, char op) { switch(op) {case '+':return operand1 + operand2;case '-':return operand1 - operand2;case '*':return operand1 * operand2;case '/':return operand1 / operand2;default:return 0;}}// 表达式求值double evaluateExpression(char* expression) {Stack operandStack; // 操作数栈Stack operatorStack; // 运算符栈init(&operandStack, MAX_EXPR_LEN);init(&operatorStack, MAX_EXPR_LEN);int i = 0;while (expression[i] != '\0') {if (expression[i] >= '0' && expression[i] <= '9') {// 处理数字double num = 0;while (expression[i] >= '0' && expression[i] <= '9') {num = num * 10 + (expression[i] - '0');i++;}push(&operandStack, num);} else if (expression[i] == '+' || expression[i] == '-' || expression[i] == '*' || expression[i] == '/') {// 处理运算符while (!isEmpty(&operatorStack) && priority(expression[i]) <= priority(top(&operatorStack))) {char op = pop(&operatorStack);double operand2 = pop(&operandStack);double operand1 = pop(&operandStack);double result = operate(operand1, operand2, op);push(&operandStack, result);}push(&operatorStack, expression[i]);i++;} else if (expression[i] == '(') {// 处理左括号push(&operatorStack, expression[i]);i++;} else if (expression[i] == ')') {// 处理右括号while (top(&operatorStack) != '(') {char op = pop(&operatorStack);double operand2 = pop(&operandStack);double operand1 = pop(&operandStack);double result = operate(operand1, operand2, op);push(&operandStack, result);}// 弹出左括号pop(&operatorStack);i++;} else {i++;}}// 处理剩余的运算符while (!isEmpty(&operatorStack)) {char op = pop(&operatorStack);double operand2 = pop(&operandStack);double operand1 = pop(&operandStack);double result = operate(operand1, operand2, op);push(&operandStack, result);}double result = pop(&operandStack);return result;}int main() {char expression[MAX_EXPR_LEN];printf("请输入表达式:");fgets(expression, sizeof(expression), stdin);double result = evaluateExpression(expression);printf("表达式的结果为:%lf\n", result);return 0;}```使用该代码,可以实现对不带括号的四则运算表达式进行求值。
汉诺塔问题的程序实现(hanoi塔)

汉诺塔问题的程序实现(hanoi塔)问题重述:有三根柱A、B、C,在柱A上有N块盘⽚,所有盘⽚都是⼤的在下⾯,⼩⽚能放在⼤⽚上⾯。
现要将A上的N块盘⽚移到C柱上,每次只能移动⼀⽚,⽽且在同⼀根柱⼦上必须保持上⾯的盘⽚⽐下⾯的盘⽚⼩,输⼊任意的N,输出移动⽅法。
(注意:这是⼀个古⽼的传说,传说是如果把64个盘⼦由A柱移到了C柱的话,那么世界末⽇就到了,事实上如果要把64个盘⼦从A柱移到C柱的话,即使⽤计算机运算,也要计算数亿年,所以这个预⾔未必不是真实。
)【分析】我们可以这样考虑,当n=1时,我们只要直接将A柱的盘⼦移到C柱,当n>1时,我们可以先把n-1个盘⼦由A柱通过C柱移到B 柱,此时就可以把A柱剩下的最后⼀个盘⼦直接移到C柱,这样接下来只要把n-1个盘⼦通过A柱移到C 柱即可,如果就构成了递归的思路,我们可以定义个移动过程mov(n,a,b,c)表⽰将n个盘⼦从a通过b移到c1.只要求输出搬运的次数#includeusing namespace std;int m=0;void move(){m++;}void I(int n){if(n==1)move();else{I(n-1);move();I(n-1);}}int main(){I(3);cout<cout<<"输出完毕!"<return 0;}更加简单的⽅法!#includeusing namespace std;int fact(int n){if(n==1)return(1);elsereturn((2*fact(n-1)+1));}int main(){cout<}2.不仅要求输出搬运的次数,⽽且要输出每个步骤的详细搬运#includeusing namespace std;int m=0;void Move(int n,char x,char y){cout<<"把"<m++;}void Hannoi(int n,char a,char b,char c){if(n==1)Move(1,a,c);else{Hannoi(n-1,a,c,b);Move(n,a,c);Hannoi(n-1,b,a,c);}}int main(){int i;cout<<"请输⼊圆盘数"<cin>>i;Hannoi(3,'a','b','c');cout<<"总的搬运次数"<cout<<"输出完毕!"<return 0;}}另外⼀种不利⽤递归的解法(很抱歉,我⾃⼰也没调出来,实在太复杂了)#includeusing namespace std;//圆盘的个数最多为64const int MAX = 1;//⽤来表⽰每根柱⼦的信息struct st{int s[MAX]; //柱⼦上的圆盘存储情况int top; //栈顶,⽤来最上⾯的圆盘char name; //柱⼦的名字,可以是A,B,C 中的⼀个int Top()//取栈顶元素{return s[top];}int Pop()//出栈{return s[top--];}void Push(int x)//⼊栈{s[++top] = x;}} ;long Pow(int x, int y); //计算x^yvoid Creat(st ta[], int n); //给结构数组设置初值void Hannuota(st ta[], long max); //移动汉诺塔的主要函数int main(void){int n;cin >> n; //输⼊圆盘的个数st ta[3]; //三根柱⼦的信息⽤结构数组存储Creat(ta, n); //给结构数组设置初值long max = Pow(2, n) - 1;//动的次数应等于2^n - 1 Hannuota(ta, max);//移动汉诺塔的主要函数system("pause");return 0;}void Creat(st ta[], int n){ta[0].name = 'A';ta[0].top = n-1;//把所有的圆盘按从⼤到⼩的顺序放在柱⼦A 上for (int i=0; ita[0].s[i] = n - i;//柱⼦B,C 上开始没有没有圆盘ta[1].top = ta[2].top = 0;for (int j=0; jta[1].s[j] = ta[2].s[j] = 0;//若n 为偶数,按顺时针⽅向依次摆放A B Cif (n%2 == 0){ta[1].name = 'B';ta[2].name = 'C';}else //若n 为奇数,按顺时针⽅向依次摆放A C B {ta[1].name = 'C';ta[2].name = 'B';}}long Pow(int x, int y){long sum = 1;for (int i=0; isum *= x;return sum;}void Hannuota(st ta[], long max){int k = 0; //累计移动的次数int i = 0;int ch;while (k < max){//按顺时针⽅向把圆盘1 从现在的柱⼦移动到下⼀根柱⼦ch = ta[i%3].Pop();ta[(i+1)%3].Push(ch);cout << ++k << ": " <<"Move disk " << ch << " from " << ta[i%3].name <<" to " << ta[(i+1)%3].name << endl;i++;//把另外两根柱⼦上可以移动的圆盘移动到新的柱⼦上if (k < max){ //把⾮空柱⼦上的圆盘移动到空柱⼦上,当两根柱⼦都为空时,移动较⼩的圆if (ta[(i+1)%3].Top() == 0 ||ta[(i-1)%3].Top() > 0 &&ta[(i+1)%3].Top() > ta[(i-1)%3].Top()){ch = ta[(i-1)%3].Pop();ta[(i+1)%3].Push(ch);cout << ++k << ": " << "Move disk "<< ch << " from " << ta[(i-1)%3].name<< " to " << ta[(i+1)%3].name << endl;}else{ch = ta[(i+1)%3].Pop();ta[(i-1)%3].Push(ch);cout << ++k << ": " << "Move disk " << ch << " from " << ta[(i+1)%3].name << " to " << ta[(i-1)%3].name << endl; }}}}补充知识:【典型例题1】求阶乘n!#includeusing namespace std;int fact(int n){if(n==0)return(1);elsereturn(n*fact(n-1)); }int main(){cout<。
汉诺塔问题非递归算法c语言

汉诺塔问题非递归算法c语言以下是一个非递归解决汉诺塔问题的C语言算法:```c#include <stdio.h>// 定义栈的数据结构typedef struct {int n; // 当前圆盘数char src, dst, aux; // 源柱子、目标柱子和辅助柱子 int step; // 当前操作数} Stack;void hanoi(int n) {Stack s[32]; // 栈,存储每一步的操作int top = 0; // 栈顶指针int i; // 循环变量char tmp; // 用于交换柱子s[top].n = n;s[top].src = 'A';s[top].dst = 'C';s[top].aux = 'B';s[top].step = 0;while (top >= 0) {// 出栈n = s[top].n;char src = s[top].src;char dst = s[top].dst;char aux = s[top].aux;int step = s[top].step;top--;if (n == 1) {printf("第%d步:将第1个盘从 %c 柱移到 %c 柱\n", step+1, src, dst);} else if (step == 0) {// 第一步:将上面 n-1 个盘从源柱借助辅助柱移到辅助柱s[++top].n = n - 1;s[top].src = src;s[top].dst = aux;s[top].aux = dst;s[top].step = 0;} else if (step == 1) {// 第二步:将第 n 个盘从源柱移到目标柱printf("第%d步:将第%d个盘从 %c 柱移到 %c 柱\n", step+1, n, src, dst);} else if (step == 2) {// 第三步:将上面 n-1 个盘从辅助柱借助目标柱移到目标柱s[++top].n = n - 1;s[top].src = aux;s[top].dst = dst;s[top].aux = src;s[top].step = 0;} else {// 交换辅助柱和目标柱tmp = aux;aux = dst;dst = tmp;// 第一步:将上面 n-1 个盘从源柱借助辅助柱移到辅助柱s[++top].n = n - 1;s[top].src = src;s[top].dst = aux;s[top].aux = dst;s[top].step = 0;}// 当前步骤加1s[top].step++;}}int main() {int n;printf("请输入汉诺塔的盘数:");scanf("%d", &n);hanoi(n);return 0;}```使用栈来模拟递归过程,将递归过程中的参数和局部变量保存到栈中,依次出栈执行,直到栈为空。
汉诺塔函数

汉诺塔函数
汉诺塔函数,又称为河内塔函数,是一种经典的递归算法。
该算法的目的是将一堆盘子从一个柱子移动到另一个柱子,同时遵循以下规则:
1. 每次只能移动一个盘子;
2. 每次移动必须将盘子从较小的柱子移动到较大的柱子上;
3. 每个盘子只能放在比它大的盘子上面。
汉诺塔函数的实现过程是将问题分解成更小的问题,通过递归的方式解决。
具体实现方法如下:
1. 如果只有一个盘子,直接将它移动到目标柱子上;
2. 如果有多个盘子,将它们看作两部分:最底下的一个盘子和上面的所有盘子。
先将上面的所有盘子移动到辅助柱子上,再将最底下的盘子移动到目标柱子上,最后将辅助柱子上的盘子移动到目标柱子上。
通过反复执行上述操作,即可将所有盘子从起始柱子移动到目标柱子上。
汉诺塔函数是一种经典的递归算法,具有较高的实用价值。
在程序设计中,我们可以通过该函数解决一些具有相似结构的问题,如排序、搜索等。
- 1 -。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
计算机科学与工程学院
《算法与数据结构》试验报告[二]
专业班级10级计算机工程02 试验地点计算机大楼计工教研室学生学号1005080222 指导教师蔡琼
学生姓名肖宇博试验时间2012-4-14
试验项目算法与数据结构
试验类别基础性()设计性()综合性(√)其它()
试验目的及要求(1)掌握栈的特点及其存储方法;(2)掌握栈的常见算法以及程序实现;(3)了解递归的工作过程。
成
绩评定表
类别评分标准分值得分合计
上机表现积极出勤、遵守纪律
主动完成设计任务
30分
程序与报告程序代码规范、功能正确
报告详实完整、体现收获
70分
备注:
评阅教师:
日期:年月日
试 验 内 容
一、实验目的和要求
1、实验目的:
(1)掌握栈的特点及其存储方法;
(2)掌握栈的常见算法以及程序实现; (3)了解递归的工作过程。
2、实验内容
Hanoi 塔问题。
(要求4个盘子移动,输出中间结果)
3、实验要求:
要求实现4个盘子的移动,用递归和栈实现。
二、设计分析
三个盘子Hanoi 求解示意图如下:
三个盘子汉诺塔算法的运行轨迹:
B A
B C A B C
A C A
B C
(a
(b)
(c (d)
⑸
⑼ ⑶
Hanio(3,A,B,C) Hanio(3,A,B,C) Hanio(2,A,C,B)
Hanio(2,A,C,B) Hanio(1,A,B,C) Hanio(1,A,B,C) Move (A,C) Move (A,B) Hanio(1,C,A,B)
Hanio(1,C,A,B) Move (C,B)
Move (A,B)
Hanio(2,B,A,C)
Hanio(2,B,A,C) Hanio(1,B,C,A)
Hanio(1,B,C,A) Move (B,C) Hanio(1,A,B,C)
Hanio(1,A,B,C) Move (A,C)
Move (B,A)
递归第一层 递归第二层 递归第三层 ⑴ ⑵
⑷
⑹
⑺ ⑻
⑽ ⑾
⑿
⒀
⒁
三、源代码
#include<stdio.h>
#include<stdlib.h>
#define maxsize 20
typedef int datatype; //数据结构的类型
typedef struct
{
int top;
datatype data[maxsize];
char flat;
}sqstack; //栈的定义
void inisqstack(sqstack *&s,char ch) //初始化函数!{
s=(sqstack *)malloc(sizeof(sqstack));
s->top=-1;
s->flat=ch;
}
void push(sqstack *&s,datatype e) //进栈函数
{
s->top++;
s->data[s->top]=e;
}
void pop(sqstack *&s,datatype &e) //出栈函数
{
e=s->data[s->top];
s->top--;
}
void Dispstack(sqstack *s) //显示函数
{
for(int i=s->top;i>=0;i--)
{
printf("%d\t",s->data[i]);
}
printf("\n");
}
void Hanio(int n,sqstack *A,sqstack *B,sqstack *C) //汉诺塔主程序
{
int e1;
if(n==1)
{
printf("把%c的%d号盘移到
到%c\n",A->flat,A->data[A->top],C->flat);
pop(A,e1);
push(C,e1);
printf("-----%c还剩下-------------",A->flat);
if(A->top==-1)
{
printf("0");
printf("\n");
}
else
Dispstack(A);
printf("-----%c还剩下-------------",B->flat);
if(B->top==-1)
{
printf("0");
printf("\n");
}
else
Dispstack(B);
printf("-----%c还剩下-------------",C->flat);
if(C->top==-1)
{
printf("0");
printf("\n");
}
else
Dispstack(C);
}
else
{
Hanio(n-1,A,C,B);
pop(A,e1);
push(C,e1);
printf("把%c的%d号盘移到
到%c\n",A->flat,e1,C->flat);
Hanio(n-1,B,A,C);
}
}
void main()
{
sqstack *A,*B,*C;
int m;
inisqstack(A,'A');
inisqstack(B,'B');
inisqstack(C,'C');
printf("输入几个盘子");
scanf("%d",&m);
for(int i=m;i>0;i--)
{
push(A,i);
}
Hanio(m,A,B,C);
}
四、测试用例(尽量覆盖所有分支)
1.正常状态下,输入1无错误后的运行程序如下:
2.正常状态下,输入2无错误后的运行程序如下:
3.正常状态下,输入3无错误后的运行程序如下:
4.正常状态下,输入4无错误后的运行程序如下:
五、实验总结
本次进行的是汉诺塔递归实现问题,由于是要用到递归和栈那么难度加大了很多。
递归的过程中关于程序执行到那里的问题是困扰我的大问题,并且递归完成后程序到了那里也是一个大问题!
原来的版本我写了一个很麻烦的程序,它可以将移走的盘的名字都打印出来,并且可以随时看到每个柱子中剩下的盘子,但是这个程序在递归中除了很奇怪的问题,我花了很大的劲都没有改出来,所以才不得不写了这样的一个简单版本。
该程序贯彻了我一贯的风格,将用户会出现的错误都考虑在内。
并且提供了每次输出的结果!
然而程序并不是最完美的。
在今后的实验当中我将会更加的关注递归算法!。