首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么递归函数中的迭代器在返回后指向开头?

递归函数中的迭代器在返回后指向开头的原因是因为递归函数的特性决定了每次递归调用都会创建一个新的函数栈帧,而函数栈帧中的局部变量和迭代器都是独立的。

当递归函数执行到迭代器的创建语句时,会在当前函数栈帧中创建一个新的迭代器对象,并将其指向迭代对象的开头位置。随后,递归函数会继续执行下一步操作,可能是递归调用或其他操作。

当递归函数的递归调用返回时,会销毁当前函数栈帧并返回到上一层函数栈帧。这意味着上一层函数栈帧中的迭代器对象仍然存在,并且保持着之前的状态,即指向迭代对象的开头位置。

这种设计是为了保持递归函数的状态独立性,使得每次递归调用都能够独立地操作迭代器对象,而不会相互干扰。同时,这也符合递归函数的逻辑,因为每次递归调用都是在处理迭代对象的一部分数据,而不是整个迭代对象。

需要注意的是,递归函数中的迭代器在返回后指向开头,并不意味着它会重新遍历整个迭代对象。如果需要重新遍历迭代对象,可以在递归函数中重新创建一个新的迭代器对象。

总结起来,递归函数中的迭代器在返回后指向开头是为了保持递归函数的状态独立性,使得每次递归调用都能够独立地操作迭代器对象。这样设计可以更好地支持递归函数对迭代对象的处理。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

学了链表牛刀小试,三种做法都吃透就算是学会了

对于这个问题,这题很好心地在进阶里面给了我们提示,可以使用迭代或者递归的方法。 我个人感觉这两种方法难度差不多,不过从理解难度上来说,递归的方法更简单直观一些。...递归法 为什么说递归的方法稍微更直观呢?因为我们可以把递归函数本身当成是一个能够在更小范围内运作的黑盒,接着,我们要做的就是像是套娃一样,让它能够在更大的范围当中实现同样的功能。...比如在这题当中,我们要使用递归来实现reverseList函数。我们先假设,它能够在比当前更小的范围内运行。...实际上我们大可以不必如此,我们直接让递归函数也返回末尾的指针即可。但这样的话,我们就修改了返回值的类型,所以就要单独写一个递归来实现了。...既然如此,我们既可以每次插入在末尾,自然也可以插入在头部。如果我们每次插入元素都在头部的话,得到的链表中的元素顺序刚好和之前相反。

25420

递归反转链表一部分

转载自labuladong的算法小抄,go语言描述 反转单链表的迭代实现不是一个困难的事情,但是递归实现就有点难度了,如果再加一点难度,让你仅仅反转单链表中的一部分,你是否能够递归实现呢?...具体来说,我们的 reverse 函数定义是这样的: 输入一个节点 head,将「以 head 为起点」的链表反转,并返回反转之后的头结点。 明白了函数的定义,在来看这个问题。...并且根据函数定义,reverse 函数会返回反转之后的头结点,我们用变量 last 接收了。 现在再来看下面的代码: head.next.next = head ?...2、当链表递归反转之后,新的头结点是 last,而之前的 head 变成了最后一个节点,别忘了链表的末尾要指向 null: head.next = nil 理解了这两点后,我们就可以进一步深入了,接下来的问题其实都是在这个算法上的扩展...四、最后总结 递归的思想相对迭代思想,稍微有点难以理解,处理的技巧是:不要跳进递归,而是利用明确的定义来实现算法逻辑。

