day7-Java(递归、链队列)

限时加码!20+主流AI编程工具免费用 购周边加赠Coding Plan Lite,Claude Code、Cursor等即刻畅享,学习进阶更高效! 阅读详情

递归

一、关于递归

递归(Recursion)是指在函数的定义中使用函数自身的方法,通俗的说就是函数本身自己调用自己。格外重要的是,这个函数必须有明确的结束条件,否则就会导致无限递归的情况。如下:

public static int sumToN(int paraN) {
		// 结束条件
		if (paraN <= 0) {
			return 0;
		} // Of if 
		
		// 在函数中调用自己
		return sumToN(paraN - 1) + paraN; 
	} // Of sumToN

关于递归还需注意与循环的区别,递归顾名思义有一层一层往下的递,还有重要的归。当函数被调用时,它的变量空间是创建于运行时的堆栈上的,假定我以5这个值调用上述递归函数。堆栈内容如下表,栈顶位于最下方:

paraNsumToNreturn
第一次调用5sumToN(5)sumToN(4) + 5
第二次调用4sumToN(4)sumToN(3) + 4
第三次调用3sumToN(3)sumToN(2) + 3
第四次调用2sumToN(2)sumToN(1) + 2
第五次调用1sumToN(1)sumToN(0) + 1
第六次调用0sumToN(0)0

从上表的信息很容易看出,递归是如何将一个问题逐渐最小化解决的,从方法调用开始,函数return结果都会被压入栈,直到方法调用结束,最后从栈顶逐个返回得到结果。经过逐个代入,结果如下:

paraNsumToNreturn
0sumToN(0)0
1sumToN(1)0 + 1
2sumToN(2)0 + 1 + 2
3sumToN(3)0 + 1 + 2 + 3
4sumToN(4)0 + 1 + 2 + 3 + 4
5sumToN(5)0 + 1 + 2 + 3 + 4 + 5 = 15

二、递归求和与斐波那契数列

关于递归求和的体会在上段中已经作为例子详细阐述了,这段中就不再说明了。
斐波那契数列是指从第三项开始,每一项都等于前两项之和的这样一个数列(第一个和第二个数分别是1和1),可表示为如下形式: a n = a n − 1 + a n − 2 a_n = a_{n-1} + a_{n-2} an=an1+an2显然这是一个线性递推数列。求N的斐波那契数列代码实现如下:

public static int fibonacci(int paraN) {
		if (paraN <= 0) {
			// Negative values are invalid. Index 0 corresponds to the first element 0.
			return 0;
		} if (paraN ==1 ) {
			// Basis.
			return 1;
		} // Of if
		
		return fibonacci(paraN - 1) + fibonacci(paraN - 2);
	} // Of fibonacci

三、代码与运行结果

package datastructure.stack;

/**
 *
 *
 *@author Weijie Pu weijiepu@163.com.
 */
public class Recursion {
	/**
	 * 
	 ********************
	 * Sum to N. No loop, however a stack is used.
	 *
	 * @param paraN
	 * 			  The given value.
	 * @return The sum.
	 ********************
	 */
	public static int sumToN(int paraN) {
		if (paraN <= 0) {
			// Basis.
			return 0;
		} // Of if 
		
		return sumToN(paraN - 1) + paraN;
	} // Of sumToN
	
	/**
	 ********************
	 * Fibonacci sequence.
	 *
	 * @param paraN
	 * 			  The given value.
	 * @return The sum.
	 ********************
	 */
	public static int fibonacci(int paraN) {
		if (paraN <= 0) {
			// Negative values are invalid. Index 0 corresponds to the first element 0.
			return 0;
		} if (paraN ==1 ) {
			// Basis.
			return 1;
		} // Of if
		
		return fibonacci(paraN - 1) + fibonacci(paraN - 2);
	} // Of fibonacci
	
