递归的思想在于他将一件n的事情变成n-1的事情,反复如此即可得到一件关于1的事情,所以递归的关键有两点:1.当这件事为1的时候我们的具体操作;2.什么样的事情做n次与做n-1次是一样的。看下面的例子:
1.阶乘算法。
当我们求一个数n的阶乘时,首先按上面分析,这件事为1的时候我们的具体操作是--->1!=1.什么样的事情做n次与做n-1次相同--->当n*(n-1)的阶乘时,做n次与做n-1次相同。
因此算法如下:
int fac(int n)
{
int count;
if(n==1);
count=1;
else
count=n*fac(n-1);
return count;
}
2.hanoi 塔算法
说是有X,Y,Z三座塔,我们需要将n个从小到大依次放置的圆盘从X移动至Z,且大的盘不能在小的上面。
分析:这件事为1的时候我们怎么做----->move(X,1,Z);(意思是将X上的1个移动到Z)
什么样的事情做n次与做n-1次是相同的---->j将n-1个从X移动到Y,将第n个从X移动到Z:move(X,n,Z),再将n-1个从Y上移动到Z上:hanoi(n-1,Y,X,Z)。这就等同于hanoi(n,X,Y,Z).(意思为将n个圆盘通过Y这个媒介从X移动到Z)
因此算法如下:
void hanoi(int n,char X,char Y,char Z)
{
if(n==1)
move(X,1,Z);
else
{
hanoi(n-1,X,Z,Y);
move(X,n,Z);
hanoi(n-1,Y,X,Z);
}
因此递归的思想就是上面说的两点,在二叉树的一些应用中也很常见。
在前面的博文中,说到二叉树的递归遍历算法为:
访问根节点;访问左子树;访问右子树。由于左子树的遍历又是同原树的遍历是一样的路子,因此递归调用这个函数即可。
status ProOd(BiTree T,visit* e)
{
visit(....);
if(T)
{
if(visit(T->data))
if(PreOd(T->lchild,visit))
if(PreOd(T->rchild),visit)
return OK;
return ERROR
}
return NULL;
}
在二叉树的一些应用中也有着递归的思想。
1.求二叉树叶子节点的个数
分析:还是和上面的递归分析一样,当事情为1的时候怎么办--->节点数即为1;做什么样的事情n次与n-1次相同---->除开根节点,求其左子树与右子树的叶子节点相当于做n-1的过程。另外注意到这里的终止条件应该为找到了叶子节点(其左子树与右子树皆为空),然后开始计数。
算法如下:
int ListLeaf(BiTree T,int count)
{
if(T)
{
if(T->lchild==NULL&&T->rchild==NULL)
count++;
ListLeaf(T->lchild,count);
ListLeaf(T->rchild,count);
return count;
}
else return 0;
}
2.求二叉树的深度
分析:当这件事为1的时候--->二叉树深度为1,做什么样的事情n次与n-1次是一样的--->求二叉树的左子树与右子树的深度与求原树的深度是一样的。
关系为:二叉树的深度等于其左子树与右子树深度的较大值加上1.
算法如下:
int depth(BITree T)
{
if(T)
{
if(T->lchild==NULL&&T->rchild==NULL)
d=1;
else
{
dleft=depth(T->lchild);
dright=depth(T->rchild);
d=1+max(dleft,dright);
}
return d;
}
else return 0;
}
3.复制二叉树
二叉树的本质即是一个指向根节点的节点指针,其含有数据域,左子树与右子树。复制二叉树可以分解为复制根节点数据域,根节点左右子树。然后再从其左子树复制,左子树又可以当做一个根节点,再分析其左右子树与数据域。因此创建节点,复制节点应该是非常重要的一环。
创建一个根节点:
BiNode* rootnode(int item,char *lchild,char* rchild)
{
T=(BiNode*)malloc(sizeof(Node));
if(!T) exit(1);
T->data=item;
T->lchild=newlchild;
T->rchild=newrchild;
return T;
}
BiNode *CopyTree(BiNode* T)
{
item=T->data;
if(T->lchild)
newlchild=CopyTree(T->lchild);
else return NULL;
if(T->rchild)
newrchild=CopyTree(T->rchild);
else return NULL;
newnode=rootnode(T->data,newlchild,newrchild);
return newnode;
}
方法可描述为将原来T的左子树复制给新左,将T的右子树复制给新右,将新左新右与数据按照节点函数结合在一起即可。
明日再介绍二叉树的建立过程。