剑指offer-04前序中序构建二叉树

问题:

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

思路:

二叉树前序遍历第一个点为根节点,中序遍历顺序为先左子树然后根节点最后右子树。所以先通过前序遍历找出根节点,然后将中序遍历分为左右子树两组,最后对于每个子树依次递归调用。

/*以后这个就是树的基本结构,最快做题*/
function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
}


/*前序和中序重构二叉树*/
function reConstructBinaryTree1(pre,vin) {
    if(pre.length===0 || vin.length===0) return null;
    //构建树就是构建根节点,indexof
    var tree=new TreeNode(pre[0]),index=vin.indexOf(pre[0]);
    /*递归调用 slice*/
    tree.left=reConstructBinaryTree1(pre.slice(1,index+1),vin.slice(0,index));
    tree.right=reConstructBinaryTree1(pre.slice(index+1),vin.slice(index+1));
    return tree;
}

//中序+后序:中序遍历序列和后序遍历序列可以确定唯一的二叉树
function reConstructBinaryTree2(pos, vin)
{
    if(pos.length===0 || vin.length===0 ) return  null;
    //创建根节点,根节点是后序遍历的最后一个数
    var tree = new TreeNode(  pos[pos.length-1]);
    //找到中序遍历根节点所在位置
    var index = vin.indexOf(root);
    //对于中序遍历,根节点左边的节点即左子树,根节点右边的节点即右子树
    tree.left=reConstructBinaryTree2(pos.slice(0,index),vin.slice(0,index))
    tree.right=reConstructBinaryTree2(pos.slice(index,pos.length-1),vin.slice(index+1))
    return tree;
}


/*前序遍历*/
/*思路:首先写函数,传参,然后把结果放到数组中,因为传进来的其实就是根节点,首先判断是否为空*/
/*非空的话把根节点的值放到数组。因为是先序,所以先放,然后递归左子树,右子树*/
function preOrder(tree) {
    var result=[];
    const preorder=(treenode)=>{
        if(treenode!==null){
            result.push(treenode.val);
            preorder(treenode.left);
            preorder(treenode.right);
        }
    };
    preorder(tree);
    return result;
}

/*中序遍历*/
function vinOrder(tree) {
    let result=[];
    const vinorder=(treenode)=>{
        if(treenode!==null){
            vinorder(treenode.left);
            result.push(treenode.val);
            vinorder(treenode.right);
        }

    };
    vinorder(tree);
    return result;

}

/*后续遍历*/
function postOrder(tree) {
    var result=[];
    const postorder=(treenode)=>{
        if(treenode!==null){
            postorder(treenode.left);
            postorder(treenode.right);
            result.push(treenode.val);
        }

    };
    postorder(tree);
    return result;
}




/*测试*/
var pre=[11,7,5,3,9,8,10,13,12,14,20,18,25];
var vin=[3,5,7,8,9,10,11,12,13,14,18,20,25];
var post=[3,5,8,10,9,7,12,18,25,20,14,13,11];

tree1=reConstructBinaryTree1(pre,vin);
tree2=reConstructBinaryTree2(post,vin);
console.log(tree2);
console.log(preOrder(tree2));
console.log(vinOrder(tree2));
console.log(postOrder(tree2));

注意点:

indexOf()函数根据给定元素,判断在数组中的位置,如果数组中没有,那么返回-1;

slice(n,m) 切分数组n表示开始位置,m表示结束位置,并不包含m位置上的值。不改变原来数组。

 

以下代码是实现二叉搜索树的数据结构,可以参考

/*实现二叉树的数据结构*/
//定义的构建二叉树,前序,后序,中序,查找最大,最小,特定没有问题,删除有小问题,小问题是删除节点后的二叉树不能调用前序等方法
/*删除节点后的二叉树,虽然可以中序等遍历,但是遍历的节点会有重复*/


