汉诺塔递归实现 C#版本

汉诺塔的计算实现是算法课程中递归部分的经典案例。算法不难,但是要实现,还是要动点脑筋的。大致描述如下:
就是要把n个盘移动到目标柱,首先得把n-1个盘移动到临时柱。
然后把把剩下的最大的盘移动到目标柱。
然后把临时柱作为起始柱,原先的起始柱作为临时柱,重复上述步骤。
如果只移动起始柱的一个盘,就直接放到目标柱即可。
————————————————————————————
大致描述就是如此,大多算法书的输出无非是几个箭头移来移去,不直观。因此此处采用C#重新写了一遍,看注释即可明白。
其中Move_1和Move是一样的,仅仅是采用Last()方法还是用临时tmp的区别,个人认为用last更好理解点。本质都一样。

tolist.Add(fromlist.Last()); fromlist.Remove(fromlist.Last()); PrintStatus();
tolist.Add(tmp); fromlist.Remove(tmp); PrintStatus();

附代码:

 
 
 
 

using
System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Dynamic; namespace ConsoleApplication1 { class Program { //static List<int> l = new List<int>() { 1, 2, 3 }; static List<int> A = new List<int>() {10,9,8,7,6,5, 4, 3, 2, 1 }; static List<int> B = new List<int>() { }; static List<int> C = new List<int>() { }; static int count = 0; static void Main(string[] args) { PrintStatus(); Move_1(A.Count, ref A, ref B, ref C); Console.WriteLine("移动次数:" + count); } //Move,表示把n个盘子从fromlist,经过tmplist作为临时柱,移动到目标柱tolist static public void Move_1(int n, ref List<int> fromlist, ref List<int> tmplist, ref List<int> tolist) { if (n == 1) { tolist.Add(fromlist.Last()); fromlist.Remove(fromlist.Last()); PrintStatus(); } else { //由于下面要把fromlist中的n-1个盘子移动走,tmp则为移动走以后,剩下的那个盘子中最小的那个盘子。 int tmp = fromlist[fromlist.Count - n]; //先把fromlist上的n-1个盘子,经过tolist作为临时柱,移动到tmplist。 Move_1(n - 1, ref fromlist, ref tolist, ref tmplist); //把fromlist上剩下的那个盘子,移动到目标盘tolist tolist.Add(tmp); fromlist.Remove(tmp); PrintStatus(); //把临时柱作为起始柱(此时临时柱上只剩下n-1个盘片),原先的起始柱作为临时柱,重复上述的移动,移动到目标盘tolist Move_1(n - 1, ref tmplist, ref fromlist, ref tolist); } } //Move,表示把n个盘子从fromlist,经过tmplist作为临时柱,移动到目标柱tolist static public void Move(int n, ref List<int> fromlist, ref List<int> tmplist, ref List<int> tolist) { if (n == 1) { count++; tolist.Add(fromlist.Last()); fromlist.Remove(fromlist.Last()); PrintStatus(); } else { //Console.WriteLine("//先把fromlist上的" + (n - 1).ToString() + "个盘子,经过tolist作为临时柱,移动到tmplist。"); //先把fromlist上的n-1个盘子,经过tolist作为临时柱,移动到tmplist。 Move(n - 1, ref fromlist, ref tolist, ref tmplist); //Console.WriteLine("//把fromlist上剩下最小的那个盘子,移动到目标盘tolist"); //把fromlist上剩下最小的那个盘子,移动到目标盘tolist tolist.Add(fromlist.Last()); fromlist.Remove(fromlist.Last()); PrintStatus(); count++; //Console.WriteLine("//把临时柱作为起始柱(此时临时柱上只剩下" + (n - 1).ToString() + "个盘片),原先的起始柱作为临时柱,重复上述的移动,移动到目标盘tolist"); //把临时柱作为起始柱(此时临时柱上只剩下n-1个盘片),原先的起始柱作为临时柱,重复上述的移动,移动到目标盘tolist Move(n - 1, ref tmplist, ref fromlist, ref tolist); } } static public void PrintStatus() { Console.Write("A:"); A.ForEach((m) => Console.Write(m)); Console.WriteLine(); Console.Write("B:"); B.ForEach((m) => Console.Write(m)); Console.WriteLine(); Console.Write("C:"); C.ForEach((m) => Console.Write(m)); Console.WriteLine(); Console.WriteLine("-------------------"); } } }


 

 

-----------------5个盘的实现过程-----------

A:54321
B:
C:
-------------------
A:5432
B:
C:1
-------------------
A:543
B:2
C:1
-------------------
A:543
B:21
C:
-------------------
A:54
B:21
C:3
-------------------
A:541
B:2
C:3
-------------------
A:541
B:
C:32
-------------------
A:54
B:
C:321
-------------------
A:5
B:4
C:321
-------------------
A:5
B:41
C:32
-------------------
A:52
B:41
C:3
-------------------
A:521
B:4
C:3
-------------------
A:521
B:43
C:
-------------------
A:52
B:43
C:1
-------------------
A:5
B:432
C:1
-------------------
A:5
B:4321
C:
-------------------
A:
B:4321
C:5
-------------------
A:1
B:432
C:5
-------------------
A:1
B:43
C:52
-------------------
A:
B:43
C:521
-------------------
A:3
B:4
C:521
-------------------
A:3
B:41
C:52
-------------------
A:32
B:41
C:5
-------------------
A:321
B:4
C:5
-------------------
A:321
B:
C:54
-------------------
A:32
B:
C:541
-------------------
A:3
B:2
C:541
-------------------
A:3
B:21
C:54
-------------------
A:
B:21
C:543
-------------------
A:1
B:2
C:543
-------------------
A:1
B:
C:5432
-------------------
A:
B:
C:54321
-------------------
移动次数:31

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值