我有以下树,可以将其称为Tree One
。
1
/ \
/ \
2 3
/
/
4
现在我想用2替换根节点。然后上面的树将变成这样的东西。让我们称之为Tree Two
2
/ \
/ \
4 1
\
\
3
如何按上述方法为数组输入实现上述内容?
更新
我已经尝试过使用Linkedlist。但是,它低于上述输入(即数组)。
function replaceRootNode(tree, x) {
var y = x.left;
x.left = y.right;
if (y.right) {
y.right.parent = x;
}
y.parent = x.parent;
if (!x.parent) {
tree.root = y;
} else {
if (x === x.parent.left) {
x.parent.left = y;
} else {
x.parent.right = y;
}
}
y.right = x;
x.parent = y;
}
更新2
我使用likeslist的上述解决方案基于Splay Tree。但我需要它来进行数组输入。
答案 0 :(得分:2)
您的定义不完整,因此我添加了以下定义:
我所做的是首先将其转换为结构化的json并在那里进行操作。我使用lodash来使代码更清晰。
请注意,我的代码具有从您的格式转换为json并返回的功能。当您查看代码时,请确保打开控制台,此外,您还有一些更复杂的树木样本。注释掉,你也可以尝试一下。
// var tree = [1, [2, [4], [5]], [3]];
var tree = [1, [2, [4]],
[3]
];
// var tree = [1, [2, [4, [5, [6,[7]]]]], [3]];
var zipTree = _.partial(_.zipObject, ['root', 'left', 'right']);
var toTree = _.flow(zipTree, _.partial(_.pick, _, _.identity));
function toTreeRecurse(data) {
var result = toTree(data);
if (_.isArray(result.left)) {
result.left = toTreeRecurse(result.left);
}
if (_.isArray(result.right)) {
result.right = toTreeRecurse(result.right);
}
return (result);
}
function toArrayRecurse(tree) {
var result = [tree.root];
if (tree.left) {
result.push(toArrayRecurse(tree.left));
}
if (tree.right) {
result.push(toArrayRecurse(tree.right));
}
return (result);
}
function findValueParent(tree, value) {
if (!tree) {
return (null);
}
var result;
if (_.get(tree, 'left.root') === value) {
return (tree);
} else if (_.get(tree, 'right.root') === value) {
return (tree);
} else if (result = findValueParent(tree.left, value)) {
return (result);
} else if (result = findValueParent(tree.right, value)) {
return (result);
} else {
return (null);
}
}
function setRoot(tree, value) {
var rootParent = findValueParent(tree, value);
var newRoot;
if (rootParent) {
var fromSide, toSide;
if (findValueParent(tree.left, value) || (_.get(tree, 'left.root') === value)) {
fromSide = 'left';
toSide = 'right';
} else if (findValueParent(tree.right, value) || (_.get(tree, 'right.root') === value)) {
fromSide = 'right';
toSide = 'left';
}
newRoot = _.get(rootParent, fromSide);
if (_.get(newRoot, toSide)) {
_.set(rootParent, fromSide, _.get(newRoot, toSide));
} else {
delete rootParent[fromSide];
}
_.set(newRoot, toSide, tree);
return (newRoot);
} else {
console.log('value does not exist');
return (null);
}
}
console.log('original: ', JSON.stringify(tree));
console.log('original as json tree: ', JSON.stringify(toTreeRecurse(tree)));
console.log('setting root to 2: ', JSON.stringify(toArrayRecurse(setRoot(toTreeRecurse(tree), 2))));
console.log('setting root to 4: ', JSON.stringify(toArrayRecurse(setRoot(toTreeRecurse(tree), 4))));

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script>
<div>Demo, make sure you open the devtools to see the console print</div>
&#13;
答案 1 :(得分:0)
我不相信有一种方法可以专门使用数组。链接列表绝对更适合您的问题。
因此,如果您只接受数组作为输入,则可以执行以下操作:
replaceRootNode
功能替换节点。这是我转换数组的代码示例:
var arr = [2, [1, [3]], [4]];
var tree = {
root: null
};
arrayToList(arr, tree);
console.log(tree);
function arrayToList(array, tree){
var node = {
data: array[0],
left: null,
right: null
};
if (tree.root == null) {
tree.root = node;
}
if(array[1] instanceof Array) {
node.left = arrayToList(array[1], tree);
} else {
node.left = array[1];
}
if(array[2] instanceof Array) {
node.right = arrayToList(array[2], tree);
} else {
node.right = array[2];
}
return node;
}
Fiddle(在控制台输出)。
我正在使用Postorder
遍历树,Left
&gt; Right
&gt; Root
。因此,与上面的示例相比,它将输出镜像的树。
如果您希望首先访问正确的节点,则可以执行以下简单编辑:Fiddle。虽然你通常总是在Right之前访问Left。
无论如何,你可以用你的功能替换你的根节点(没有尝试过)。
然后,您可以执行类似的功能将重新排列的树转换回数组。