C语言初学者必知!河内塔问题算法、逻辑及代码实现
汉诺塔这个问题,看上去仅仅是将一伙那堆积如山的碟子由一根那儿的柱子挪动到另一根所处的柱子,然而它的挪动次数会跟随着盘子给出的数量呈现出爆炸式的增长态势。当那盘子的数量达到64个那样的地步,依照每秒钟移动一回这样的速度来进行计算,需要大概5850亿年这么漫长的时间才能够完成,而这个时间跨度甚至已经超过了宇宙自身所拥有的年龄。
递归思想是核心
汉诺塔的解法不在意具体每一步究竟如何去挪动,而是把握住一个关键规律,那就是,若要把n个盘子从A柱移至C柱,就得先将上面n - 1个盘子从A柱移到B柱,接着把最底下那个大盘子直接从A柱移到C柱,最后再把B柱上的n - 1个盘子从B柱移到C柱。在这个历程当中,移动n - 1个盘子时又再度重复同样的逻辑。
程序在进行实现之际,仅仅只需对一个hanoi函数付诸定义之举,该函数会接纳四个参数,分别为盘子的数量,还有起始柱,以及辅助柱,另外还有目标柱。当盘子的数量等同于1的时候,便径直输出移动的步骤。其余情况下,也就是盘子数量不等于1的时候,便会依照上面所讲述的三个步骤,递归地调用自身。这样的一种写法,将复杂的问题分解成为具有相同结构的子问题,其代码显得极为简洁。
移动次数指数增长
关于汉诺塔的移动次数,存在着一个精准的公式,即:2的n次方减1。当n等于1的时候,移动的次数为1次。而当n等于2的时候,移动的次数是3次。当n等于3的时候,移动的次数为7次。随着n的不断增加,移动的次数会迅速地翻倍。当n等于64的时候,移动的次数大约是1.84乘以10的19次方,这个数字大到超乎想象。
按照每秒移动一回的速率来计算,达成64个盘子的汉诺塔所需时间约为5850亿年,当前科学界认定宇宙年龄约莫138亿年,其中5850亿年等同于宇宙年龄的42倍,此例子常常被用以向学生阐释指数级增长的可怖之处,还展现了递归算法于处理这般问题之际的优势。
费氏数列的自然规律
计算机算法教学里,费氏数列所处地位和汉诺塔相同,都极重要,此数列起始于1、1,后来每一项均是前两项相加所得,即1、1、2、3、5、8、13、21、34、55、89……其递推关系虽简易,然而应用范围却极为广泛。
自然界里,费氏数列常常出现,比如说向日葵种子的排列,菠萝表面鳞片的数量,蜜蜂的家族树,甚至是某些花瓣的数量,都契合这个规律。计算费氏数列之际,可以用递归函数直接达成,然而更具效率的做法是运用循环迭代,从第三项起逐个递推计算,如此就不会产生重复计算,执行效率要高许多。
组合数与打印模式
从多个元素当中选取几个元素的方案所用的组合数C(n, k),得以体现从n个元素里选k个的情况,计算之际能够运用公式C(n, k) = n! / (k! (n-k)!)来进行求解。 只是在运用程序形式予以实现时,为实现避开大数阶乘所产生的计算方面的花销,通常会借助递推公式C(n, k) = C(n, k-1) (n-k+1) / k来逐一项展开计算。
有一种递推的方式,在打印杨辉三角的时候,它显得格外有用,杨辉三角每一行所对应的数字,实际上就是组合数,当把空格数量控制妥当之后,能够借助循环逐个逐行地打印出来,凭借观察循环变量的变化情形以及组合数的计算流程,可以非常直观地去理解递推关系在实际编程里面的应用。
三色旗排序问题
来源于荷兰国旗问题的三色旗问题,要求将蓝、白、红三种颜色的旗子以蓝、白、红的顺序排列在一起,其约束条件为,仅能交换相邻的旗子,并且只能在一个数组内部进行操作,同时不能使用额外的空间,这个问题所考察的是怎样在有限的条件之下达成分类排序。
解决的思路是,设置三个指针,分别是B、W、R,B指向蓝色区域末尾,W指向当前正处理的旗子,R指向红色区域开头,初始的时候,B在开头,R在末尾,在遍历过程里,如果W指向白色,那么W直接向后移动,如果指向蓝色,互换B和W位置后两个指针都向后移动,如果指向红色,互换W和R位置后R向前移动,当W超过R时,所有旗子分类完成。
指针移动控制流程
于三色旗算法里头,三个指针之所以移动的规则,是将排序的效率做出了决定,B指针一直在指着蓝色区域的,最后一个位置往后边去,W指针把整个数组都遍历了,R指针一直在前头,指向红色区域的第一个位置,每次处于处理情况之际,都凭W指定着的颜色,来决定其中的操作,并不需要另外的比较,也无需回溯。
这一算法的时间复杂度为O(n),仅仅只需对数组展开一回遍历。其空间复杂度为O(1),只是于原数组之上开展交换动作。在领会指针挪移逻辑之后,能够将其扩展至更多颜色分类的情形,是用于学习数组操作以及指针运用的经典实例。
进行编程学习期间,汉诺塔这种算法,费氏数列那般的算法,三色旗排序这类算法,你对其中哪一个在理解的时候是最为费劲的呢?欢迎于评论区去分享你的学习经历呀。
