Problem
In the classic problem of the Towers of Hanoi, you have 3 towers and N disks of different sizes which can slide onto any tower. The puzzle starts with disks sorted inascendingorder
of size from top to bottom (i.e., each disk sits on top of an even larger one). You have the following constraints:
(1) Only one disk can be moved at a time.
(2) A disk is slid off the top of one tower onto another tower.
(3) A disk cannot be placed on top of a smaller disk.
Write a program to move the disks from the frst tower to the last using Stacks.
Solution
这个问题非常适合“Base Case and Build“方法。
我们从最小的可能情况开始:n=1。
Case n=1。如何把Disk1从Tower1移动到Tower3?
1.只需要简单地将Disk1从Tower1移到Tower3就可以了。
Case n=2。如何把Disk1和Disk2从Tower1移动到Tower3?
1.将Disk1从Tower1移动到Tower2
2.将Disk2从Tower1移动到Tower3
3.将Disk1从Tower2移动到Tower3
注意在上面的步骤中,Tower2实际上是作为一个缓冲的,也就是说当我们将其他Disk移到Tower3时来保存一个Disk。
Case n=3。如何把Disk1、Disk2和Disk3从Tower1移动到Tower3?
1.我们知道我们可以将上面的两个disk从一个tower移动到另一个tower(如上文所述),所以,假设我们已经做到了。但是,这里我们将上面两个disk移动到Tower2。
2.将Disk3移动到Tower3。
3.移动Disk1和Disk2到Tower。从上文我们已经知道我们可以做到这些。
Case n=4。如何把Disk1、Disk2、Disk3和Disk4从Tower1移动到Tower3?
1.移动Disk1,Disk2和Disk3到Tower2。
2.移动Disk4到Tower3。
3.移动Disk1,Disk2和Disk3到Tower3。
注意,tower的标签并不重要,它们实际是等价的。所以,利用Tower2作为缓冲将disks移到Tower3和利用Tower3作为缓冲将disks移动到Tower2是一样的。
面向过程的:
void Hanoi(int N,char src,char aux,char dest)
{
if(N == 1)
{
cout<
return;
}
Hanoi(N-1, src,dest,aux );
cout<
Hanoi(N-1, aux, src, dest);
}
int main(int argc, const char * argv[])
{
Hanoi(3, 'A', 'B','C');
return 0;
}
面向对象的:
class Tower
{
public:
Tower(int i)
:index_(i)
{
}
int index()
{
return index_;
}
void add(int d)
{
if(!disks.empty() && disks.top() <= d)
{
cout<
}
else
{
disks.push(d);
}
}
void moveTopTo(Tower& t)
{
int topDisk = disks.top();
disks.pop();
t.add(topDisk);
}
void moveDisks(int n,Tower& destnitation,Tower& buffer)
{
if (n > 0)
{
moveDisks(n-1,buffer,destnitation);
moveTopTo(destnitation);
buffer.moveDisks(n-1,destnitation,*this);
}
}
private:
stack disks;
int index_;
};
int main()
{
int n = 3;
Tower *towers[3];
for (int i = 0;i< 3;++i)
{
towers[i] = new Tower(i);
}
for(int i = n-1;i>=0;--i)
{
towers[0]->add(i);
}
towers[0]->moveDisks(n,*(towers[2]),*(towers[1]));
return 0;
}