89720
  • 前端常见手写面试题

    this: {name: 'poetries', age: 18}注意: bind之后不能再次修改this的指向,bind多次后执行,函数this还是指向第一次bind的对象实现Array.isArray...实现迭代器生成函数我们说迭代器对象全凭迭代器生成函数帮我们生成。...在ES6中,实现一个迭代器生成函数并不是什么难事儿,因为ES6早帮我们考虑好了全套的解决方案,内置了贴心的 生成器 (Generator)供我们使用:// 编写一个迭代器生成函数function *iteratorGenerator...下面我们要做的,不仅仅是写一个迭代器对象,而是用ES5去写一个能够生成迭代器对象的迭代器生成函数(解析在注释里):// 定义生成器函数,入参是任意集合function iteratorGenerator...(3)让函数的 this 指向这个对象,执行构造函数的代码(为这个新对象添加属性)(4)判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象。

    36220

    《C++ primer》--第三章

    getline函数对空白字符的处理:不忽略行开头的空白字符,读取字符直至遇到换行符,读取终止并丢弃换行符(换行符从输入流中去掉但并不存储在string对象中)。...const迭代器是迭代器常量,该迭代器本身的值不能修改,即该迭代器在定义时需要初始化,而且初始化之后,不能再指向其他元素。若需要指向固定元素的迭代器,则可以使用const迭代器。...const迭代器这种类型几乎没什么用处:一旦它被初始化后,只能用它来改写其指向的元素,但不能使它指向任何其他元素。...const_iterator是一种迭代器类型,对这种类型的迭代器解引用会得到一个指向const对象的引用,即通过这种迭代器访问到得对象是常量。...道理很简单:因为前置操作需要做的工作更少,只需加1返回加1后的结果即可。而后置操作符则必须先保存操作数原来的值,以便返回未加1之前的值作为操作的结果。

    63250

    C++相关基础知识总结笔记

    C++什么情况下迭代器会失效? 在 C++ 中,迭代器失效通常发生在容器的状态发生改变,导致迭代器不再指向有效的元素或者其指向的元素的位置发生了变化。 以下是一些常见的迭代器失效的情况: 1....但是: 删除元素:删除当前迭代器指向的元素会使该迭代器失效。但删除操作不会影响其他迭代器的有效性。 例如,std::map::erase 会使被删除元素的迭代器失效,但不影响其他迭代器。...如何避免迭代器失效 为了避免迭代器失效带来的问题,可以采取以下措施: 使用返回值:某些容器的成员函数会返回有效的迭代器,例如 std::vector::erase 返回下一个有效迭代器。...可以看到在删除元素后,迭代器失效的情况。...在实际编程中,应始终留意迭代器是否仍然有效,并采取适当的措施来避免由此引发的问题。

    21330

    前端面试遇到了这些手写题

    在ES6中,实现一个迭代器生成函数并不是什么难事儿,因为ES6早帮我们考虑好了全套的解决方案,内置了贴心的 生成器 (Generator)供我们使用:// 编写一个迭代器生成函数function *iteratorGenerator...下面我们要做的,不仅仅是写一个迭代器对象,而是用ES5去写一个能够生成迭代器对象的迭代器生成函数(解析在注释里):// 定义生成器函数,入参是任意集合function iteratorGenerator...运行一下我们自定义的迭代器,结果符合预期:图片实现Ajax步骤创建 XMLHttpRequest 实例发出 HTTP 请求服务器返回 XML 格式的字符串JS 解析 XML,并更新局部页面不过随着历史进程的推进...:使用定时器的节流函数在第一次触发时不会执行,而是在 delay 秒之后才执行,当最后一次停止触发后,还会再执行一次函数function throttle(func, delay){ var timer...原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发。函数节流 :使得一定时间内只触发一次函数。

    41820

    链表排序总结(全)(C++)

    借助外部空间 既然数组排序简单,那可以借助数组进行排序: 把链表中的值一次遍历导入数组(时间复杂度O(n)) 对数组进行排序(可以选择各种算法,假设选择快排,时间复杂度O(nlogn)) 把排序后的元素依次放入链表的节点内...数组的merge函数我们已经很熟悉了: 需要一个辅助数组,大小与A[p…r]相同,双指针i,j分别指向两个待合并数组开头,假设为A[p…q],A[q+1,r]: 比较A[i]与A[j],将较小者放入辅助数组并移动指针指向下一个元素...那不符合要求并不代表归并排序不行,因为递归只是算法的特定实现方式而已,我们也可以使用迭代来实现链表的归并排序。...++q; } // 处理完之后beg指向的是两块中(已经排序好)元素最大的那个节点...首先想想我们为什么不用双指针法,因为双指针需要从后往前遍历啊,而单链表是没法从后往前遍历的。

    88110

    C语言详解(二) - 函数

    在使用某个函数时只需要知道它在哪个库函数中,然后在自己程序的开始添加相应的库函数即可。 .h结尾的文件是头文件。...void为返回类型意为函数没有返回值,可以在程序的末尾写上return;,或者不写return;,对这个函数无影响。 void*为返回值意为,函数返回一个不指向任何类型的为"空"的指针。...解决方法是在main函数之前进行相应的函数声明。 函数的声明一般放在程序的main函数之前,放在程序的开头部分,与函数定义不同,只需要由函数头和结尾分号组成。...函数声明时函数返回类型、函数名、函数的形参的数据类型是必需的,而形参中的变量名是可有可无的。...{ return 0; } } 运行结果: 6.4 递归与迭代 6.4.1 解释 循环是迭代的一种,但迭代不一定是循环 一些问题既可以用递归实现,也可以用循环实现。

    88010

    Python 实现反转、合并链表有啥用?

    反转链表先看在 Python 中实现反转链表,我们可以使用迭代和递归两种方法。下面分别给出这两种方法的详细实现。...迭代方法迭代方法的核心思想是遍历链表,在遍历过程中改变每个节点的指针方向,使其指向前一个节点。...在函数开始处就对链表是否为空进行了判断,如果其中一个链表为空,直接返回另一个链表。...,同上面代码在递归实现中,同样在函数开始就对链表为空的情况进行了处理,确保递归调用时不会出现访问空节点属性的错误。...最后反转链表和合并链表是链表操作中的基础且重要的算法,在很多实际应用场景中都有广泛的用途,就如 V 哥文章开头介绍的应用场景,如果不懂应用场景来学链表反转、合并,即使掌握了实现原理,也只是学会了招式,而不懂为什么学

    3700

    链表反转(递归和非递归方式)的正确姿势

    ; 而递归恰恰相反,首先一直迭代到链尾也就是递归基判断的准则,然后再逐层返回处理到开头。...总结来说,链表翻转操作的顺序对于迭代来说是从链头往链尾,而对于递归是从链尾往链头。 下面我会用详细的图文来剖析其中实现的细节。...1、非递归(迭代)方式 迭代的方式是从链头开始处理,如下图给定一个存放5个数的链表。...最后一步: 2、递归方式 我们再来看看递归实现链表翻转的实现,前面非递归方式是从前面数1开始往后依次处理,而递归方式则恰恰相反,它先循环找到最后面指向的数5,然后从5开始处理依次翻转整个链表。...首先指针H迭代到底如下图所示,并且设置一个新的指针作为翻转后的链表的头。由于整个链表翻转之后的头就是最后一个数,所以整个过程NewH指针一直指向存放5的地址空间。

    1.4K20

    C++【一棵红黑树封装 set 和 map】

    ,当整棵树都重构完成后,返回 根节点 注意: 拷贝构造函数中的参数需要使用 引用,避免 无穷递归问题 因为是三叉链结构,需要注意父指针的链接,判断不为空后直接链接即可 1.1.4、赋值重载 编译器生成的...树形 结构的容器在进行遍历时,默认按 中序遍历 的顺序进行迭代器移动,因为这样遍历 二叉搜索树 后,结果为 有序 清楚遍历路径后,就可以设计具体操作了 正向移动 operator++() 与 operator...的指向,这种方法在进行迭代器操作时比较友好,其他场景下就比较麻烦了,需要额外维护一个节点 如果按库中的 红黑树定义,rbegin() 就是 header 这个节点,因为它指向 最右节点 为了避免破坏前面的操作...,否则会导致这个错误无法出现 出现错误的原因 在 set 中,普通对象调用 begin() 或 end() 时,返回的是 普通迭代器,但此时的 iterator 是 const 迭代器,这就涉及一个类型转换问题了...:不能给常量对象赋值 注意: set 中的普通对象对应的也是 const 迭代器,但底层 红黑树 仍然是普通对象,返回的普通迭代器无法转换为 set 中的 const 迭代器,需要通过特殊构造函数解决

    34130

    二叉树八股文:递归改迭代通用模板

    首先我想说,递归改迭代从实用性的角度讲是没什么意义的,明明可以写递归解法,为什么非要改成迭代的方式?...通用性较差的意思是说,模板只是针对「用迭代的方式返回二叉树前/中/后序的遍历结果」这个问题,函数签名类似这样,返回一个TreeNode列表: List traverse(TreeNode...理论上,所有递归算法都可以利用栈改成迭代的形式,因为计算机本质上就是借助栈来迭代地执行递归函数的。 所以本文就来利用「栈」模拟函数递归的过程,总结一套二叉树通用迭代遍历框架。...假设计算机运行函数A,就会把A放到调用栈里面,如果A又调用了函数B,则把B压在A上面,如果B又调用了C,那就再把C压到B上面…… 当C执行结束后,C出栈,返回值传给B,B执行完后出栈,返回值传给A,最后等...其实很简单,我们只需要维护一个visited指针,指向「上一次遍历完成的根节点」,就可以判断p的左右子树遍历情况了 下面是迭代遍历二叉树的完整代码框架: // 模拟函数调用栈 private Stack

    41830

    删除链表中的重复节点.

    前言 在一个排序的链表中,存在重复的节点,如何删除链表中重复的节点并返回删除后的链表头指针?例如:1->2->3->3->4->4->5,处理后为: 1->2->5。...找到后,我们将其传入递归函数,并返回这个递归函数;如果当前节点pHead与它的下一个节点不等,我们就将其下一个节点的传入递归函数,修改pHead的下一个节点指向为此递归函数。...,寻找与当前节点不重复的节点;找到后继续调用递归函数,将不重复的节点作为参数传入,最后返回这个递归函数。...如果不相等,则修改pHead.next指向,使用递归函数求出当前不相等的节点,最后返回pHead。...// 本轮轮递归结束,返回最终的链表头节点 return pHead; } } 测试用例 我们将开头的例子代入上述代码,验证下能否正确执行。

    2.8K40

    2019年,Python工程师必考的6个面试题,Python面试题No5

    函数tuple(seq)可以把所有可迭代的(iterable)序列转换成一个tuple, 元素不变,排序也不变 list转为tuple: temp_list = [1,2,3,4,5] 将temp_list...进行强制转换:tuple(temp_list) 确定是否转换成功:print(type(temp_list)) 函数list(seq)可以把所有的序列和可迭代的对象转换成一个list,元素不变,排序也不变...它们两个都在re模块中 match()函数是在string的开始位置匹配,如果不匹配,则返回None; search()会扫描整个string查找匹配; match() >>> import re >>...,用来比较判断两个对象的value(值)是否相等 is也被叫做同一性运算符(对象标示符),这个运算符比较判断的是对象间的唯一身份标识,也就是id(内存中的地址)是否相同 我们在检查 a is b 的时候...这里还有一个问题,为什么 a 和 b 都是 "hello" 的时候,a is b 返回True,而 a 和 b都是 "hello world" 的时候,a is b 返回False呢?

    77320

    在Java中谈尾递归--尾递归和垃圾回收的比较(转载)

    比如如果有返回值的,你不能:乘个常数 return 3f(n);乘个n return n*f(n);甚至是 f(n)+f(n-1) 另外,使用return的尾递归还跟函数式编程有一点关系 编译器对尾递归的优化...,不仅不用释放上一个,连下一个新的都不用开,效率非常高(有人做实验,这个比递推比迭代都要效率高) 为什么写成尾递归的形式,编译器就能优化了?...因此,在栈中,只保存有基本类型的变量和对象引用。而引用所指向的对象保存在堆中。...每个对象包含一个计数器。当有新的指向该对象的引用时,计数器加 1。...那为什么呢,我看到有的说法是:JAVA编写组不实现尾递归优化是觉得麻烦又没有太大的必要,就懒得实现了(原话是:在日程表上,但是非常靠后),官方的建议是不使用递归,而是使用while循环,迭代,递推 转载

    1.4K50

    记录我的Python学习笔记

    def语句,依次写出函数名、括号、括号里的参数和冒号: ,然后,在缩进块中编写函数体,函数的返回值用return语句返回。...在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。...遗憾的是,大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把上面的fact(n)函数改成尾递归方式,也会导致栈溢出。...可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。...,返回一个函数,所以,原来的now()函数仍然存在,只是现在同名的now变量指向了新的函数,于是调用now()将执行新函数,即在log()函数中返回的wrapper()函数。

    77020

    前端高频面试题(三)(附答案)

    迭代查询与递归查询实际上,DNS解析是一个包含迭代查询和递归查询的过程。递归查询指的是查询请求发出后,域名服务器代为向下一级域名服务器发出请求,最后向用户返回查询的最终结果。...使用递归 查询,用户只需要发出一次查询请求。迭代查询指的是查询请求后,域名服务器返回单次查询的结果。下一级的查询由用户自己请求。使用迭代查询,用户需要发出 多次的查询请求。...一般我们向本地 DNS 服务器发送请求的方式就是递归查询,因为我们只需要发出一次请求,然后本地 DNS 服务器返回给我 们最终的请求结果。...而本地 DNS 服务器向其他域名服务器请求的过程是迭代查询的过程,因为每一次域名服务器只返回单次 查询的结果,下一级的查询由本地 DNS 服务器自己进行。...这个时候就可以通过 response 中的数据来对页面进行更新了。当对象的属性和监听函数设置完成后,最后调用 sent 方法来向服务器发起请求,可以传入参数作为发送的数据体。

    43420
    领券