Hanoi tower运用递归算法。几年前没能了解其中的真正奥妙,
想通了其实很简单,呵呵
参见了《数据结构及算法分析 JAVA版》
思路:
1 设计disk和pole类,其中pole类类似于栈(先入后出)
2 利用递归算法得出移动disk的先后顺序以及移动路线,并将每一步操作信息保存至链表中
3 将链表中保存的结果打印出来
以下是汉诺塔中定义的类:
HanoiType.h
代码
#include <stdio.h>
// disk type
class disk
{
public:
int id;
disk *next; // upper one
disk *pre; // downer one
disk(int _id);
protected:
private:
};
disk::disk(int _id)
{
id = _id;
next = NULL;
pre = NULL;
}
// pole with ordered stack data structure
class pole
{
public:
void push(disk *_dsk);
disk* pop();
disk *head; // the disk on the tower top
pole(int _pol_id);
~pole();
int pole_id;
protected:
private:
};
void pole::push(disk *_dsk)
{
if (NULL == _dsk)
{
return;
}
if (NULL == head) // the pole is empty
{
head = _dsk;
}
else// the pole is not empty
{
_dsk->pre = head;
head->next = _dsk;
head = _dsk;
}
}
disk* pole::pop()
{
if (NULL == head) // the pole is empty
{
return NULL;
}
else // the pole is not empty
{
disk *tmp = head;
head = head->pre;
if (!head)
{
//head->next = NULL;
}
tmp->pre = NULL;
tmp->next = NULL;
return tmp;
}
}
pole::~pole()
{
disk *ptr = head;
disk *tmp;
while(!ptr)
{
tmp = ptr->pre;
delete ptr;
ptr = NULL;
ptr = tmp;
}
}
pole::pole(int _pole_id)
{
pole_id = _pole_id;
head = NULL;
}
class report_node
{
public:
int disk_id;
int src_pole_id;
int des_pole_id;
report_node *next;
report_node(int _d_id, int _src_p_id, int _des_p_id);
protected:
private:
};
report_node::report_node(int _d_id, int _src_p_id, int _des_p_id)
{
disk_id = _d_id;
src_pole_id = _src_p_id;
des_pole_id = _des_p_id;
next = NULL;
}
class report
{
public:
report_node *first, *ptr;
void insert(report_node *node);
report();
~report();
protected:
private:
};
report::report()
{
first = NULL;
ptr = NULL;
}
report::~report()
{
report_node *_ptr = first;
while(!_ptr)
{
delete _ptr;
_ptr = NULL;
}
}
void report::insert(report_node *node)
{
if (NULL == node)
{
return;
}
else if(NULL == first)
{
first = node;
ptr = node;
}
else
{
ptr->next = node;
ptr = ptr->next;
}
}
// disk type
class disk
{
public:
int id;
disk *next; // upper one
disk *pre; // downer one
disk(int _id);
protected:
private:
};
disk::disk(int _id)
{
id = _id;
next = NULL;
pre = NULL;
}
// pole with ordered stack data structure
class pole
{
public:
void push(disk *_dsk);
disk* pop();
disk *head; // the disk on the tower top
pole(int _pol_id);
~pole();
int pole_id;
protected:
private:
};
void pole::push(disk *_dsk)
{
if (NULL == _dsk)
{
return;
}
if (NULL == head) // the pole is empty
{
head = _dsk;
}
else// the pole is not empty
{
_dsk->pre = head;
head->next = _dsk;
head = _dsk;
}
}
disk* pole::pop()
{
if (NULL == head) // the pole is empty
{
return NULL;
}
else // the pole is not empty
{
disk *tmp = head;
head = head->pre;
if (!head)
{
//head->next = NULL;
}
tmp->pre = NULL;
tmp->next = NULL;
return tmp;
}
}
pole::~pole()
{
disk *ptr = head;
disk *tmp;
while(!ptr)
{
tmp = ptr->pre;
delete ptr;
ptr = NULL;
ptr = tmp;
}
}
pole::pole(int _pole_id)
{
pole_id = _pole_id;
head = NULL;
}
class report_node
{
public:
int disk_id;
int src_pole_id;
int des_pole_id;
report_node *next;
report_node(int _d_id, int _src_p_id, int _des_p_id);
protected:
private:
};
report_node::report_node(int _d_id, int _src_p_id, int _des_p_id)
{
disk_id = _d_id;
src_pole_id = _src_p_id;
des_pole_id = _des_p_id;
next = NULL;
}
class report
{
public:
report_node *first, *ptr;
void insert(report_node *node);
report();
~report();
protected:
private:
};
report::report()
{
first = NULL;
ptr = NULL;
}
report::~report()
{
report_node *_ptr = first;
while(!_ptr)
{
delete _ptr;
_ptr = NULL;
}
}
void report::insert(report_node *node)
{
if (NULL == node)
{
return;
}
else if(NULL == first)
{
first = node;
ptr = node;
}
else
{
ptr->next = node;
ptr = ptr->next;
}
}
以下是源文件
Movedisks.cpp
代码
#include "HanoiType.h"
#include <iostream>
using namespace std;
report *rept = new report(); // store the moving steps
/* move just one dist from src_pole to des_pol,
* pop a disk from src and push it into
* des;
*/
void move_1(pole *src_pole, pole *des_pole)
{
if (NULL == src_pole->head)
{
return;
}
else
{
// cout << "move disk --" << src_pole->head->id << "-- on --"
// << src_pole->pole_id << "-- to " << "pole " << des_pole->pole_id << endl;
report_node *step = new report_node(src_pole->head->id, src_pole->pole_id, des_pole->pole_id);
rept->insert(step);
disk *src_top = src_pole->pop();
des_pole->push(src_top);
}
}
void move_disks(int n, pole *src_pole, pole *emp_pole, pole *des_pole)
{
if (0 == n)
{
return;
}
else if (1 == n) // basic condition
{
move_1(src_pole, des_pole);
}
else
{
move_disks(n - 1, src_pole, des_pole, emp_pole);
move_1(src_pole, des_pole);
move_disks(n - 1, emp_pole, src_pole, des_pole);
}
}
void main()
{
int N = 3; // number of disks on src pole
pole *src_pole = new pole(0);
pole *emp_pole = new pole(1);
pole *des_pole = new pole(2);
// construct the s
for(int i = N; i != 0; i--)
{
disk *d = new disk(i);
src_pole->push(d);
}
// begin
move_disks(N, src_pole, emp_pole, des_pole);
report_node *_ptr = rept->first;
while(_ptr)
{
cout << "Move disk --" << _ptr->disk_id << " -- from pole "<<_ptr->src_pole_id << " to " << _ptr->des_pole_id << endl;
_ptr = _ptr->next;
}
}
#include <iostream>
using namespace std;
report *rept = new report(); // store the moving steps
/* move just one dist from src_pole to des_pol,
* pop a disk from src and push it into
* des;
*/
void move_1(pole *src_pole, pole *des_pole)
{
if (NULL == src_pole->head)
{
return;
}
else
{
// cout << "move disk --" << src_pole->head->id << "-- on --"
// << src_pole->pole_id << "-- to " << "pole " << des_pole->pole_id << endl;
report_node *step = new report_node(src_pole->head->id, src_pole->pole_id, des_pole->pole_id);
rept->insert(step);
disk *src_top = src_pole->pop();
des_pole->push(src_top);
}
}
void move_disks(int n, pole *src_pole, pole *emp_pole, pole *des_pole)
{
if (0 == n)
{
return;
}
else if (1 == n) // basic condition
{
move_1(src_pole, des_pole);
}
else
{
move_disks(n - 1, src_pole, des_pole, emp_pole);
move_1(src_pole, des_pole);
move_disks(n - 1, emp_pole, src_pole, des_pole);
}
}
void main()
{
int N = 3; // number of disks on src pole
pole *src_pole = new pole(0);
pole *emp_pole = new pole(1);
pole *des_pole = new pole(2);
// construct the s
for(int i = N; i != 0; i--)
{
disk *d = new disk(i);
src_pole->push(d);
}
// begin
move_disks(N, src_pole, emp_pole, des_pole);
report_node *_ptr = rept->first;
while(_ptr)
{
cout << "Move disk --" << _ptr->disk_id << " -- from pole "<<_ptr->src_pole_id << " to " << _ptr->des_pole_id << endl;
_ptr = _ptr->next;
}
}
在report单链表中保存的移动操作步骤可以用于图形化显示(待续。。。)