	/**
	 ********************
	 * The entrance of the program
	 *
	 * @param args
	 *  		  Not used now.
	 ********************
	 */
	public static void main(String args[]){
		int tempValue = 5;
		System.out.println("0 sum to " + tempValue + " = " + sumToN(tempValue));
		tempValue = -1;
		System.out.println("0 sum to " + tempValue + " = " + sumToN(tempValue));
		
		for (int i = 0; i < 10; i++) {
			System.out.println("Fibonacci " + i + ": " + fibonacci(i));
		} // Of for i
	} // Of main
} // class Recursion

运行结果:
在这里插入图片描述

总结

递归算法的一个重要思路就是把规模大的问题转化为规模小的子问题来解决,这些问题的演化是一个从大到小,由近及远的过程,并且会有一个明确的终点(临界点),一旦到达了这个终点,就不用再往更小、更远的地方走下去。最后,从这个终点开始,原路返回到原点,原问题以此解决。
在初学递归时,容易分不清递归和循环,两者有一个显然的共同特点,即做重复任务,但递归通常很直白地描述一个问题的求解过程,如这段代码中求和函数里 sumToN(paraN - 1) + paraN,而使用循环的算法有时并不会那么清晰地描述解决问题的步骤。这两者是两种不同的解决问题的思路。递归的简洁与可读性是最大的优点,而其效率问题是难以避免的缺点。

链队列

一、关于链队列

链队列的实现并不难,与前两天写的链表结构相似。不同的是链队列不仅有头指针,还有链表没有的尾指针,且入队仅操作尾部,出队仅操作头部(队列特点,先进先出,后进后出)。

二、链队列实现逻辑

创建一个内嵌类,节点Node由一个需要存储的对象data以及对下个节点的引用组成。

class Node {
		int data;
		Node next;
		public Node(int paraValue) {
			data = paraValue;
			next = null;
		} // Of the constructor
	} // Of class Node

头尾两个指针

Node header;
Node tail;

构造一个空链队列,头指针和尾指针都指向头结点。

public LinkedQueue() {
		header = new Node(-1);
		tail = header;
	} 

接下来就需要实现入队和出队的功能,参考前面链表部分的插入和删除操作,注意插入和删除分别在链队列的尾指针和头指针处进行。入队操作如下:
首先创建一个新的节点。

Node tempNode = new Node(paraValue);

然后将新节点插入到尾指针指向的节点之后,再使尾指针指向新节点,完成入队。

tail.next = tempNode;
tail = tempNode;

出队操作时,要检查队列是否为空,若为空,则无对象可出列。因为队列先进先出的特性,出队操作是在头指针指向的下一个节点处进行的,在进行几次出队操作后,若头指针指向的下一个节点为空,即只剩下头结点,则尾指针也指向头结点,即tail = header。

header.next = header.next.next;

三、代码与数据测试

package datastructure.queue;

/**
 * Linked queue
 *
 * @auther Weijie Pu weijiepu@163.com.
 */
public class LinkedQueue {
	
	/**
	 * An inner class
	 */
	class Node {
		/**
		 * The data
		 */
		int data;

		/**
		 * The reference to the next node.
		 */
		Node next;

		/**
		 ********************
		 * The constructor.
		 *
		 * @param paraValue
		 ********************
		 */
		public Node(int paraValue) {
			data = paraValue;
			next = null;
		} // Of the constructor
	} // Of class Node

	/**
	 * The header of the queue.
	 */
	Node header;

	/**
	 * The tail of the queue.
	 */
	Node tail;

	/**
	 ********************
	 * Construct an empty sequential list.
	 ********************
	 */
	public LinkedQueue() {
		header = new Node(-1);
		// header.next = null;

		tail = header;
	} // Of the first constructor

	/**
	 ********************
	 * Enqueue.
	 *
	 * @param paraValue
	 *            The value of the new node.
	 ********************
	 */
	public void enqueue(int paraValue) {
		Node tempNode = new Node(paraValue);
		tail.next = tempNode;
		tail = tempNode;
	} // Of enqueue

	/**
	 ********************
	 * Dequeue
	 *
	 * @return The value at the header.
	 ********************
	 */
	public int dequeue() {
		if (header == tail) {
			System.out.println("No element in the queue");
			return -1;
		} // Of if

		int resultValue = header.next.data;

		header.next = header.next.next;

		// The queue becomes empty.
		if (header.next == null) {
			tail = header;
		} // Of if

		return resultValue;
	} // Of dequeue

