递归从入门到入土

递归入门

递归函数的特征

  1. 在函数里面自己调用自己,子问题须与原始问题为同样的事,且更为简单;
  2. 不能无限制地调用本身,须有个出口,化简为非递归状况处理(否则会栈溢出)。

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(n1)!n=0n>0

int factorial(int n)
{
    if (n==1)
        return 1;
    else
        return n*factorial(n-1);
}

在这里插入图片描述

递归实战

归并排序

分治思想
分治法的设计思想:

  1. 分–将问题分解为规模更小的子问题;
  2. 治–将这些规模更小的子问题逐个击破;
  3. 合–将已解决的子问题合并,最终得出“母”问题的解;
  • 减而治之(每次让问题的规模减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;
	}
}

参考资料

递归从入门到精通
什么是递归,通过这篇文章,让你彻底搞懂递归

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值