劍指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);

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章