算法设计思维之递归与八皇后问题

本文介绍了递归思维在解决八皇后问题中的应用。递归是一种逆向的计算机思维,通过递归可以有效地解决一些难题,如八皇后问题。文章详细讲解了递归执行的过程,包括栈的工作原理,以及尾递归的概念和优化。最后,文章给出了八皇后问题的具体解法和实现策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

递归简介

计算机思维和人的思维最大的不同就是递归。我们日常思考问题方式是正向的递推(iterative),计算机是逆向的递归思维。要想真正理解的计算机解决问题的精髓,递归是必须要学的。

递推是人本能的正向思维,比如数数,从1、2、3一直数到100,这就是典型的递推。如果用递推的方法来计算一个数的阶乘,比如5! = 1×2×3×4×5,一个很自然的做法就是从小到大一个个乘起来。

但是,对于一些难题,递推方法并不好用,比如经典的八皇后问题。

八皇后问题

如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上

八皇后问题的其中一种解法

按照我们通常的递推思维,可以在第一行摆好一个棋子,它当然不会和任何棋子冲突,然后第二行摆一个,保证它和第一个棋子没有冲突,然后再摆第三行的,以此类推。

需要指出的是,没有计算机之前找到所有可能的摆放是非常困难的。如果你能在5分钟内找到一个答案,就算非常快了。**大数学家高斯穷其一生只找到76种方案,而八皇后独立解共有92种。**当然,有了计算机,很快就能找到它的全部92种结果。

要更好的求解这个问题,就要用递归的思维。计算机计算阶乘,比如说计算5!,计算机就会把它变成 5×4!,4!不知道,没事,同样转化成4×3!,以此类推。最后到了1!(递归基),计算机知道它等于自身,就不接着往下扩展。接下来,计算机倒推回去所有结果,1!知道了,2!,然后3!,4!,5!。

递归的过程,从上向下层层展开,再从下到上一步步回溯。这和栈这种数据结构是一致的,即先进后出,后进先出,但栈清空的时候,计算就完成了。不过,这带来了新的问题。

递归执行的过程

要理解递归带来的问题,就要理解递归的工作过程,有必要先来看看C语言中函数执行的方式。基于这点,我们需要了解一点关于C程序在内存中的组织方式。基本上来说一个可执行程序由四个区域组成:代码段(.text)、静态数据区(.data)、堆(heap)和栈(stack)。

程序在内存中的组织结构

bss(block started by symbol)由符号开始的块。

  • 代码段包含程序运行时所执行的机器指令。
  • 静态数据区包含在程序生命周期内一直持久的数据,比如全局变量和静态局部变量。
  • 堆包含程序运行时动态分配的存储空间,比如malloc分配的内存。
  • 栈包含函调用的信息。

注意:按照惯例,堆的增长方向从程序低地址到高地址向上增长,而栈的增长方向刚好相反。(实际情况可能不是这样,和CPU的体系结构有关)。另外,这里的堆和数据结构的堆没有太大的关系。

当C程序中调用了一个函数时,栈中会分配一块空间来保存与这个调用相关的信息。每一个调用都被当作是活跃的。栈上的那块存储空间称为活跃记录,或者称为栈帧。栈帧由5个区域组成:输入参数、返回值空间、计算表达式用到的临时存储空间、函数调用时保存的状态信息以及输出参数。

输入参数是传递到活跃记录中的参数;输出参数是传递给在活跃记录中调用的函数。一个活跃记录中的输出参数就成为栈中下一个活跃记录的输入参数(到了1!=1,1就作为输出参数输出到调用1!的2!)。函数调用产生的活跃记录将一直存在于栈中直到这个函数调用结束。

// 阶乘的递归实现
int fact(int n) {
   
  if (n < 0) return 0;
  else if (n == 0) return 1;
  else if (n == 1) return 1;
  else
    return n * fact(n 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值