汉诺塔的详细分析步骤及可视化程序

 三个柱子:  A, B, C
 盘子数:    n
 
 1. 通过整体思想,把n-1看为一个整体,目的显而易见
 	把  n-1    	 从   A   移到    B
 	把  最大的  	 从   A   移到    C
	把  n-1      从   B   移到    C
 
 2. 其中比较费解的就是:
        n-1如何从A移到B的
        n-1又是如何从B移到C的。
 
 3. 解释n-1如何从A移动B
 把  n-2     从   A   移到   C
 把  最大的   从   A   移到   B
 把  n-2     从   C   移到   B
 
 4. 解释n-1如何从B移动C
 把  n-2     从   C   移到  A
 把  最大的   从   C   移到  B
 把  n-2     从   A   移到  B
 
 1的步骤可以看作是 从A移到C
 3的步骤可以看作是 从B移到A
 4的步骤可以看作是 从C移到B
 
 根据这些我们可以建立通用的函数:
 move(int nNumb, string strFrom, string strTo);
 参数:    nNumb       移动个数
         strFrom     从哪移动
         strTo       移到哪去
 
 
 问题就可以概括为:
                                         { move(n-2, "A", "C")
                   { move(n-1, "A", "B") { move(1,   "A", "B")
                   {                     { move(n-2, "C", "B")
 move(n, "A", "C") { move(1,   "A", "C")                            ...
                   {                     { move(n-2, "B", "A")
                   { move(n-1, "B", "C") { move(1,   "B", "C")
                                         { move(n-2, "A", "C")
 
 
 由上又可以看出部分结构的组成,通过这部分结构,可以看出这就是一个递归体:
 
                     { move(n-1, Begin, Other)
 move(n, Begin, End) { move(1,   Begin, End  )
                     { move(n-1, Other, End  )
 
 那么递归的终止条件在哪呢?我们按照这个步骤推演到最后,结构类似如下:
 
                     { move(1, Begin, Other)
 move(2, Begin, End) { move(1, Begin, End  )
                     { move(1, Other, End  )
 
 显而易见的,move(1, ..., ...);没有再执行下去的必要。 所以这也就成为了递归的终止条件。

代码如下:

#include 
#include 
#include 
#include 

using std::max_element;
using std::cout;
using std::endl;
using std::vector;
using std::string;

static int nStep = 0;

struct HanNuoTa
{
	string strName;			// 塔名
	vector<int> vecData;	// 塔内数据
};

HanNuoTa GetTaByName(const string & strName, const HanNuoTa& A, const HanNuoTa& B, const HanNuoTa& C)
{
	if (strName.compare(A.strName) == 0)
	{
		return A;
	}
	else if (strName.compare(B.strName) == 0)
	{
		return B;
	}
	else if (strName.compare(C.strName) == 0)
	{
		return C;
	}
}

void PrintData(const HanNuoTa& A, const HanNuoTa& B, const HanNuoTa& C)
{
	int nNumb[] = { A.vecData.size(), B.vecData.size(), C.vecData.size() };
	int nMax = *max_element(nNumb, nNumb + 3);

	if (nStep == 0)
	{
		cout << "开始:" << endl;
	}
	else
	{
		cout << "第" << nStep << "步" << endl;
	}
	
	cout << "A" << "\tB" << "\tC" << endl;
	nStep++;

	HanNuoTa ATemp = GetTaByName("A", A, B, C);
	HanNuoTa BTemp = GetTaByName("B", A, B, C);
	HanNuoTa CTemp = GetTaByName("C", A, B, C);

	for (int i = 0; i < nMax; i++)
	{
		cout << (ATemp.vecData.size() > i ? ATemp.vecData.at(i) : 0) << "\t";
		cout << (BTemp.vecData.size() > i ? BTemp.vecData.at(i) : 0) << "\t";
		cout << (CTemp.vecData.size() > i ? CTemp.vecData.at(i) : 0) << endl;
	}

	cout << endl;
}

void Move(const int nNumb, HanNuoTa& stuFrom, HanNuoTa& stuTo)
{
	stuTo.vecData.insert(stuTo.vecData.begin(), stuFrom.vecData.begin(), stuFrom.vecData.begin() + nNumb);
	stuFrom.vecData.erase(stuFrom.vecData.begin(), stuFrom.vecData.begin() + nNumb);
}

//**************************************************
//	@参数:nNumb	移动数量
//		   A		开始移动的塔
//		   B		途径的塔
//		   C		结束的塔
//**************************************************
void HanNuo(const int nNumb, HanNuoTa& A, HanNuoTa& B, HanNuoTa& C)
{
	if (nNumb == 1)
	{
		Move(nNumb, A, C);
		PrintData(A, B, C);
	}
	else
	{
		HanNuo(nNumb - 1, A, C, B);
		HanNuo(1, A, B, C);
		HanNuo(nNumb - 1, B, A, C);
	}
}

int main(int argc, const char* argv[])
{
	HanNuoTa A, B, C;
	A.strName = "A";
	A.vecData = { 1, 2, 3 };

	B.strName = "B";
	C.strName = "C";

	PrintData(A, B, C);
	HanNuo(A.vecData.size(), A, B, C);
}

测试结果:
汉诺塔的详细分析步骤及可视化程序_第1张图片

你可能感兴趣的:(递归)