-----------------------------------------------------------------------瞎逼逼部分----------------------------------------------------------------------
递归算法是一个很让人头大的事情,现在我还是没理解汉诺塔是怎么实现的,看到大神们的代码就短短几行,但是我脑中的想法却有很多。
决定的实现方法是采用形象的桟,使用三个桟,分别表示三根柱子,利用循环结构给第一个柱子从大到小放入盘子。
利用全局指针指向三个桟,在每一次挪动过后,利用函数输出桟里面的元素。
好吧这些无关最重要部分
----------------------------------------------------------------------------------------------------------------------------------------------------------
下面是关键代码
void han(int n, mystack<int> &a, mystack<int> &b, mystack<int> &c) //这边形参使用了一个n,表示要转移数量,还有三个我自己定义的桟类指针,传递了三个塔的地址。
{
int e; ///e用来辅助我的桟进出
if (n == 1) *重点*:实际上所有的操作都在这边if条件成立的时候进行。
{ 所以要理解这一点很重要,因为你每次移动的都是一个盘子,相当于你的每一次操作都是n=1。
a.pop(e); ///a栈顶元素出桟,并存储到e中。
c.push(e); 将e进桟到c中。
stout(); ///这句不要纠结,只是我的输出函数,这样我就可以在每一次操作后看到三个桟的情况。
}
else /else里面没有任何的直接移动,都是在调用自身这个函数。
{ //先解释一下下面可能用到的词,要这样认为,广义上,a桟是起点桟,b桟是空闲桟,c桟是目标桟。这边的abc桟和我们定义的abc桟不一定是对应的。
han(n - 1, a, c, b); ///将n-1个盘子移动到空闲桟上。
han(1, a, b, c); 将起点桟上剩余的一个盘移动到目标桟。
han(n - 1, b, a, c); /再将空闲桟上的盘移动到目标桟上。
}
}
所以就是这些了,以上就是实现汉诺塔的关键算法了。
---------------------------------------------------贴上完整代码,自己写的桟类。感兴趣的可以copy来调试一下,蹩脚注释请忽视---------------------------------------------
#include <iostream>
using namespace std;
//下面是我自己写的栈,还不会用标准库里面的,就自己写了一个
template <typename T>
class mystack
{
T *data;
int top;
public:
mystack();
~mystack();
bool isempty();
bool isfull();
bool push(T e);
bool getop(T &e);
bool pop(T &e);
void disp();
};
template <typename T>
mystack<T>::mystack()
{
data = new T[100];
top = -1;
}
template <typename T>
mystack<T>::~mystack()
{
delete[] data;
}
template <typename T>
bool mystack<T>::isempty()
{
return (top == -1);
}
template <typename T>
bool mystack<T>::isfull()
{
return (top == 99);
}
template <typename T>
bool mystack<T>::push(T e)
{
if (isfull())
return false;
else
{
top++;
data[top] = e;
return true;
}
}
template <typename T>
bool mystack<T>::getop(T &e)
{
if (isempty())
return false;
else
{
e = data[top];
return true;
}
}
template <typename T>
bool mystack<T>::pop(T &e)
{
if (isempty())
return false;
else
{
e = data[top];
top--;
return true;
}
}
template <typename T>
void mystack<T>::disp()
{
int i = -1;
while (i<top)
{
i++;
cout << "|" << data[i];
}
cout << "|" << endl;
}
///这是我的输出函数,可以输出三个塔里面的元素
mystack<int> *pa, *pb, *pc;
int ct = 1;
void stout()
{
cout << "Step " << ct << ":" << endl;
pa->disp();
pb->disp();
pc->disp();
ct++;
}
下面是关键函数
void han(int n, mystack<int> &a, mystack<int> &b, mystack<int> &c)
{
int e;
if (n == 1)
{
a.pop(e);
c.push(e);
stout();
}
else
{
han(n - 1, a, c, b);
han(1, a, b, c);
han(n - 1, b, a, c);
}
}
/下面是main函数
int main()
{
again:
ct = 1;
system("cls");
int n;
cout << "Please enter the number of the plate." << endl;
cin >> n;
system("cls");
mystack<int> a;
mystack<int> b;
mystack<int> c;
pa = &a;
pb = &b;
pc = &c;
for (int i = n; i>0; i--)
a.push(i);
a.disp();
han(n, a, b, c);
system("pause");
goto again;
return 0;
}
————————————————分割线————————————————————
有几个月了,现在暑假集训发现不止有经典汉诺塔,还有汉诺塔1到10;
感兴趣的小伙伴可以到杭电里面找一下,做了感觉有加深理解。