	/**
	 ********************
	 * Overrides the method claimed in Object, the superclass of any class.
	 ********************
	 */
	public String toString() {
		String resultString = "";

		if (header.next == null) {
			return "empty";
		} // Of if

		Node tempNode = header.next;
		while (tempNode != null) {
			resultString += tempNode.data + ", ";
			tempNode = tempNode.next;
		} // Of while

		return resultString;
	} // Of toString

	/**
	 ********************
	 * The entrance of the program.
	 *
	 * @param args
	 *            Not used now.
	 ********************
	 */
	public static void main(String args[]) {
		LinkedQueue tempQueue = new LinkedQueue();
		System.out.println("Initialized, the list is: " + tempQueue.toString());

		for (int i = 0; i < 5; i++) {
			tempQueue.enqueue(i + 1);
		} // Of for i 
		System.out.println("Enqueue, the queue is: " + tempQueue.toString());
		
		tempQueue.dequeue();
		System.out.println("Dequeue, the queue is: " + tempQueue.toString());
		
		int tempValue;
		for (int i = 0; i < 5; i++) {
			tempValue = tempQueue.dequeue();
			System.out.println("Looped delete " + tempValue + ", the new queue is: " + tempQueue.toString());
		} // Of for i
		
		for (int i = 0; i < 3; i++) {
			tempQueue.enqueue(i + 10);
		} // Of for i
		System.out.println("Enqueue, the queue is: " + tempQueue.toString());
	}// Of main
}// Of calss LinkedQueue

运行结果:
在这里插入图片描述

总结

链队列可以动态的申请和释放空间,在入队操作时不用检测队列是否已满,这也是链队列相较于顺序表的优点。队列是顺序结构,其存储的数据一个挨着一个,链表则是相当于一根线把存储数据连接起来,不难看出,在查找上,队列肯定是优于链表的,而在删除和插入上,链表只需把连接的线剪断再在断处用新的接上,所以实现起来很快。

今日代码量:217
累积:1506

VM虚拟机下,通过无线,有线两种方式连接PLC的设置方法 1,VMware软件:编辑>虚拟网络编辑器。 2.右下角:更改设置(如果可以选中“添加网络”选项,则可考虑略过此步) 3.选中VMnet0,点击桥接模式,选中你的物理机有线网卡。点击确定。 4.点击添加网络,我的添加完是VMnet2,然后选中,像上一步样,点击桥接模式,在下拉菜单中选中笔记本的【无线网卡】,然后点击确定。 5.VMware软件:虚拟机>设置。 6.点击 添加>网络... 阅读详情

相关推荐

Lisflood

文献:基于SWMM和LISFLOOD-FP模型的居住区低影响开发模拟评价。问题:多个节点溢流同时,不行,待解决。目录下,cmd命令行。

警警的博客 2608

java 递归有次数限制吗,小心递归次数限制

最近, 我在 review 组员的 Python 代码时, 发现了一个递归调用, 我立即发现了其中的问题.先说一下编程中递归. 只有会用递归, 并且能随心应手地写出递归程序的程序员, 才是已经入门了的程序员. 不过, 许多程序员并没有发现编程中的递归的一个限制: recursion depth limit, 逻辑上的递归可以无次数限制, 但语言执行器或者程序堆栈会限制递归的次数.例如一个 Cpy ...

weixin_42512936的博客 3039

保姆级教程:从Navicat 11/12到15,平滑升级搞定MySQL 8.0的caching_sha2_password认证

本文提供从Navicat 11/12升级到15的保姆级教程,重点解决MySQL 8.0的caching_sha2_password认证问题。详细介绍了备份配置、新版本功能亮点、跨平台安装步骤、配置迁移流程以及高级使用技巧,帮助用户平滑过渡到Navicat 15,提升数据库管理效率。

weixin_33724046的博客 179

