代码随想录算法训练营第十四天 二叉树理论、递归遍历、迭代遍历和统一迭代

一、二叉树基础

1)满二叉树:如果一颗二叉树只有度为0结点和度为2的结点,并且度为0的结点在同一层

2)完全二叉树:除了最底层结点可能没填满之外,其余每层结点都达到最大值;并且最下面节点都集中在左边的位置

优先级队列是一棵完全二叉树

3)二叉搜索树:有数值的有序树;若左子树节点不空,则左子树上所有节点的值均小于它的根节点的值;若右子树节点不空,则右子树节点的值均大于它的根节点的值

4)平衡二叉树:一颗空树,或它的左右子树高度差的绝对值不超过1

二叉树的储存方式:链式储存或顺序储存

链式储存:用指针串联在一起;

顺序储存:用数组来储存。

二、二叉树的遍历方式:深度优先遍历和广度优先遍历;

深度优先遍历:先遍历到深层次的子节点,再往回找节点,分为前序遍历,中序遍历和后序遍历;

广度优先遍历:按每层进行遍历

三、二叉树节点代码定义的代码实现方式:

function TreeNode(val, left, right) {
  this.val = val === undefined ? 0 : val;
  this.left = left === undefined ? null : left;
  this.right = right === undefined ? null : right;
}

四、二叉树的递归遍历

递归遍历有三要素 1)确认入参和返回值 2)确认终止条件 3)确认单层递归的逻辑

这里实现深度优先遍历:前中后序遍历,其实是中间元素在中左右这三个元素递归中的顺序;

// 前序遍历
var preorderTraversal = function(root) {
   let res = []

   function dfs (cur) {
    if(cur === null) return
    res.push(cur.val)
    dfs(cur.left)
    dfs(cur.right)
   }

   dfs(root)
   return res 
};



//后序遍历
var postorderTraversal = function(root) {
    let res = []
    function dfs(cur) {
        if( cur === null) return //终止条件
        dfs(cur.left) 
        dfs(cur.right)
        res.push(cur.val)
    }

    dfs(root)
    return res // 入参和返回值
};

//中序遍历
var inorderTraversal = function(root) {
    let res = []
    function dfs(cur) {
        if(cur === null) return
        dfs(cur.left)
        res.push(cur.val)
        dfs(cur.right)
    }
    dfs(root)
    return res
};

五、二叉树的迭代遍历

二叉树的迭代遍历是用栈来实现的,将元素不断压入栈中,根据先入后出的原则来遍历数组;

前序遍历:按右左的顺序来入栈,那么出债的顺序就是中左右;后序遍历在前序遍历的基础上修改;即通过中右左的顺序来输出再反转; 中序遍历: 将左节点全部弹出栈,再将左节点以此取出,查看是否有右节点,如果有的话,将右节点下的左节点全部弹入栈;

// 前序遍历
var preorderTraversal = function(root) {
   let stack = [root]
   let result = []
   if(root === null) return result
   while(stack.length) {
    let cur = stack.pop()
    result.push(cur.val)
    cur.right && stack.push(cur.right)
    cur.left && stack.push(cur.left)
   }
   return result
};

// 后序遍历
var postorderTraversal = function(root) {
   if(root === null) return []
   let stack = [root]
   let result = []
   while(stack.length) {
    let cur = stack.pop()
    result.push(cur.val)
    cur.left && stack.push(cur.left)
    cur.right && stack.push(cur.right)
   }
   return result.reverse()
};

// 中序遍历
var inorderTraversal = function(root) {
    if(root === null) return []
    let result = [], stack = []
    while(root) {
        stack.push(root)
        root = root.left
    } 
    while(stack.length) {
        let cur = stack.pop()
        result.push(cur.val)
        if(cur.right) {
            let node = cur.right
            while(node) {
                stack.push(node)
                node = node.left
            }
        }
    }

    return result

};

可以将上述右节点的逻辑放入栈中;也可以在一个条件中同时判断:中序遍历的实现代码:

var inorderTraversal = function (root) {
    if (root === null) return []
    let result = [], stack = [];
    let cur = root
    while (stack.length || cur) {
        if (cur) {
            stack.push(cur)
            cur = cur.left
        } else {
            cur = stack.pop()
            result.push(cur.val)
            cur = cur.right
        }
    }
    return result
};

六、二叉树的统一迭代

统一迭代的核心是对处理过的节点后 push(null)入栈进行标记,如果 pop 出的是 null 节点,那么就要将前一个节点 pop 出并加入 result

实现中序遍历的过程,其他同理;

var inorderTraversal = function (root) {
    // 中序遍历输出顺序左中右,入栈顺序应该是右中左
  let result = [], stack = []
  if(root === null) return result;
  stack.push(root)
  while(stack.length) {
    let node = stack.pop()
    if(!node) {
        result.push(stack.pop().val)
        continue;
    }
    node.right && stack.push(node.right)
    stack.push(node)
    stack.push(null)
    node.left && stack.push(node.left)
  }
  return result
};

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值