码迷,mamicode.com
首页 > 其他好文 > 详细

用栈模拟汉诺塔问题

时间:2018-07-23 22:41:26      阅读:169      评论:0      收藏:0      [点我收藏+]

标签:class   code   条件   unset   辅助   入栈   val   noi   cti   

在经典的汉诺塔问题中,有 3 个塔和 N 个可用来堆砌成塔的不同大小的盘子。要求盘子必须按照从小到大的顺序从上往下堆 (如,任意一个盘子,其必须堆在比它大的盘子上面)。同时,你必须满足以下限制条件:

(1) 每次只能移动一个盘子。
(2) 每个盘子从堆的顶部被移动后,只能置放于下一个堆中。
(3) 每个盘子只能放在比它大的盘子上面。

请写一段程序,实现将第一个堆的盘子移动到最后一个堆中。

 

分析:

技术分享图片

(1)n == 1

             第1次  1号盘  A---->C       sum = 1 次

       (2)  n == 2

             第1次  1号盘  A---->B

             第2次  2号盘  A---->C

             第3次  1号盘  B---->C        sum = 3 次

  (3)n == 3

        第1次  1号盘  A---->C

        第2次  2号盘  A---->B

        第3次  1号盘  C---->B

        第4次  3号盘  A---->C

        第5次  1号盘  B---->A

        第6次  2号盘  B---->C

        第7次  1号盘  A---->C        sum = 7 次

设栈A上最初的盘子总数为n,

当n=1时,只要将编号为1的盘子从栈A直接移到栈C上即可;否则执行以下三步:

(1)用栈C做过渡,将栈A上的n-1个盘子移到栈B上;

(2)将栈A上的最后一个盘子直接移到栈C上面;

(3)用栈A做过渡,将栈B上面的n-1个盘子移到栈C上面;

根据这种解法,如何将n-1个盘子从一个栈移到另一个栈的问题是一个和原问题具有相同特征属性的问题,只是问题的规模-1,因此可以用相同的方法求解。

  1 <?php
  2 header("Content-type: text/html; charset=utf-8");
  3 class Stack
  4 {
  5     private $id = null;//栈的标识,用于区分从哪个栈移到哪个栈
  6     private $top = -1;//栈顶
  7     private $max_size = 100;//栈的最大容量
  8     private $stack = array();
  9     
 10     public function __construct($id)
 11     {
 12         $this->id = $id;
 13     }
 14     
 15     public function get_id()
 16     {
 17         return $this->id;
 18     }
 19     
 20     /**
 21      * 入栈
 22      */
 23     public function push($val)
 24     {
 25         if($this->top == $this->max_size-1)
 26         {
 27             return false;//栈满
 28         }
 29         $this->top++;
 30         $this->stack[$this->top] = $val;
 31     }
 32     
 33     /**
 34      * 出栈
 35      */
 36     public function pop()
 37     {
 38         if($this->top == -1)
 39         {
 40             return false;//栈空
 41         }
 42         $val = $this->stack[$this->top];
 43         unset($this->stack[$this->top]);
 44         $this->top--;
 45         return $val;
 46     }
 47 }
 48 
 49 /**
 50  * 将栈A上的n个盘子移动到栈C上面,栈B用作辅助
 51  */
 52 function hanoi($n, $stack_a, $stack_b, $stack_c)
 53 {
 54     if($n == 1)//只有一个盘子时,直接移动到目标栈
 55     {
 56         move($stack_a, $stack_c);
 57     } else {
 58         hanoi($n-1, $stack_a, $stack_c, $stack_b);//将栈A上编号为1至n-1个盘子移到栈B上,栈C作为辅助
 59         move($stack_a, $stack_c);//将编号为n的盘子从栈A移到C
 60         hanoi($n-1, $stack_b, $stack_a, $stack_c);//将栈B上编号为1至n-1个盘子移到栈C上,栈A作为辅助
 61     }
 62 }
 63 
 64 /**
 65  * 移动
 66  */
 67 function move($stack_a, $stack_c)
 68 {
 69     static $count = 0;//盘子移动的次数
 70     $val = $stack_a->pop();
 71     $stack_c->push($val);
 72     $count++;
 73     echo $count . ": 从栈" . $stack_a->get_id() . "把" . $val . "移到栈" . $stack_c->get_id() . "<br/>"; 
 74 }
 75 
 76 /**
 77  * 递归解法($n: 表示有多少个盘子)
 78  * 1.先创建3个栈,并初始化栈A
 79  * 2.将栈A上的n个盘子移动到栈C上面,栈B用作辅助
 80  * 3.打印盘子的移动轨迹
 81  */
 82 function solution($n = 3)
 83 {
 84     $A = new Stack(‘A‘);
 85     $B = new Stack(‘B‘);
 86     $C = new Stack(‘C‘);
 87     for($i=$n;$i>0;$i--)
 88     {
 89         $A->push($i);
 90     }
 91     
 92     hanoi($n, $A, $B, $C);
 93     
 94     //打印盘子的移动轨迹
 95     echo "<pre>";
 96     print_r($A);
 97     print_r($B);
 98     print_r($C);
 99     die;
100 }
101 
102 solution(4);

 

用栈模拟汉诺塔问题

标签:class   code   条件   unset   辅助   入栈   val   noi   cti   

原文地址:https://www.cnblogs.com/573583868wuy/p/9357259.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!