Java队列优化递归

遍历的树深的时候,使用队列来优化递归

pseudonym_的博客 6209

java 递归调整为队列

如果递归的是深而不广的树时,应该使用队列来优化递归;如果递归是广而不深的树的时候,就应该用递归来优化队列。 https://blog.csdn.net/pseudonym_/article/details/71600084?utm_source=itdadao&utm_medium=referral 转载于:https://www.cnblogs.com/qxynotebook/p/95...

weixin_30408309的博客 285

Java8新特性-使用Stream流递归实现遍历树形结构

1.实体类: package entity; import lombok.Builder; import lombok.Data; import java.util.List; /** * 描述:Menu * * @author 何志鹏 * @ClassName:Menu * @create 2021-03-05 10:42 * Version 1.0 */ @Data @Builder public class Menu { /** * id */.

weixin_39643007的博客 3191

Java: 栈+递归实现队列功能和操作(add,poll,peek)

package offer; import java.util.Stack; public class Queue_rec { private Stack&lt;Integer&gt; stack; public Queue_rec(){ this.stack=new Stack&lt;Integer&gt;(); } public void add(int newNu...

One's Blog 1129

JAVA数据结构 DAY6-栈和队列

本文是Java数据结构学习笔记系列,重点讲解栈和队列两种基础数据结构。文章详细介绍了栈(LIFO)队列(FIFO)的概念、核心方法、模拟实现(数组/)及典型应用场景。特别对循环队列和双端队列(Deque)进行了深入解析,并提供了LeetCode高频面试题的解题思路。通过代码示例和详细注释,帮助读者深入理解数据结构原理,掌握从理论到实践的完整知识体系。文章还区分了易混淆概念,适合Java初学者和面试准备者系统学习数据结构基础知识。

HRDMN的博客 895

Day0301 Java队列(queue)

一、队列定义及实现 队列是一种操作受限的线性表,它只允许在线性表的一端进行插入操作(rear),在另一端进行删除操作(front)Java用LinkedList类实现Queue接口,我们可以把LinkedList当成Queue来用。 相关方法及代码实现参见:https://blog.csdn.net/qq_36625806/article/details/78985589 二、二叉树结点数的计算...

qq_31842777的博客 165

扩展--使用队列来优化递归操作完成文件下载

扩展:使用队列来优化递归操作. 队列特点:先进先出. 在jdk中有一个接口Queue 它有一个实现类叫LinkedList它其时就是一个队列。 如果要使用队列,插入 offer 获取使用 poll 使用队列来优化递归操作:是可以解决目录层次过多问题。 因为:递归操作可以理解成是纵向的遍历,如果目录层次比较多,在内存中存储的数据也多,会引起溢出。 使用队列,它...

Leon_Jinhai_Sun的博客 386

Java day16——队列Queue、二叉树优化(递归)、Set(I)、Map(I)

这里写目录标题队列QueueAPIDeque双端队列LinkedList二叉树优化(递归)Set(I)HashSetadd原理remove移除why重写hashCode和equalsSortedSet(I)总结Map(I)常用API迭代方式应用——统计个数 队列Queue Queue(I): - 队列(offer/peek/poll) Deque(I) - 双端队列(offerFirst/offerLast…) -(push/pop) LinkedList API offer("")

qq_40905010的博客 333

蓝桥杯刷题 Day3 队列、并查集

今天写牛客网模板题中的队列、并查集

WYyanyufei的博客 711

Java复习Day25

递归是一种通过将问题分解为同类子问题来求解的方法,表现为方法自我调用。类比查词典:当遇到不理解的词时查阅,若解释中仍有不理解的词则继续查阅,直到获得明确解释,再回溯理解最初的问题。队列是操作受限的线性表,只允许在表的一端(队尾Rear)插入,另一端(队头Front)删除。其特性为先进先出(FIFO)。按方向:单向队列、双向队列按阻塞情况:阻塞队列、非阻塞队列按容量限制:有界队列、无界队列

Lanii_的博客 327

JAVA数据结构 DAY7-二叉树

本文是Java数据结构系列教程中的二叉树学习笔记,系统讲解了二叉树的核心概念和操作。内容包括:树形结构基础概念、二叉树的定义与特性(满二叉树、完全二叉树)、五大核心性质及计算题解析、存储结构(顺序/链式)比较。重点介绍了二叉树的遍历方式(前/中/后序递归实现及层序遍历)和常用基本操作(节点统计、查找、判断完全二叉树等),提供完整Java代码实现。文章还汇总了14道经典OJ题解题思路,涵盖基础操作和进阶题目(构建二叉树、最近公共祖先等)。

HRDMN的博客 542

Java错题归纳day16

A顺序表B双表C带头结点的双循环表D单循环表答案A解析线性表最常用得操作是存取任一指定序号的元素和在最后进行插入和删除运算;进行任意位置存取,这个最省时省力的就是数组了,也就是顺序表。而且元素是在最后的位置进行插入和删除运算,也就不涉及其他元素进行位移的额外操作,最多涉及的就是去扩展空间了。...

m0_52322019的博客 1525

day13 栈与队列(单调队列、堆、优先队列

单调队列、优先队列

weixin_41029475的博客 190

Day10|栈与队列

通过两个指针在一个for循环下完成两个for循环的工作。

weixin_44997209的博客 264

LeetCode刷题笔记day18-翻转二叉树(递归和非递归实现)

翻转一棵二叉树。 示例: 输入: 4 / 2 7 / \ / 1 3 6 9 输出: 4 / 7 2 / \ / 9 6 3 1 接:https://leetcode-cn.com/problems/invert-binary-tree 递归算法: ①、确定递归参数 ②、确定退出条件 ③、确定单层逻辑 首先,当root为空时直接返回,invertTree函数的作用相当于将二叉树绕中心轴旋转180°,故先将左子树翻转180°,再将右子树翻转180°,最

Mark_able 342

数据结构day10栈-队列--复习

Python 字符串: 单引号或者双引号 数字: int float complex list [] 可以存不同类型数据的数组 tuple () 不可更改的列表 dict {k:v} 可以自定义的索引列表 set {} 无序不重复 数据结构 数据结构 : 其实就是存储数据和表⽰数据的⽅式。数据结构内容⽐较多,细细的学起来也是相对费功夫 的,不可能达到⼀蹴⽽就。我们将常⻅的数据结构:堆栈、队列、数组、表和红⿊树 这⼏种给⼤家介 绍⼀下,作为数据结构的⼊⻔,了解⼀下它们的特点即可。 栈:

__Miracle__ 255

百日算法修炼 · Day 10

本文介绍了8个算法练习,涵盖表、栈、队列递归等核心数据结构与操作。主要内容包括:反转单表(指针修改顺序)、删除指定节点(虚拟头节点技巧)、双端队列模拟栈和队列、环形数组队列实现、O(1)获取最小值的栈设计、两个栈实现队列(延迟倒数据)、两个队列实现栈(保留最后一个元素),以及递归求解区间最大值(分治思想)。每个练习都强调关键思维:指针操作需先保存后继、数据结构可以互相模拟、递归要拆解大问题为小问题。建议先独立完成练习再对照参考答案,重点关注指针顺序、状态维护和问题分解能力。

linux_hzh的博客 613

阻塞队列、线程池、File类、递归

阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素。遍历某一文件夹目录下的所有文件和所有的子目录。下面是老韩的视频截取部分.(侵权删)古人学问无遗力,少壮工夫老始成。纸上得来终觉浅,绝知此事要躬行。回溯算法 思想原理。

weixin_67024075的博客 108

day 31死锁和递归

day 31死锁和递归锁 1.死锁和递归锁 所谓死锁:是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程 #科学家吃面问题 from threading import Thread,Lock import time lock1=Lock() lock2=lock1 def eat1(name): lock1.acquire() print('%s

qq_1617271856的博客 189
上一篇: day6-Java体验(228行)
下一篇: day8-Java(循环列表)
nooooooooooob
博客等级 码龄8年 0粉丝 19原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值