递归

递归

递归函数:非常重要的一点就是不要在意他的过程是怎么实现的而是要选择去相信他,这是一定可以实现的。能得到我们想要的结果,并且将它当做结论来使用

使用递归函数:

1.确定这个函数的功能。

2.确定这个函数的返回值。

3.相信这个函数可以得到我们想要的。

4.在我们的递归函数中怎么使用到这个递归函数本身,也就是他的子问题。

5.他的终止条件是什么。(我们递归所变化的参数当为什么值时不用递归就可以明确知道他的返回值)

6.在调用递归函数之后我们可以继续进行操作,我们只需要知道他返回的值是什么,无需关心他是怎么实现的。

例题:Pow(x, n)

#include<iostream>
using namespace std;

/* - 首先确定这个函数的功能:很明确,这个函数的功能就是求x的n次幂
 * - 其次确定这个函数的返回值是一个double的数
 * - 再者他的终止条件是什么
 */
double Pow(int x,int n){
    /*终止条件:同样设置终止条件的时候我们不要去考虑,这个函数慢慢递归递归到什么程度的时候要返回什么值
    而是随着递归函数参数的变化,我们给出一些不用递归就可以得出答案的参数案例。
    一个简单的基本案例(basic case)(或一些案例) —— 能够不使用递归就能产生答案的终止方案。
    例如:此题:递归函数变化的参数是n我们寻找当n等于多少时我们不用递归就可以得到结果,这种数学公式显而易			见就可以得到,将其填上就可以了
    	 再有:像二叉树,链表那种题目。我们都是对链结点或者树结点进行操作,然后经常需要用到下一个结点的		 数据,但是我们可以很容易就知道,当遇到链表为空的时候我们可以知道这个结点里面没有任何东西,也没		 有下个结点,当到达叶结点的时候同样如此*/
    if(n == 1) return x;
    if(n == 0) return 1;
    if(n == -1) return 1/x;
   
    /* 我们相信Pow(x,n/2)这个函数会将x的n/2次幂的值以double类型的值返回给我们,并且我们将使用这个结		  果进行操作。*/    
    double half = Pow(x,n/2);
    
    /* 注意:在调用递归函数之后还能继续操作,甚至是调动递归。你不用管他怎么进行到下一步的,我们只要相信			上一步的递归能得到我们想要的就行了*/
    double res = Pow(x,n%2);
    
    /* 返回值:我们不需要管我们子问题的返回值是什么对我们最后的结果有什么问题,我们只需要应用我们子问题			的递归函数的结果凑成最终我们想要的答案就可以了 
    	例如这一题,我们相信half是x的n/2次幂的结果,res是他们余数次幂的结果,并应用他们的结果返回我们		的值就行了,其返回的就是x的n次幂*/
    return half*half*res;
}

int main()
{
    cout<<Pow(2,10)<<endl;
    return 0;
}

注意:

  • 递归非常重要的一点就是不要去纠结他的过程,他是怎么实现的,而是要去想他的结果,我们怎么利用他的结果得到我们想要的结论。

  • 还有刚接触递归的时候,看到那个快速排序的时候,在一个函数的里同时调用两次递归,当时我就是去在意他的实现过程,我一步一步去推。一个递归函数头就很大了,两个递归函数同时出现,我头更大了,整个人都傻掉了。

快排思想:

快速排序就是将一些混乱的数字按照一定的顺序排好。采用的方法是,选出一个数比这个数大的放右边,比这个数小的放左边,然后对左右两边再做同样的操作,直到他完全排好。

实现的时候就是会左边递归一次,然后右边再递归一次,当时就会去纠结如果第一次递归调用的时候调用掉第二个递归函数,第二个递归调用的时候又调用到第一个递归然后会不会无限循环下去。其实这样的担心完全没有必要,我们不用去想为什么不会,而是去相信他能得到我们想要的结果就行了,第一个递归能把左边的数全部排好,第二递归能把右边的数全部排好,这就够了。

  • 其实我们只要去想我们是调用另一个函数完成这个功能,而且这个函数是正确的并且保证会完成我们想要的结果,只是调用的这个函数是自己本身就会好理解很多。

快速排序(quick sort)

#include <stdio.h>

void swap(int a[], int i, int j)
{
	int t = a[i];
	a[i] = a[j];
	a[j] = t;
}

/*选一个数将大于这个数的放在右边,小于这个数的放在左边,返回中间这个值得位置*/
int partition(int a[], int p, int r)
{
    int i = p;
    int j = r + 1;
    int x = a[p];
    while(1){
        while(i<r && a[++i]<x);
        while(a[--j]>x);
        if(i>=j) break;
        swap(a,i,j);
    }
	swap(a,p,j);
    return j;
}

/* 递归快排:
 * 参数1:需要排序的数组
 * 参数2:排序的开始位置
 * 参数3:排序的结束位置
 * 结束条件:让结束位置大于或等于开始位置的时候,说明已经排序结束完成了
 * 没有返回值
 * 函数的功能:将起始位置到结束位置的数字按从小到大的顺序排序好。
 */
void quicksort(int a[], int p, int r)
{
    if(p<r){
        int q = partition(a,p,r);
        quicksort(a,p,q-1);
        quicksort(a,q+1,r);
    }
}
    
int main()
{
	int i;
	int a[] = {5,13,6,24,2,8,19,27,6,12,1,17};
	int N = 12;
	
	quicksort(a, 0, N-1);
	
	for(i=0; i<N; i++) printf("%d ", a[i]);
	printf("\n");
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值