二叉树有常见的三种遍历方式

  • 前序遍历: 根结点 -> 左子树 -> 右子树
  • 中序遍历: 左子树 -> 根结点 -> 右子树
  • 后序遍历: 左子树 -> 右子树 -> 根结点

要遍历的二叉树

  1. const root = {
  2. val: "A",
  3. left: {
  4. val: "B",
  5. left: {
  6. val: "D"
  7. },
  8. right: {
  9. val: "E"
  10. }
  11. },
  12. right: {
  13. val: "C",
  14. right: {
  15. val: "F"
  16. }
  17. }
  18. };

前序遍历

  1. // 所有遍历函数的入参都是树的根结点对象
  2. function preorder(root){
  3. // 递归边界,root 为空
  4. if(!root){
  5. return;
  6. }
  7. // 输出当前遍历的结点值
  8. console.log('当前遍历的结点值是:', root.val);
  9. preorder(root.left);
  10. preorder(root.right);
  11. }

中序遍历

递归边界照旧,唯一发生改变的是递归式里调用递归函数的顺序——左子树的访问会优先于根结点。我们参考先序遍历的分析思路,来写中序遍历的代码:

  1. // 所有遍历函数的入参都是树的根结点对象
  2. function preorder(root){
  3. // 递归边界,root 为空
  4. if(!root){
  5. return;
  6. }
  7. preorder(root.left);
  8. // 输出当前遍历的结点值
  9. console.log('当前遍历的结点值是:', root.val);
  10. preorder(root.right);
  11. }

后序遍历

递归边界照旧,唯一发生改变的仍然是是递归式里调用递归函数的顺序

  1. // 所有遍历函数的入参都是树的根结点对象
  2. function preorder(root){
  3. // 递归边界,root 为空
  4. if(!root){
  5. return;
  6. }
  7. preorder(root.left);
  8. preorder(root.right);
  9. // 输出当前遍历的结点值
  10. console.log('当前遍历的结点值是:', root.val);
  11. }

深度优先遍历(DFS)

深度优先主要是利用栈,先压右子树,再压左子树

  1. function DepthFirstSearch(biTree) {
  2. let stack = [];
  3. stack.push(biTree);
  4. while (stack.length != 0) {
  5. let node = stack.pop();
  6. console.log(node.data);
  7. if (node.rChild) {
  8. stack.push(node.rChild);
  9. }
  10. if (node.lChild) {
  11. stack.push(node.lChild);
  12. }
  13. }
  14. }

广度优先遍历(BFS)

广度优先主要利用队列,先入左子树,再入右子树

  1. function BreadthFirstSearch(biTree) {
  2. let queue = [];
  3. queue.push(biTree);
  4. while (queue.length != 0) {
  5. let node = queue.shift();
  6. console.log(node.data);
  7. if (node.lChild) {
  8. queue.push(node.lChild);
  9. }
  10. if (node.rChild) {
  11. queue.push(node.rChild);
  12. }
  13. }
  14. }