本文主要包括樹相關(guān)的算法缩膝,二叉樹結(jié)點基本結(jié)構(gòu)如下
function TreeNode(x) {
this.val = x;
this.left = null;
this.right = null;
}
本文還會繼續(xù)更新。
二叉樹的深度
function depth(pRoot){
if(!pRoot){
return 0;
}
var depth = 0;
var currDepth = 0;
dfs(pRoot);
return depth;
function dfs(node){
if(!node){
depth = depth > currDepth ? depth : currDepth;
return;
}
currDepth++;
dfs(node.left);
dfs(node.right);
currDepth--;
}
}
二叉樹的前序遍歷
function preOrder(root){
if(!root)
return [];
var result = [];
_preOrder(root);
return result;
function _preOrder(node){
result.push(node.val);
node.left && _preOrder(node.left);
node.right && _preOrder(node.right);
}
}
二叉樹的中序遍歷
function inOrder(root){
if(!root)
return [];
var result = [];
_inOrder(root);
return result;
function _inOrder(node){
node.left && _inOrder(node.left);
result.push(node.val);
node.right && _inOrder(node.right);
}
}
二叉樹的后序遍歷
function postOrder(root){
if(!root)
return [];
var result = [];
_postOrder(root);
return result;
function _postOrder(node){
node.left && _postOrder(node.left);
node.right && _postOrder(node.right);
result.push(node.val);
}
}
二叉樹的層序遍歷
/* function TreeNode(x) {
this.val = x;
this.left = null;
this.right = null;
} */
function printFromTopToBottom(root){
if (!root) {
return [];
}
var queue = [];
queue.push(root);
var result = [];
while (queue.length) {
var temp = queue.shift();
result.push(temp.val);
if (temp.left) {
queue.push(temp.left);
}
if (temp.right) {
queue.push(temp.right);
}
}
return result;
}
根據(jù)層序遍歷建立二叉樹
//層序的空節(jié)點使用 null
function Tree(arr, node, num){ //也可以通過 new 調(diào)用
if(!arr || arr.length === 0){
return new TreeNode(null);
}
num = num || 1;
node = node || new TreeNode(arr[num - 1]);
var curr = node;
if(num * 2 - 1 < arr.length && arr[num * 2 - 1] != null){
curr.left = new TreeNode(arr[num * 2 - 1]);
Tree(arr, curr.left, num * 2);
}
if(num * 2 < arr.length && arr[num * 2] != null){
curr.right = new TreeNode(arr[num * 2]);
Tree(arr, curr.right, num * 2 + 1);
}
return node;
}
根據(jù)中序遍歷和前序遍歷重建二叉樹
function reBuildTree_pi(pre, vin){
if(pre.length == 0 || vin.length == 0 || pre.length !== vin.length){
return null;
};
var index = vin.indexOf(pre[0]);
var left = vin.slice(0,index);
var right = vin.slice(index+1);
var node = new TreeNode(vin[index]);
node.left = reBuildTree_pi(pre.slice(1,index+1),left);
node.right = reBuildTree_pi(pre.slice(index+1),right);
return node;
}
根據(jù)中序遍歷和后序遍歷重建二叉樹
function reBuildTree_ip(vin, post){
if(post.length == 0 || vin.length == 0 || vin.length !== post.length){
return null;
};
var index = vin.indexOf(post.pop());
var left = vin.slice(0,index);
var right = vin.slice(index+1);
var node = new TreeNode(vin[index]);
node.left = reBuildTree_ip(left, post.slice(0,index));
node.right = reBuildTree_ip(right, post.slice(index));
return node;
}
求二叉樹的最遠節(jié)點距離
function maxDistance(root){ //root 二叉樹根節(jié)點丽涩;
if(root === null) return 0;
var max = 0;
_maxDistance(root, max);
return max; //函數(shù)返回最大值
function _maxDistance(curr){ //curr: 當前節(jié)點;max: 最大值;
if(curr === null) return 0;
var leftDepth = curr.left ? _maxDistance(curr.left) : 0;
var rightDepth = curr.right ? _maxDistance(curr.right) : 0;
if(leftDepth + rightDepth > max) max = leftDepth + rightDepth;
return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;
}
}
二叉樹的鏡像
function mirror(root){
if(!root){
return null;
}
var temp = root.left;
root.left = root.right;
root.right = temp;
if(root.left){
Mirror(root.left);
}
if(root.right){
Mirror(root.right);
}
}
二叉搜索樹轉(zhuǎn)雙向鏈表
將左子樹構(gòu)成雙向鏈表矢渊,返回的是左子樹的尾結(jié)點继准,將其連接到root的左邊;
將右子樹構(gòu)成雙向鏈表矮男,將其追加到root結(jié)點之后移必,并返回尾結(jié)點;
向左遍歷返回的鏈表至頭結(jié)點處毡鉴,即為所求雙向鏈表的首結(jié)點崔泵。
function convert(pRootOfTree){
if(!pRootOfTree) {
return null;
}
var lastNode = null;
lastNode = ConvertNode(pRootOfTree);
var head = lastNode;
while(head && head.left) {
head = head.left;
}
return head;
function ConvertNode(node){
if(!node){
return;
}
if(node.left) {
lastNode = ConvertNode(node.left);
}
node.left = lastNode;
if(lastNode){
lastNode.right = node;
}
lastNode = node;
if(node.right){
lastNode = ConvertNode(node.right);
}
return lastNode;
}
}
判斷是否平衡二叉樹
function isBalancedTree(pRoot){
if(!pRoot){
return true;
}
var left = TreeDepth(pRoot.left);
var right = TreeDepth(pRoot.right);
var diff = left - right;
if(diff > 1 || diff < -1)
return false;
return IsBalanced_Solution(pRoot.left) && IsBalanced_Solution(pRoot.right);
function TreeDepth(pRoot){
if(!pRoot){
return 0;
}
var depth = 0;
var currDepth = 0;
dfs(pRoot);
return depth;
function dfs(node){
if(!node){
depth = depth > currDepth ? depth : currDepth;
return;
}
currDepth++;
dfs(node.left);
dfs(node.right);
currDepth--;
}
}
}
判斷是否對稱二叉樹
function isSymmetrical(pRoot){
if(!pRoot){
return true;
}
return symmetrical(pRoot, pRoot);
function symmetrical(node1,node2){
if(!node1 && !node2)
return true;
if(!node1 || !node2)
return false;
if(node1.val != node2.val)
return false;
return symmetrical(node1.left, node2.right) && symmetrical(node1.right, node2.left);
}
}
判斷是否完全二叉樹
function isPrefectTree(root){
if(!root)
return true;
var que = [];
que.push(root);
var curr;
while(curr = que.shift()){
que.push(curr.left);
que.push(curr.right);
}
while (que.length > 0){
if (que.pop())
return false;
}
return true;
}
判斷是否滿二叉樹
function isFullTree(root){
if(!root)
return true;
var que = [];
que.push(root);
var curr;
var nodeNum = 0;
while(curr = que.shift()){
que.push(curr.left);
que.push(curr.right);
nodeNum++;
}
while (que.length > 0){
if (que.pop())
return false;
}
return (nodeNum & (nodeNum + 1)) === 0;
}