問題:
輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{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);