【上】二叉树

1.二叉树的定义

力扣上的定义:

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

用类定义:

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

2.二叉树的递归遍历

144. 二叉树的前序遍历

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var preorderTraversal = function(root) {
    let array = new Array();
    const preorder = function(root,array) {
        if(root === null) return;
        array.push(root.val);
        preorder(root.left, array);
        preorder(root.right, array);
    }
    preorder(root,array);
    return array;
};
//或
var preorderTraversal = function(root) {
    let array = new Array();
    const preorder = function(root) {
        if(root === null) return;
        array.push(root.val);
        preorder(root.left);
        preorder(root.right);
    }
    preorder(root);
    return array;
};

145. 二叉树的后序遍历

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var postorderTraversal = function(root) {
    let array = new Array();
    const postorder = function(root, array) {
        if(root === null) return;
        postorder(root.left, array);
        postorder(root.right, array);
        array.push(root.val);
    }
    postorder(root, array);
    return array;
};

94. 二叉树的中序遍历

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var inorderTraversal = function(root) {
    let array = new Array();
    const inorder = function(root, array) {
        if(root === null) return;
        inorder(root.left, array);
        array.push(root.val);
        inorder(root.right, array);
    }
    inorder(root, array);
    return array;
};

3.二叉树的非递归遍历

144. 二叉树的前序遍历
前序遍历是中左右,每次先处理的是中间节点,那么先将根节点放入栈中,然后将右孩子加入栈,再加入左孩子。

为什么要先加入 右孩子,再加入左孩子呢? 因为这样出栈的时候才是中左右的顺序。

动画如下:
在这里插入图片描述

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var preorderTraversal = function(root) {
    let stack = [];
    let result = [];
    let p=root;
    if(p!==null) stack.push(p);
    while(stack.length!==0) {
        p=stack.pop();
        result.push(p.val);
        if(p.right!==null)  stack.push(p.right);
        if(p.left!==null)  stack.push(p.left);
    }
    return result;
};

94. 二叉树的中序遍历

分析一下为什么刚刚写的前序遍历的代码,不能和中序遍历通用呢,因为前序遍历的顺序是中左右,先访问的元素是中间节点,要处理的元素也是中间节点,所以刚刚才能写出相对简洁的代码,因为要访问的元素和要处理的元素顺序是一致的,都是中间节点。

那么再看看中序遍历,中序遍历是左中右,先访问的是二叉树顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点(也就是在把节点的数值放进result数组中),这就造成了处理顺序和访问顺序是不一致的。

那么在使用迭代法写中序遍历,就需要借用指针的遍历来帮助访问节点,栈则用来处理节点上的元素。
在这里插入图片描述

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var inorderTraversal = function(root) {
    let stack = [];
    let result = [];
    let p=root;
    while(stack.length!==0 || p) {
        if(p) {
            stack.push(p);
            p=p.left;
        }
        else {
            p=stack.pop();
            result.push(p.val);
            p=p.right;
        }
    }
    return result;
};

145. 二叉树的后序遍历

再来看后序遍历,先序遍历是中左右,后续遍历是左右中,那么我们只需要调整一下先序遍历的代码顺序,就变成中右左的遍历顺序,然后在反转result数组,输出的结果顺序就是左右中了,如下图:
在这里插入图片描述

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var postorderTraversal = function(root) {
    let stack = [];
    let result = [];
    let p = root;
    if(p) stack.push(p);
    while(stack.length!==0) {
        p=stack.pop();
        result.push(p.val);
        if(p.left) stack.push(p.left);
        if(p.right) stack.push(p.right);
    }
    return result.reverse();
};

102. 二叉树的层序遍历

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var levelOrder = function(root) {
    let queue = [];
    let result = new Array();
    let queuesize=0;
    if(root) {
        queue.push(root);
        queuesize=1;
    }
    let p;
    while(queue.length!==0){
        let k=new Array();
        while(queuesize--) {
            p=queue.shift();
            k.push(p.val);
            if(p.left) {
                queue.push(p.left);
            }
            if(p.right) {
                queue.push(p.right);
            }
        }
        result.push(k);
        queuesize=queue.length;
    }
    return result;

};

