问题:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{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);