资讯专栏INFORMATION COLUMN

JS递归与二叉树的遍历

church / 3530人阅读

摘要:貌似大部分语言中的递归都差不多,之所以在标题加是因为搜了下后感觉网上用来描述这概念的不多,简单地说递归就是函数调用自己的过程。

貌似大部分语言中的递归都差不多, 之所以在标题加JS是因为搜了下后感觉网上用js来描述这概念的不多, 简单地说递归就是函数调用自己的过程。下面的栗子可以很直观地展示递归的执行过程:

</>复制代码

  1. function rec(x){
  2. if(x!==1){
  3. console.log(x)
  4. rec(x-1)
  5. console.log(x)
  6. }
  7. }
  8. rec(5) //输出为5 4 3 2 2 3 4 5

由这个栗子?可知:在递归调用语句前的语句执行是正常顺序, 但是递归调用语句后的执行却是相反的也就是说在递归还没有完成时,函数的输出结果暂时被挂起,因为一般在计算机中,是以栈的形式来实现递归,这个过程如下:

</>复制代码

  1. 5 rec(4) //第一级
  2. 5 4 rec(3) //第二级
  3. 5 4 3 rec(2) //第三级
  4. 5 4 3 2 rec(1) //第四级
  5. console.log() 2 3 4 5 //以出栈形式输出结果

当递归完成时, 执行流开始处理上一级递归中的递归语句后面的语句, 在这里是输出当前变量console.log(x)

递归非常适用于相同函数不同参数的迭代循环。但是因为需要为每一级的递归开辟内存所以递归的开销相对来说蛮大的, 在很多编程的语言中,对于递归的开销问题有个TCO优化(Tail Call Optimization)戳这篇博客了解更多?[翻译] JS的递归与TCO尾调用优化

之所以想起码这篇博客,是因为最近看《算法与数据结构JavaScript描述》(请拉黑此书,bug极多,极不推荐)中使用递归遍历二叉树的算法挺绕的, 写篇博客厘清下。
这里直接借用原书的代码(有删改), 以二叉树的的中序遍历为例:

</>复制代码

  1. // 节点对象的构造函数
  2. function Node(data, left, right) {
  3. this.data = data;
  4. this.left = left;
  5. this.right = right;
  6. this.show = show;
  7. }
  8. function show() {
  9. return this.data;
  10. }
  11. //二叉树的构造函数
  12. function BST() {
  13. this.root = null;
  14. this.insert = insert;
  15. this.inOrder = inOrder;
  16. }
  17. //插入方法
  18. function insert(data) {
  19. var n = new Node(data, null, null);
  20. if (this.root == null) {
  21. this.root = n;
  22. }
  23. else {
  24. var current = this.root;
  25. var parent;
  26. while (true) {
  27. parent = current;
  28. if (data < current.data) {
  29. current = current.left;
  30. if (current == null) {
  31. parent.left = n;
  32. break;
  33. }
  34. }
  35. else {
  36. current = current.right;
  37. if (current == null) {
  38. parent.right = n;
  39. break;
  40. }
  41. }
  42. }
  43. }
  44. }
  45. //调用两次递归遍历二叉树
  46. function inOrder(node) {
  47. if (!(node == null)) {
  48. inOrder(node.left);
  49. console.log(node.show() )
  50. inOrder(node.right);
  51. }
  52. }
  53. //将以下数据导入二叉树
  54. nums.insert(23)
  55. nums.insert(45)
  56. nums.insert(16)
  57. nums.insert(37)
  58. nums.insert(3)
  59. nums.insert(99)
  60. nums.insert(22)
  61. //中序遍历二叉树
  62. inOrder(nums.root)
  63. /*
  64. 输出结果为:
  65. 3
  66. 16
  67. 22
  68. 23
  69. 37
  70. 45
  71. 99
  72. */

在inOrder函数中使用了两次递归,它的执行顺序是:沿左边找到最小值3,第一次递归完成, 之前被挂起的语句开始以出栈的形式执行,输出无子节点的节点3,然后回到上一级递归,输出其上一级递归中的节点16, 在节点16处, 存在子节点,于是执行向右递归,执行到无子节点的22,输出22后返回到节点16 , 执行流继续往回执行, 执行到根节点23,输出23后又插入一次向右递归,右递归到45, 存在左子节点,执行向左递归, 以此类推,就完成了这棵二叉树的中序遍历

附张遍历顺序示意图:

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/86226.html

相关文章

  • 学习JavaScript数据结构与算法(四):二叉搜索树

    摘要:像刚才的这幅图,就是二叉搜索树。而我们本文要学习的内容,就是如何写一个二叉搜索树。但在二叉搜索树中,我们把节点成为键,这是术语。前端路漫漫,且行且歌的前端乐园原文链接寒假前端学习学习数据结构与算法四二叉搜索树 本系列的第一篇文章: 学习JavaScript数据结构与算法(一),栈与队列第二篇文章:学习JavaScript数据结构与算法(二):链表第三篇文章:学习JavaScript数据...

    ingood 评论0 收藏0
  • 数据结构之二叉树(java版)

    摘要:二叉树是数据结构中很重要的结构类型,学习数据结构也是深入学习编程的必由之路,这里我们简单介绍下我对于二叉树的理解,水平有限,如有错误还请不吝赐教。 二叉树是数据结构中很重要的结构类型,学习数据结构也是深入学习编程的必由之路,这里我们简单介绍下我对于二叉树的理解,水平有限,如有错误还请不吝赐教。 首先照例定义一个二叉树的节点类 class Node { private int ...

    JayChen 评论0 收藏0
  • JavaScript二叉树及各种遍历算法详情

      在之前的文章中我们有讲过树的相关知识,例如,树的概念、深度优先遍历和广度优先遍历。这篇文章讲述了一个特殊的树——二叉树。 什么是二叉树  二叉树是每个节点最多只能有两个子节点的树,如下图所示:  一个二叉树具有以下几个特质:  要计算在每层有多少个点,可以依据公式2^(i-1)个(i是树的第几层);  如果这颗二叉树的深度为k,那二叉树最多有2^k-1个节点;  在一个非空的二叉树中,若使...

    3403771864 评论0 收藏0

发表评论

0条评论

church

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<