226. 翻转二叉树
方法一:

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {TreeNode}
 */
var invertTree = function(root) {
    let array=[];
    if(root===null) return root;
    let p;
    array.push(root);
    while(array.length!==0) {
        p=array.pop();
        let q=p.left;
        p.left=p.right;
        p.right=q;
        if(p.left) {
            array.push(p.left);
        }
        if(p.right) {
            array.push(p.right);
        }
    }
    return root;
};

方法二:

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {TreeNode}
 */
var invertTree = function(root) {
    if(root===null) return root;
    const bianli = function(root) {
        let p=root.left;
        root.left=root.right;
        root.right=p;
        if(root.left) bianli(root.left);
        if(root.right) bianli(root.right);
    }
    bianli(root);
    return root;
};

101. 对称二叉树

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {boolean}
 */
var isSymmetric = function(root) {
    let p;
    let arr = [];
    if(root===null) return true;
    arr.push(root);
    let arrcount=1;
    while(arr.length!==0) {
        for(let i=0;i<arrcount;i++) {
            p=arr.shift();
            if(p) {
                arr.push(p.left);
                arr.push(p.right);
            }
        }
        arrcount=arr.length;
        // console.log(arr);
        for(let k=0;k<(arrcount>>1);k++) {
            if(arr[k]===null ||arr[arrcount-1-k]===null) {
                if((arr[k]===null &&arr[arrcount-1-k]!==null)||(arr[arrcount-1-k]===null && arr[k]!==null))
                return false;
            }
            else if(arr[k].val!==arr[arrcount-1-k].val) {
                return false;
            }
        }
    }
    return true;
};

100. 相同的树

照上一道改的。

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} p
 * @param {TreeNode} q
 * @return {boolean}
 */
var isSameTree = function(p, q) {
    let arr = [];
    arr.push(p);
    arr.push(q);
    let k;
    let arrcount=2;
    while(arr.length!==0) {
        for(let k=0;k<(arrcount>>1);k++) {
            if(arr[k]===null ||arr[(arrcount>>1)+k]===null) {
                if((arr[k]===null &&arr[(arrcount>>1)+k]!==null)||(arr[(arrcount>>1)+k]===null && arr[k]!==null))
                return false;
            }
            else if(arr[k].val!==arr[(arrcount>>1)+k].val) {
                return false;
            }
        }
        for(let i=0;i<arrcount;i++) {
            k=arr.shift();
            if(k) {
                arr.push(k.left);
                arr.push(k.right);
            }
        }
        arrcount=arr.length;
    }
    return true;
};

572. 另一棵树的子树

也是照上一道改的。

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @param {TreeNode} subRoot
 * @return {boolean}
 */
var isSubtree = function(root, subRoot) {
    let a = [];
    const bianli = function(p) {
        if(p.val===subRoot.val&&p!==null&&subRoot!==null) {
            a.push(p);
        }
        if(p.left) bianli(p.left);
        if(p.right) bianli(p.right);
    }
    const isSameTree = function(p, q) {
    let arr = [];
    arr.push(p);
    arr.push(q);
    let k;
    let arrcount=2;
    while(arr.length!==0) {
        for(let k=0;k<(arrcount>>1);k++) {
            if(arr[k]===null ||arr[(arrcount>>1)+k]===null) {
                if((arr[k]===null &&arr[(arrcount>>1)+k]!==null)||(arr[(arrcount>>1)+k]===null && arr[k]!==null)){
                      return false;
                }
               
            }
            else if(arr[k].val!==arr[(arrcount>>1)+k].val) {
                 return false;
            }
        }
        for(let i=0;i<arrcount;i++) {
            k=arr.shift();
            if(k) {
                arr.push(k.left);
                arr.push(k.right);
            }
        }
        arrcount=arr.length;
    }
    return true;
};
    bianli(root);
    for(let i of a) {
        if(isSameTree(i,subRoot)) {
            return true;
        }
    }
    return false;
    
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值