//定义节点
class Node {
    constructor(data){
        this.root=this;
        this.data=data;
        this.left=null;
        this.right=null;
    }
}
//创建二叉搜索树BST
class BinarySearchTree {
    constructor() {
        this.root=null;
    }
//   插入节点
    insert(data){
        const newNode=new Node(data);
        const insertNode=(node,newNode)=>{
            if(newNode.data<node.data){
                if(node.left===null){
                    node.left=newNode;
                }else{
                    insertNode(node.left,newNode);
                }
            }  else {
                if(node.right===null){
                    node.right=newNode;
                }else{
                    insertNode(node.right,newNode);
                }
            }
        };
        if(!this.root){
            this.root=newNode;
        }else{
            insertNode(this.root,newNode);
        }
}

//中序遍历
    inOrder(){
        let backs=[];
        const inOrderNode=(node,callback)=>{
            if(node!==null){
                inOrderNode(node.left,callback);
                backs.push(callback(node.data));
                inOrderNode(node.right,callback)
            }
        };
        inOrderNode(this.root,callback);
        function callback(v) {
            return v;
        }
        return backs;
    }
//    前序遍历
    preOrder(){
        let backs=[];
        const preOrderNode=(node,callback)=>{
            if(node!==null){
                backs.push(callback(node.data));
                preOrderNode(node.left,callback);
                preOrderNode(node.right,callback)
            }
        };
        preOrderNode(this.root,callback);
        function callback(v) {
            return v;
        }
        return backs;
    }
//    后序遍历
    postOrder(){
        let backs=[];
        const postOrderNode=(node,callback)=>{
            if(node!==null){
                postOrderNode(node.left,callback);
                postOrderNode(node.right,callback);
                backs.push(callback(node.data));

            }
        };
        postOrderNode(this.root,callback);
        function callback(v) {
            return v;
        }
        return backs;
    }
//    查找最小值
    getMin(node){
        const minNode=node=>{
            return node ? (node.left? minNode(node.left):node):null;
        };
        return  minNode(node || this.root)
    }
//   查找最大值
    getMax(node){
        const maxNode=node=>{
            return node ? (node.right? maxNode(node.right):node):null;
        };
        return maxNode(this.node || this.root)
    }
//    查找特定值
    find(data){
        const findNode=(node,data)=>{
            if(node===null) return false;
            if(node.data===data) return node;
            return findNode((data<node.data)?node.left:node.right,data)
        }
        return findNode(this.root,data);
    }
//    删除节点
    remove(data){
        const removeNode=(node,data)=> {
            if (node === null) return null;
            if (node.data === data) {
                if (node.left === null && node.right === null) return null;
                if (node.left === null) return node.right;
                if (node.right === null) return node.left;
                if (node.left !== null && node.right !== null) {
                    let _node = this.getMin(node.right);
                    node.data = _node.data;
                    node.right = removeNode(node.right, data);
                    return node;
                }
            }else if (data < node.data) {
                    node.left = removeNode(node.left, data);
                    return node;
                } else {
                    node.right = removeNode(node.right, data);
                    return node;
                }
            }
            return removeNode(this.root, data);
        }
}
//创建BST
const tree =new BinarySearchTree();
tree.insert(11);
tree.insert(7);
tree.insert(5);
tree.insert(3);
tree.insert(9);
tree.insert(8);
tree.insert(10);
tree.insert(13);
tree.insert(12);
tree.insert(14);
tree.insert(20);
tree.insert(18);
tree.insert(25);
// // console.log(tree);
// // console.log(tree.root);
// console.log(tree.preOrder());
// console.log(tree.inOrder());
// console.log(tree.postOrder());
// console.log(tree.getMin());
// console.log(tree.getMax());
// console.log(tree.find(2));
// console.log(tree.find(11));
// //删除节点,返回新的二叉树,不改变原来的二叉树
// console.log('..........1.............')
// console.log(tree)
// // console.log(tree.remove(11));
// a=tree.remove(11);
// console.log('..........2.............');
// console.log(tree);
// console.log('.............3..........');
// console.log(tree.inOrder());
// console.log(a);
// console.log('..........4.............')
// console.log(a.root);
// console.log('.......................')
// console.log(tree);
// console.log('.......................')



/*根据前序和中序构建二叉树*/
function reConstructBinaryTree(pre,vin) {
    if(pre.length==0 ) return null;
    var index=vin.indexOf(pre[0]);
    var left=vin.slice(0,index);
    var right=vin.slice(index+1);
    return {
        var:pre[0],
        left:reConstructBinaryTree(pre.slice(1,index+1),left),
        right:reConstructBinaryTree((pre.slice(index+1),right))
    };
}

var pre=[11,7,5,3,9,8,10,13,12,14,18,20,25];
var vin=[3,5,7,8,9,10,11,12,13,14,18,20,25];
var result=reConstructBinaryTree(pre,vin);
console.log(result);

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值