递归入门
递归函数的特征
- 在函数里面自己调用自己,子问题须与原始问题为同样的事,且更为简单;
- 不能无限制地调用本身,须有个出口,化简为非递归状况处理(否则会栈溢出)。
PS:在运用递归函数的是,我们应该给函数反复调用自己的时候给一个出口给他,否则函数一直被调用但却没有返回会使得CPU中的栈溢出:C语言内存四区
递归函数的模板
- 这个递归函数的功能是什么,怎样调用这个函数,即设计好递归函数的返回值和参数列表
- 什么时候应该结束这个递归,它的边界条件(出口)是什么 (边界条件)
- 在非边界情况时,怎样从第n层转变成第n+1层 (递推公式)
int recursion(参数0)
{
if (终止条件)
{
return c;//返回一个常数,终止递归
}
recursion(参数1);
}
我对于递归的理解是来自于多米诺骨牌:递归与BUG
计算阶乘(factorial)
n ! = { 1 n = 0 n ∗ ( n − 1 ) ! n > 0 n!=\begin{cases} 1 & n=0 \\ n*(n-1)! & n>0 \end{cases} n!={1n∗(n−1)!n=0n>0
int factorial(int n)
{
if (n==1)
return 1;
else
return n*factorial(n-1);
}
递归实战
归并排序
分治思想
分治法的设计思想:
- 分–将问题分解为规模更小的子问题;
- 治–将这些规模更小的子问题逐个击破;
- 合–将已解决的子问题合并,最终得出“母”问题的解;
- 减而治之(每次让问题的规模减1)
- 分而治之(每次让问题的规模减半)(归并排序的思想)
/**
* @name : void MergeArray(int *a,int begin,int mid,int end,int *temp);
* @description : 归并排序(合并数组)
* @param : 数组指针a,数组起点begin,数组中点mid,数组终点end,承载数组指针temp
*/
void MergeArray(int *a,int begin,int mid,int end,int *temp)//将两个有序数组合并成一个有序数组
{
int i=0,j=0,k=0;
for(k=begin;k<=end;k++)
{
temp[k]=a[k];
}
for(i=begin,j=mid+1,k=i; i<=mid && j<=end; k++)//K是为了给即将排序好的的数组做标记的
{
if(temp[i]<=temp[j])//比较被分开的两个数组的第一位的大小
{
a[k]=temp[i];
i++;
}
else
{
a[k]=temp[j];
j++;
}
}
while(i<=mid)
{
a[k]=temp[i];
k++;i++;
}
while(j<=end)
{
a[k]=temp[j];
k++;j++;
}
}
/**
* @name : void MergeSort(int *a,int begin,int end,int *temp);
* @description : 归并排序
* @param : 数组指针a,数组起点begin,数组终点end,承载数组指针temp
*/
void MergeSort(int *a,int begin,int end,int *temp)//归并排序,递归函数,把数组对半拆分
{
if(begin<end)
{
int mid=(begin+end)/2;
MergeSort(a,begin,mid,temp);//让左边有序
MergeSort(a,mid+1,end,temp);//让右边有序
MergeArray(a,begin,mid,end,temp);
}
else
return;
}
二叉树的递归遍历
//递归遍历函数
void visit(NodePtr n)
{
printf(" %d ",n->value);
}
先序遍历
Status RecursionPreTravel(NodePtr node,void (*visit(NodePtr)))
{
if(node==NULL)
{
return ERROR;
}
else
{
visit(node);
RecursionPreTravel(node->left,visit);
RecursionPreTravel(node->right,visit);
}
}
Status BST_preorderR(BinarySortTreePtr P, void (*visit)(NodePtr))
{
if(P->root==NULL)
{
printf("树为空树!\n");
return ERROR;
}
else
{
printf("递归前序遍历结果为\n");
RecursionPreTravel(P->root,visit);
printf("\n");
return SUCCESS;
}
}
中序遍历
Status RecursionINTravel(NodePtr node,void (*visit(NodePtr)))
{
if(node==NULL)
{
return ERROR;
}
else
{
RecursionINTravel(node->left,visit);
visit(node);
RecursionINTravel(node->right,visit);
}
}
Status BST_inorderR(BinarySortTreePtr P, void (*visit)(NodePtr))
{
if(P->root==NULL)
{
printf("树为空树!\n");
return ERROR;
}
else
{
printf("递归中序遍历结果为\n");
RecursionINTravel(P->root,visit);
printf("\n");
return SUCCESS;
}
}
后序遍历
Status RecursionPostTravel(NodePtr node,void (*visit(NodePtr)))
{
if(node==NULL)
{
return ERROR;
}
else
{
RecursionPostTravel(node->left,visit);
RecursionPostTravel(node->right,visit);
visit(node);
}
}
Status BST_postorderR(BinarySortTreePtr P, void (*visit)(NodePtr))
{
if(P->root==NULL)
{
printf("树为空树!\n");
return ERROR;
}
else
{
printf("递归后序遍历结果为\n");
RecursionPostTravel(P->root,visit);
printf("\n");
return SUCCESS;
}
}