什么是递归

一定要明白递归函数中每个参数的含义,这样在逻辑处理和函数调用的时候才能得心应手,

函数的调用我们一定不要去一步步拆开去

递归模板

递归必须具备两个条件,一个是调用自己,一个是有终止条件。这两个条件必须同时具备,且一个都不能少。并且终止条件必须是在递归最开始的地方,也就是下面这样

递归就是在函数内部调用自身的函数。


public void recursion(参数0) {
    if (终止条件) {
        return;
    }
    recursion(参数1);
}

不能把终止条件写在递归结束的位置

实例分析

递归的理解是先往下一层层传递,当碰到终止条件的时候会反弹,最终会反弹到调用处。下面我们就以5个最常见的示例来分析下

最简单的递归调用-阶乘

    public int recursion(int n) {
        if (n == 1) {
            return 1;
        }
        return n * recursion(n - 1);
    }

在这里插入图片描述
递归的目的是把一个大的问题细分为更小的子问题,我们只需要知道递归函数的功能即可,不要把递归一层一层的拆开来想,

斐波那契数列

道斐波那契数列当前的值是前两个值的和

public int recursion(int n) {
    if (n == 1 || n == 2) {
        return 1;
    }
    return recursion(n-1)+recursion(n-2);
}

前序遍历

    public void recursion(TreeNode treeNode) {
        // 终止条件 (必须要有)
        if (treeNode == null) {
            return;
        }
        // 逻辑处理 (不是必须的)
        System.out.println("treeNode.val = " + treeNode.val);
        // 递归调用 (必须要有)
        recursion(treeNode.left);
        recursion(treeNode.right);
    }

中序遍历

    public void recursion(TreeNode treeNode) {
        // 终止条件 (必须要有)
        if (treeNode == null) {
            return;
        }
        // 逻辑处理 (不是必须的)
        // 递归调用 (必须要有)
        recursion(treeNode.left);
        System.out.println("treeNode.val = " + treeNode.val);
        recursion(treeNode.right);
    }

后序遍历

    public void recursion(TreeNode treeNode) {
        // 终止条件 (必须要有)
        if (treeNode == null) {
            return;
        }
        // 逻辑处理 (不是必须的)
        // 递归调用 (必须要有)
        recursion(treeNode.left);
        recursion(treeNode.right);
        System.out.println("treeNode.val = " + treeNode.val);
    }

在树的前序,中序,后序遍历算法中,递归的实现明显要比循环简单得多。

递归由于是函数调用自身,而函数调用是有时间和空间的消耗的:每一次函数调用,都需要在内存栈中分配空间以保存参数、返回地址以及临时变量,而往栈中压入数据和弹出数据都需要时间。(效率)

递归中很多计算都是重复的,由于其本质是把一个问题分解成两个或者多个小问题,多个小问题存在相互重叠的部分,则存在重复计算,如fibonacci斐波那契数列的递归实现。(效率)

调用栈可能会溢出,其实每一次函数调用会在内存栈中分配空间,而每个进程的栈的容量是有限的,当调用的层次太多时,就会超出栈的容量,从而导致栈溢出。(性能)

package com.softsec;

/**
 * 递归计算n的阶乘
 * @author Chenhh
 */
public class demo {
    
    public static void main(String[] args) {
        System.out.println(recursion(5));
    }
    
    /**
     * 递归计算n的阶乘
     */
    private static int recursion(int n) {
        if (n <1) {
            throw new IllegalArgumentException("参数必须大于0");
        } else if (n == 1) {
            return 1;
        } else {
            return n * recursion(n - 1);
        }
    }

}

class Node {
	private int Data;// 数据域
	private Node Next;// 指针域
}


/**
public class javatest1 {
    public static void main(String[] args) {
        Node head = new Node(0);
        Node node1 = new Node(1);
        Node node2 = new Node(2);
        Node node3 = new Node(3);
        head.setNext(node1);
        node1.setNext(node2);
        node2.setNext(node3);
        Node h = head;
        while (null != h) {
            System.out.print(h.getData() + " ");
            h = h.getNext();
        }
        head = Reverse1(head);
         while (null != head) {
            System.out.print(head.getData() + " ");
            head = head.getNext();
        }
    }

    /**
     * 递归,在反转当前节点之前先反转后续节点
     */
    public static Node Reverse1(Node head) {
        // head看作是前一结点,head.getNext()是当前结点,reHead是反转后新链表的头结点
        if (head == null || head.getNext() == null) {
            return head;// 若为空链或者当前结点的下一个节点在尾结点,则直接还回
        }
        Node reHead = Reverse1(head.getNext());// 先反转后续节点head.getNext()
        head.getNext().setNext(head);// 将当前结点的指针域指向前一结点
        head.setNext(null);// 前一结点的指针域令为null;
        return reHead;// 反转后新链表的头结点
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值