C语言-递归算法思想

写在前面

继上篇博文里介绍的C语言常见基础算法,本篇在于算法的思路的整理和常见的算法编程实现。

递归的含义和常见应用

【定義】递归具体用法其实就是让你把一个问题分解成很多个类似的情况,虽然你要解决这个问题非常难,莫名其妙,要你想几年,但是把他一直递归分解,就变成很好理解的单种情况,而你整个问题又是跟这个单种情况类似,把整个问题通过递归调用一层一层分解到最低级简单的那种情况,就是你所需要理解的了。
一个函数在它的函数体内调用它自身称为递归调用。这种函数称为递归函数。C语言允许函数的递归调用。在递归调用中,主调函数又是被调函数。执行递归函数将反复调用其自身,每调用一次就进入新的一层。
常见的用法:1、斐波那契数列

// 计算fibonaci数列---2
int fibonaci_2(int n)
{
    if(n<=2)
    {
        return 1;
    }
    else
    {
        return fibonacci_2(n-1)+fibonacci_2(n-2);
    }
}
0 1 1 2 3 5 8....
或者定义一个公有的temp,返回该值。边界条件可以是n=0\n=1

2、阶乘

n!=1 (n=0,1)
n!=n*(n-1)! (n>1)
(n-1)!=(n-1)*(n-2)!
具体如下
long ff(int n)
{
	long f;
	if(n<0) printf("n<0,input error");
	else if(n==0||n==1) f=1;
	else f=ff(n-1)*n;
	return(f);
}
经过n次入栈后,剩下n=1的已知值,后续全部相乘,直接得到答案,返回结果,出栈一次

3、倒序输出字符串、数字转字符等

void alpha_exchange_2(void)
{
    char temp;
    scanf("%c",&temp);
    if(temp != '\n') // 给出正确的退出条件
    {
        alpha_exchange_2();
        printf("%c",temp);
    }
}
void alpha_exchange_3(void)
{
    char temp;
    scanf("%c",&temp);//temp的值必须要先由输入获得
    if(temp == '\n') // 给出正确的退出条件
    {
        // printf("%c\n",temp);
        return temp;
    }
    alpha_exchange_3();
    printf("%c",temp);
}
void binary_to_ascii(unsigned int value)
{
    unsigned int quotient;
    quotient = value / 10;
    //將數據按照高位到地位逐漸變小
    if(quotient != 0)
    binary_to_ascii(quotient);
    //按照順序輸出每一位值
    putchar(value%10+'0');
}
该函数出栈了n次,将每一次传入参数出栈计算,都是结果的一部分

4、翻转链表,翻转队列

struct ListNode* reverseList(struct ListNode* head){
    if (head == NULL || head->next == NULL)
        return head;
    else
    {
        struct ListNode *newhead = reverseList(head->next);
        head->next->next = head;
        head->next = NULL;
        return newhead;
    }
}
//递归实现
struct node * reverse(struct node *pHead)
{
    if (pHead == NULL || pHead -> pNext == NULL)
    {   
        return pHead;
    }   
    struct node *p = pHead -> pNext;
    struct node *pNewHead =  reverse(p);
    p -> pNext = pHead;
    pHead ->pNext = NULL;
    return pNewHead;
}

优化方法介绍(尾递归)
从我给出的第一算法可以看出,先进栈再出栈,递归的效率是很低的。速度上完全比不上迭代(循环)。但是尾递归引入了一个新的函数参数,用这个新的函数参数来记录中间值。普通递归阶乘fac(x),就1个x而已,尾递归用2个参数fac(x,y),y存放阶乘值。

int fac(int x, int y) {
	if (x == 1)
		return y;
	else return fac(x-1, y*x);
}

int ff(int x)
{
	if (x == 0)
		return 1;
	else return fac(x,1);
}

int fac(int x, int y)
{
	if(x == 0)
	return 1;
	if(x == 1)
	{
		return y;
	}
	else
	{
		return fac(x, x*y);
	}
}
对于这个程序我们先看函数ff,函数ff其实是对fac的一个封装函数,
纯粹是为了输入方便设计的,通过调用ff(x)来调用fac(x,1)

这里常数1就是当x=1的时候阶乘值了,我通过走一遍当x=3时的值即为3!来说明一下。首先ff(3),x!=0,执行fac(3,1).第一次调用fac,x=3,y=1,x!=1,调用fac(x-1,yx),新的x=2,y=3*1=3,这里可以看到,y已经累计了一次阶乘值了,你会发现这个递归更类似于迭代了。事实上我们用了y记录了普通递归时候,出栈的乘积,所以减少了出栈后的步骤。

【推荐文章】
本博文详细介绍了递归的入栈和出栈的过程,需要特别强调的是递归的结束条件以及选用递归的传入参数。
在调用函数之后的代码是在函数返回后执行的,因此会层次的调用出栈的变量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值