基于广义表是递归定义的结构,因此实现广义表操作的算法均为递归函数。

  何谓"递归函数"?
  一个含直接或间接调用本函数语句的函数被称之为递归函数,它必须满足以下两个条件:1) 在每一次调用自己时,必须是(在某种意义上)更接近于解;2) 函数中必须有一个终止处理或计算的准则。例如,在右侧的梵塔函数中,每一次的递归调用,问题规模减少1,在 n=1 时达到"终结状态",即可直接求解,不再需要继续递归。

  又如,二叉树的遍历,每一次的递归调用,问题规模缩小为二叉树的左子树或右子树,在子树为空时达到"终结状态"。

  这两个递归算法都有一个共同特点,即问题求解的方法都是将一个复杂问题分割成若干子问题求解,反之,求得子问题的解之后,原问题也就迎刃而解了。

  "分割求解(又称分治法)"是进行算法设计的一种方法,其严格定义为:
  对于一个输入规模为 n 的函数或问题,用某种方法把输入分割成 k(1<k≤n) 个子集,从而产生 个子问题,分别求解这 个问题,得出 个问题的子解,再用某种方法把它们组合成原来问题的解。若子问题还相当大,则可以反复使用分治法,直至最后所分得的子问题足够小,以至可以直接求解为止。

  在利用分治法求解时,若所得子问题的性质和原问题相同,则可递归求解。

例题 例如:求解焚塔问题 Hanoi(n,x,y,z) 时可将 n 个圆盘分成两组:自上而下的 n-1 个盘和最底下的 n 号盘,从而产生三个子问题:
   1) 将上面的 n-1 个盘从 x 轴移到 y 轴;
   2) 将下面的 n 号盘从 x 轴移到 z 轴;
   3) 将上面的 n-1 个盘从y轴移到 z 轴;
  依此顺序求解这三个子问题即得到原问题的解。

  显然,第1和第3个子问题和原问题的性质相同,只是问题规模比原问题小,则可用和求解原问题相同的方法求解,而第2个问题可以直接求解。对应于原问题求解的函数 Hanoi(n,x,y,z),第1和第3个子问题求解的函数分别为
    Hanoi(n-1,x,z,y) 和 Hanoi(n-1,y,x,z)
  显然,n=1 时可以直接求解,由此得到右侧的递归函数。

例题 又如,在对二叉树进行遍历时,可将二叉树中结点分成根结点、左子树和右子树三部分,从而引出三个子问题:
   1) 访问根结点;
   2) 先序遍历左子树;
   3) 先序遍历右子树。
  按任意次序完成这三个子问题,即求得原问题的解。

  显然,第1个问题是简单问题,可以直接求解,而第2和第3个问题的性质和原问题相同,则可递归求解,且递归的终结状态是二叉树为空树。
 
算法
 void hanoi(int n,char x,char y,char z)
{
 // 将 x 轴上自上而下编号依次为1至 n 的
 // n 个盘移到 z 轴上,y 轴为中间过渡用轴

 if (n==1) move(x, 1, z);
 else {
  hanoi(n-1,x,z,y);
 // 将 x 轴上自上而下编号依次为1至 n-1的 n-1个
 // 盘移到 y 轴上,z 轴为中间过渡用轴
  move(x,n,z);
 // 将编号为 n 的盘从 x 轴直接移到 z 轴上
  hanoi(n-1,y,x,z);
 // 将 y 轴上自上而下编号依次为1至n-1的n-1个
 // 盘移到 z 轴上,x 轴为中间过渡用轴
 }
} // hanoi
void PreOrderTraverse( BiTree T,
          void
(*visit)(BiTree))
{
 // 先序遍历T为指向根结点的指针的二叉树,
 // visit 为结点的访问函数

 if (T)
 { visit(T);
  PreOrderTraverse( T->lchild,visit);
 // 先序遍历 T->lchild 所指二叉树
  PreOrderTraverse( T->rchild,visit);
 // 先序遍历 T->rchild 所指二叉树
 }
} // PreOrderTraverse