|
|
@ -1,125 +1,263 @@ |
|
|
|
(function () { |
|
|
|
import { |
|
|
|
BI.Tree = function () { |
|
|
|
isObject, |
|
|
|
this.root = new BI.Node(BI.UUID()); |
|
|
|
UUID, |
|
|
|
}; |
|
|
|
extend, |
|
|
|
|
|
|
|
isEmpty, |
|
|
|
BI.Tree.prototype = { |
|
|
|
isArray, |
|
|
|
constructor: BI.Tree, |
|
|
|
first, |
|
|
|
addNode: function (node, newNode, index) { |
|
|
|
last, |
|
|
|
if (BI.isNull(newNode)) { |
|
|
|
findIndex, |
|
|
|
|
|
|
|
isUndefined, |
|
|
|
|
|
|
|
isNull, |
|
|
|
|
|
|
|
each, |
|
|
|
|
|
|
|
deepClone, |
|
|
|
|
|
|
|
isEqual, some, every, clone |
|
|
|
|
|
|
|
} from "../2.base"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export class Node { |
|
|
|
|
|
|
|
constructor(id) { |
|
|
|
|
|
|
|
if (isObject(id)) { |
|
|
|
|
|
|
|
extend(this, id); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
this.id = id; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
this.clear(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set(key, value) { |
|
|
|
|
|
|
|
if (isObject(key)) { |
|
|
|
|
|
|
|
extend(this, key); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
this[key] = value; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
get(key) { |
|
|
|
|
|
|
|
return this[key]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
isLeaf() { |
|
|
|
|
|
|
|
return isEmpty(this.children); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getChildren() { |
|
|
|
|
|
|
|
return this.children; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getChildrenLength() { |
|
|
|
|
|
|
|
return this.children.length; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getFirstChild() { |
|
|
|
|
|
|
|
return first(this.children); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getLastChild() { |
|
|
|
|
|
|
|
return last(this.children); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setLeft(left) { |
|
|
|
|
|
|
|
this.left = left; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getLeft() { |
|
|
|
|
|
|
|
return this.left; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setRight(right) { |
|
|
|
|
|
|
|
this.right = right; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getRight() { |
|
|
|
|
|
|
|
return this.right; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setParent(parent) { |
|
|
|
|
|
|
|
this.parent = parent; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getParent() { |
|
|
|
|
|
|
|
return this.parent; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getChild(index) { |
|
|
|
|
|
|
|
return this.children[index]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getChildIndex(id) { |
|
|
|
|
|
|
|
return findIndex(this.children, function (i, ch) { |
|
|
|
|
|
|
|
return ch.get("id") === id; |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
removeChild(id) { |
|
|
|
|
|
|
|
this.removeChildByIndex(this.getChildIndex(id)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
removeChildByIndex(index) { |
|
|
|
|
|
|
|
const before = this.getChild(index - 1); |
|
|
|
|
|
|
|
const behind = this.getChild(index + 1); |
|
|
|
|
|
|
|
if (before != null) { |
|
|
|
|
|
|
|
before.setRight(behind || null); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (behind != null) { |
|
|
|
|
|
|
|
behind.setLeft(before || null); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
this.children.splice(index, 1); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
removeAllChilds() { |
|
|
|
|
|
|
|
this.children = []; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
addChild(child, index) { |
|
|
|
|
|
|
|
let cur = null; |
|
|
|
|
|
|
|
if (isUndefined(index)) { |
|
|
|
|
|
|
|
cur = this.children.length - 1; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
cur = index - 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
child.setParent(this); |
|
|
|
|
|
|
|
if (cur >= 0) { |
|
|
|
|
|
|
|
this.getChild(cur) && this.getChild(cur).setRight(child); |
|
|
|
|
|
|
|
child.setLeft(this.getChild(cur)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (isUndefined(index)) { |
|
|
|
|
|
|
|
this.children.push(child); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
this.children.splice(index, 0, child); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
equals(obj) { |
|
|
|
|
|
|
|
return this === obj || this.id === obj.id; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
clear() { |
|
|
|
|
|
|
|
this.parent = null; |
|
|
|
|
|
|
|
this.left = null; |
|
|
|
|
|
|
|
this.right = null; |
|
|
|
|
|
|
|
this.children = []; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export class Tree { |
|
|
|
|
|
|
|
constructor() { |
|
|
|
|
|
|
|
this.root = new Node(UUID()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
addNode(node, newNode, index) { |
|
|
|
|
|
|
|
if (isNull(newNode)) { |
|
|
|
this.root.addChild(node, index); |
|
|
|
this.root.addChild(node, index); |
|
|
|
} else if (BI.isNull(node)) { |
|
|
|
} else if (isNull(node)) { |
|
|
|
this.root.addChild(newNode, index); |
|
|
|
this.root.addChild(newNode, index); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
node.addChild(newNode, index); |
|
|
|
node.addChild(newNode, index); |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
isRoot: function (node) { |
|
|
|
isRoot(node) { |
|
|
|
return node === this.root; |
|
|
|
return node === this.root; |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
getRoot: function () { |
|
|
|
getRoot() { |
|
|
|
return this.root; |
|
|
|
return this.root; |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
clear: function () { |
|
|
|
clear() { |
|
|
|
this.root.clear(); |
|
|
|
this.root.clear(); |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
initTree: function (nodes) { |
|
|
|
initTree(nodes) { |
|
|
|
var self = this; |
|
|
|
|
|
|
|
this.clear(); |
|
|
|
this.clear(); |
|
|
|
var queue = []; |
|
|
|
const queue = []; |
|
|
|
BI.each(nodes, function (i, node) { |
|
|
|
each(nodes, (i, node) => { |
|
|
|
var n = new BI.Node(node); |
|
|
|
const n = new Node(node); |
|
|
|
n.set("data", node); |
|
|
|
n.set("data", node); |
|
|
|
self.addNode(n); |
|
|
|
this.addNode(n); |
|
|
|
queue.push(n); |
|
|
|
queue.push(n); |
|
|
|
}); |
|
|
|
}); |
|
|
|
while (!BI.isEmpty(queue)) { |
|
|
|
while (!isEmpty(queue)) { |
|
|
|
var parent = queue.shift(); |
|
|
|
const parent = queue.shift(); |
|
|
|
var node = parent.get("data"); |
|
|
|
const node = parent.get("data"); |
|
|
|
BI.each(node.children, function (i, child) { |
|
|
|
each(node.children, (i, child) => { |
|
|
|
var n = new BI.Node(child); |
|
|
|
const n = new Node(child); |
|
|
|
n.set("data", child); |
|
|
|
n.set("data", child); |
|
|
|
queue.push(n); |
|
|
|
queue.push(n); |
|
|
|
self.addNode(parent, n); |
|
|
|
this.addNode(parent, n); |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
_toJSON: function (node) { |
|
|
|
_toJSON(node) { |
|
|
|
var self = this; |
|
|
|
const children = []; |
|
|
|
var children = []; |
|
|
|
each(node.getChildren(), (i, child) => { |
|
|
|
BI.each(node.getChildren(), function (i, child) { |
|
|
|
children.push(this._toJSON(child)); |
|
|
|
children.push(self._toJSON(child)); |
|
|
|
|
|
|
|
}); |
|
|
|
}); |
|
|
|
return BI.extend({ |
|
|
|
return extend({ |
|
|
|
id: node.id |
|
|
|
id: node.id, |
|
|
|
}, BI.deepClone(node.get("data")), (children.length > 0 ? { |
|
|
|
}, deepClone(node.get("data")), (children.length > 0 ? { |
|
|
|
children: children |
|
|
|
children: children, |
|
|
|
} : {})); |
|
|
|
} : {})); |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
toJSON: function (node) { |
|
|
|
toJSON(node) { |
|
|
|
var self = this, result = []; |
|
|
|
const result = []; |
|
|
|
BI.each((node || this.root).getChildren(), function (i, child) { |
|
|
|
each((node || this.root).getChildren(), (i, child) => { |
|
|
|
result.push(self._toJSON(child)); |
|
|
|
result.push(this._toJSON(child)); |
|
|
|
}); |
|
|
|
}); |
|
|
|
return result; |
|
|
|
return result; |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
_toJSONWithNode: function (node) { |
|
|
|
_toJSONWithNode(node) { |
|
|
|
var self = this; |
|
|
|
const children = []; |
|
|
|
var children = []; |
|
|
|
each(node.getChildren(), (i, child) => { |
|
|
|
BI.each(node.getChildren(), function (i, child) { |
|
|
|
children.push(this._toJSONWithNode(child)); |
|
|
|
children.push(self._toJSONWithNode(child)); |
|
|
|
|
|
|
|
}); |
|
|
|
}); |
|
|
|
return BI.extend({ |
|
|
|
return extend({ |
|
|
|
id: node.id |
|
|
|
id: node.id, |
|
|
|
}, BI.deepClone(node.get("data")), { |
|
|
|
}, deepClone(node.get("data")), { |
|
|
|
node: node |
|
|
|
node: node, |
|
|
|
}, (children.length > 0 ? { |
|
|
|
}, (children.length > 0 ? { |
|
|
|
children: children |
|
|
|
children: children, |
|
|
|
} : {})); |
|
|
|
} : {})); |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
toJSONWithNode: function (node) { |
|
|
|
toJSONWithNode(node) { |
|
|
|
var self = this, result = []; |
|
|
|
const result = []; |
|
|
|
BI.each((node || this.root).getChildren(), function (i, child) { |
|
|
|
each((node || this.root).getChildren(), (i, child) => { |
|
|
|
result.push(self._toJSONWithNode(child)); |
|
|
|
result.push(this._toJSONWithNode(child)); |
|
|
|
}); |
|
|
|
}); |
|
|
|
return result; |
|
|
|
return result; |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
search: function (root, target, param) { |
|
|
|
search(root, target, param) { |
|
|
|
if (!(root instanceof BI.Node)) { |
|
|
|
if (!(root instanceof Node)) { |
|
|
|
return arguments.callee.apply(this, [this.root, root, target]); |
|
|
|
return this.search(this.root, root, target); |
|
|
|
} |
|
|
|
} |
|
|
|
var self = this, next = null; |
|
|
|
let next = null; |
|
|
|
|
|
|
|
|
|
|
|
if (BI.isNull(target)) { |
|
|
|
if (isNull(target)) { |
|
|
|
return null; |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
if (BI.isEqual(root[param || "id"], target)) { |
|
|
|
if (isEqual(root[param || "id"], target)) { |
|
|
|
return root; |
|
|
|
return root; |
|
|
|
} |
|
|
|
} |
|
|
|
BI.any(root.getChildren(), function (i, child) { |
|
|
|
some(root.getChildren(), (i, child) => { |
|
|
|
next = self.search(child, target, param); |
|
|
|
next = this.search(child, target, param); |
|
|
|
if (null !== next) { |
|
|
|
if (null !== next) { |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
return next; |
|
|
|
return next; |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
_traverse: function (node, callback) { |
|
|
|
_traverse(node, callback) { |
|
|
|
var queue = []; |
|
|
|
let queue = []; |
|
|
|
queue.push(node); |
|
|
|
queue.push(node); |
|
|
|
while (!BI.isEmpty(queue)) { |
|
|
|
while (!isEmpty(queue)) { |
|
|
|
var temp = queue.shift(); |
|
|
|
const temp = queue.shift(); |
|
|
|
var b = callback && callback(temp); |
|
|
|
const b = callback && callback(temp); |
|
|
|
if (b === false) { |
|
|
|
if (b === false) { |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
@ -130,51 +268,50 @@ |
|
|
|
queue = queue.concat(temp.getChildren()); |
|
|
|
queue = queue.concat(temp.getChildren()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
traverse: function (callback) { |
|
|
|
traverse(callback) { |
|
|
|
this._traverse(this.root, callback); |
|
|
|
this._traverse(this.root, callback); |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
_recursion: function (node, route, callback) { |
|
|
|
_recursion(node, route, callback) { |
|
|
|
var self = this; |
|
|
|
return every(node.getChildren(), (i, child) => { |
|
|
|
return BI.every(node.getChildren(), function (i, child) { |
|
|
|
const next = clone(route); |
|
|
|
var next = BI.clone(route); |
|
|
|
|
|
|
|
next.push(child.id); |
|
|
|
next.push(child.id); |
|
|
|
var b = callback && callback(child, next); |
|
|
|
const b = callback && callback(child, next); |
|
|
|
if (b === false) { |
|
|
|
if (b === false) { |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
if (b === true) { |
|
|
|
if (b === true) { |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
return self._recursion(child, next, callback); |
|
|
|
return this._recursion(child, next, callback); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
recursion: function (callback) { |
|
|
|
recursion(callback) { |
|
|
|
this._recursion(this.root, [], callback); |
|
|
|
this._recursion(this.root, [], callback); |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
inOrderTraverse: function (callback) { |
|
|
|
inOrderTraverse(callback) { |
|
|
|
this._inOrderTraverse(this.root, callback); |
|
|
|
this._inOrderTraverse(this.root, callback); |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 中序遍历(递归)
|
|
|
|
// 中序遍历(递归)
|
|
|
|
_inOrderTraverse: function (node, callback) { |
|
|
|
_inOrderTraverse(node, callback) { |
|
|
|
if (node != null) { |
|
|
|
if (node != null) { |
|
|
|
this._inOrderTraverse(node.getLeft()); |
|
|
|
this._inOrderTraverse(node.getLeft()); |
|
|
|
callback && callback(node); |
|
|
|
callback && callback(node); |
|
|
|
this._inOrderTraverse(node.getRight()); |
|
|
|
this._inOrderTraverse(node.getRight()); |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 中序遍历(非递归)
|
|
|
|
// 中序遍历(非递归)
|
|
|
|
nrInOrderTraverse: function (callback) { |
|
|
|
nrInOrderTraverse(callback) { |
|
|
|
|
|
|
|
|
|
|
|
var stack = []; |
|
|
|
const stack = []; |
|
|
|
var node = this.root; |
|
|
|
let node = this.root; |
|
|
|
while (node != null || !BI.isEmpty(stack)) { |
|
|
|
while (node != null || !isEmpty(stack)) { |
|
|
|
while (node != null) { |
|
|
|
while (node != null) { |
|
|
|
stack.push(node); |
|
|
|
stack.push(node); |
|
|
|
node = node.getLeft(); |
|
|
|
node = node.getLeft(); |
|
|
@ -183,28 +320,28 @@ |
|
|
|
callback && callback(node); |
|
|
|
callback && callback(node); |
|
|
|
node = node.getRight(); |
|
|
|
node = node.getRight(); |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
preOrderTraverse: function (callback) { |
|
|
|
preOrderTraverse(callback) { |
|
|
|
this._preOrderTraverse(this.root, callback); |
|
|
|
this._preOrderTraverse(this.root, callback); |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 先序遍历(递归)
|
|
|
|
// 先序遍历(递归)
|
|
|
|
_preOrderTraverse: function (node, callback) { |
|
|
|
_preOrderTraverse(node, callback) { |
|
|
|
if (node != null) { |
|
|
|
if (node != null) { |
|
|
|
callback && callback(node); |
|
|
|
callback && callback(node); |
|
|
|
this._preOrderTraverse(node.getLeft()); |
|
|
|
this._preOrderTraverse(node.getLeft()); |
|
|
|
this._preOrderTraverse(node.getRight()); |
|
|
|
this._preOrderTraverse(node.getRight()); |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 先序遍历(非递归)
|
|
|
|
// 先序遍历(非递归)
|
|
|
|
nrPreOrderTraverse: function (callback) { |
|
|
|
nrPreOrderTraverse(callback) { |
|
|
|
|
|
|
|
|
|
|
|
var stack = []; |
|
|
|
const stack = []; |
|
|
|
var node = this.root; |
|
|
|
let node = this.root; |
|
|
|
|
|
|
|
|
|
|
|
while (node != null || !BI.isEmpty(stack)) { |
|
|
|
while (node != null || !isEmpty(stack)) { |
|
|
|
|
|
|
|
|
|
|
|
while (node != null) { |
|
|
|
while (node != null) { |
|
|
|
callback && callback(node); |
|
|
|
callback && callback(node); |
|
|
@ -214,38 +351,38 @@ |
|
|
|
node = stack.pop(); |
|
|
|
node = stack.pop(); |
|
|
|
node = node.getRight(); |
|
|
|
node = node.getRight(); |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
postOrderTraverse: function (callback) { |
|
|
|
postOrderTraverse(callback) { |
|
|
|
this._postOrderTraverse(this.root, callback); |
|
|
|
this._postOrderTraverse(this.root, callback); |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 后序遍历(递归)
|
|
|
|
// 后序遍历(递归)
|
|
|
|
_postOrderTraverse: function (node, callback) { |
|
|
|
_postOrderTraverse(node, callback) { |
|
|
|
if (node != null) { |
|
|
|
if (node != null) { |
|
|
|
this._postOrderTraverse(node.getLeft()); |
|
|
|
this._postOrderTraverse(node.getLeft()); |
|
|
|
this._postOrderTraverse(node.getRight()); |
|
|
|
this._postOrderTraverse(node.getRight()); |
|
|
|
callback && callback(node); |
|
|
|
callback && callback(node); |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 后续遍历(非递归)
|
|
|
|
// 后续遍历(非递归)
|
|
|
|
nrPostOrderTraverse: function (callback) { |
|
|
|
nrPostOrderTraverse(callback) { |
|
|
|
|
|
|
|
|
|
|
|
var stack = []; |
|
|
|
const stack = []; |
|
|
|
var node = this.root; |
|
|
|
let node = this.root; |
|
|
|
var preNode = null;// 表示最近一次访问的节点
|
|
|
|
let preNode = null;// 表示最近一次访问的节点
|
|
|
|
|
|
|
|
|
|
|
|
while (node != null || !BI.isEmpty(stack)) { |
|
|
|
while (node != null || !isEmpty(stack)) { |
|
|
|
|
|
|
|
|
|
|
|
while (node != null) { |
|
|
|
while (node != null) { |
|
|
|
stack.push(node); |
|
|
|
stack.push(node); |
|
|
|
node = node.getLeft(); |
|
|
|
node = node.getLeft(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
node = BI.last(stack); |
|
|
|
node = last(stack); |
|
|
|
|
|
|
|
|
|
|
|
if (node.getRight() == null || node.getRight() == preNode) { |
|
|
|
if (node.getRight() == null || node.getRight() === preNode) { |
|
|
|
callback && callback(node); |
|
|
|
callback && callback(node); |
|
|
|
node = stack.pop(); |
|
|
|
node = stack.pop(); |
|
|
|
preNode = node; |
|
|
|
preNode = node; |
|
|
@ -255,203 +392,72 @@ |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BI.Node = function (id) { |
|
|
|
|
|
|
|
if (BI.isObject(id)) { |
|
|
|
|
|
|
|
BI.extend(this, id); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
this.id = id; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
this.clear.apply(this, arguments); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BI.Node.prototype = { |
|
|
|
|
|
|
|
constructor: BI.Node, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set: function (key, value) { |
|
|
|
|
|
|
|
if (BI.isObject(key)) { |
|
|
|
|
|
|
|
BI.extend(this, key); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
this[key] = value; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
get: function (key) { |
|
|
|
|
|
|
|
return this[key]; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
isLeaf: function () { |
|
|
|
|
|
|
|
return BI.isEmpty(this.children); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getChildren: function () { |
|
|
|
|
|
|
|
return this.children; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getChildrenLength: function () { |
|
|
|
|
|
|
|
return this.children.length; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getFirstChild: function () { |
|
|
|
|
|
|
|
return BI.first(this.children); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getLastChild: function () { |
|
|
|
|
|
|
|
return BI.last(this.children); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setLeft: function (left) { |
|
|
|
|
|
|
|
this.left = left; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getLeft: function () { |
|
|
|
|
|
|
|
return this.left; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setRight: function (right) { |
|
|
|
|
|
|
|
this.right = right; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getRight: function () { |
|
|
|
|
|
|
|
return this.right; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setParent: function (parent) { |
|
|
|
|
|
|
|
this.parent = parent; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getParent: function () { |
|
|
|
|
|
|
|
return this.parent; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getChild: function (index) { |
|
|
|
|
|
|
|
return this.children[index]; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getChildIndex: function (id) { |
|
|
|
|
|
|
|
return BI.findIndex(this.children, function (i, ch) { |
|
|
|
|
|
|
|
return ch.get("id") === id; |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
removeChild: function (id) { |
|
|
|
|
|
|
|
this.removeChildByIndex(this.getChildIndex(id)); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
removeChildByIndex: function (index) { |
|
|
|
|
|
|
|
var before = this.getChild(index - 1); |
|
|
|
|
|
|
|
var behind = this.getChild(index + 1); |
|
|
|
|
|
|
|
if (before != null) { |
|
|
|
|
|
|
|
before.setRight(behind || null); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (behind != null) { |
|
|
|
|
|
|
|
behind.setLeft(before || null); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
this.children.splice(index, 1); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
removeAllChilds: function () { |
|
|
|
|
|
|
|
this.children = []; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
addChild: function (child, index) { |
|
|
|
|
|
|
|
var cur = null; |
|
|
|
|
|
|
|
if (BI.isUndefined(index)) { |
|
|
|
|
|
|
|
cur = this.children.length - 1; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
cur = index - 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
child.setParent(this); |
|
|
|
|
|
|
|
if (cur >= 0) { |
|
|
|
|
|
|
|
this.getChild(cur) && this.getChild(cur).setRight(child); |
|
|
|
|
|
|
|
child.setLeft(this.getChild(cur)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (BI.isUndefined(index)) { |
|
|
|
|
|
|
|
this.children.push(child); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
this.children.splice(index, 0, child); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
equals: function (obj) { |
|
|
|
|
|
|
|
return this === obj || this.id === obj.id; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
clear: function () { |
|
|
|
static transformToArrayFormat(nodes, pId, childKey) { |
|
|
|
this.parent = null; |
|
|
|
|
|
|
|
this.left = null; |
|
|
|
|
|
|
|
this.right = null; |
|
|
|
|
|
|
|
this.children = []; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BI.extend(BI.Tree, { |
|
|
|
|
|
|
|
transformToArrayFormat: function (nodes, pId, childKey) { |
|
|
|
|
|
|
|
if (!nodes) return []; |
|
|
|
if (!nodes) return []; |
|
|
|
var r = []; |
|
|
|
let r = []; |
|
|
|
childKey = childKey || "children"; |
|
|
|
childKey = childKey || "children"; |
|
|
|
if (BI.isArray(nodes)) { |
|
|
|
if (isArray(nodes)) { |
|
|
|
for (var i = 0, l = nodes.length; i < l; i++) { |
|
|
|
for (let i = 0, l = nodes.length; i < l; i++) { |
|
|
|
var node = BI.clone(nodes[i]); |
|
|
|
const node = clone(nodes[i]); |
|
|
|
node.pId = node.pId == null ? pId : node.pId; |
|
|
|
node.pId = node.pId == null ? pId : node.pId; |
|
|
|
delete node.children; |
|
|
|
delete node.children; |
|
|
|
r.push(node); |
|
|
|
r.push(node); |
|
|
|
if (nodes[i][childKey]) { |
|
|
|
if (nodes[i][childKey]) { |
|
|
|
r = r.concat(BI.Tree.transformToArrayFormat(nodes[i][childKey], node.id)); |
|
|
|
r = r.concat(Tree.transformToArrayFormat(nodes[i][childKey], node.id)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
var newNodes = BI.clone(nodes); |
|
|
|
const newNodes = clone(nodes); |
|
|
|
newNodes.pId = newNodes.pId == null ? pId : newNodes.pId; |
|
|
|
newNodes.pId = newNodes.pId == null ? pId : newNodes.pId; |
|
|
|
delete newNodes.children; |
|
|
|
delete newNodes.children; |
|
|
|
r.push(newNodes); |
|
|
|
r.push(newNodes); |
|
|
|
if (nodes[childKey]) { |
|
|
|
if (nodes[childKey]) { |
|
|
|
r = r.concat(BI.Tree.transformToArrayFormat(nodes[childKey], newNodes.id)); |
|
|
|
r = r.concat(Tree.transformToArrayFormat(nodes[childKey], newNodes.id)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return r; |
|
|
|
return r; |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
arrayFormat: function (nodes, pId) { |
|
|
|
static arrayFormat(nodes, pId) { |
|
|
|
if (!nodes) { |
|
|
|
if (!nodes) { |
|
|
|
return []; |
|
|
|
return []; |
|
|
|
} |
|
|
|
} |
|
|
|
var r = []; |
|
|
|
let r = []; |
|
|
|
if (BI.isArray(nodes)) { |
|
|
|
if (isArray(nodes)) { |
|
|
|
for (var i = 0, l = nodes.length; i < l; i++) { |
|
|
|
for (let i = 0, l = nodes.length; i < l; i++) { |
|
|
|
var node = nodes[i]; |
|
|
|
const node = nodes[i]; |
|
|
|
node.pId = node.pId == null ? pId : node.pId; |
|
|
|
node.pId = node.pId == null ? pId : node.pId; |
|
|
|
r.push(node); |
|
|
|
r.push(node); |
|
|
|
if (nodes[i]["children"]) { |
|
|
|
if (nodes[i]["children"]) { |
|
|
|
r = r.concat(BI.Tree.arrayFormat(nodes[i]["children"], node.id)); |
|
|
|
r = r.concat(Tree.arrayFormat(nodes[i]["children"], node.id)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
var newNodes = nodes; |
|
|
|
const newNodes = nodes; |
|
|
|
newNodes.pId = newNodes.pId == null ? pId : newNodes.pId; |
|
|
|
newNodes.pId = newNodes.pId == null ? pId : newNodes.pId; |
|
|
|
r.push(newNodes); |
|
|
|
r.push(newNodes); |
|
|
|
if (nodes["children"]) { |
|
|
|
if (nodes["children"]) { |
|
|
|
r = r.concat(BI.Tree.arrayFormat(nodes["children"], newNodes.id)); |
|
|
|
r = r.concat(Tree.arrayFormat(nodes["children"], newNodes.id)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return r; |
|
|
|
return r; |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
transformToTreeFormat: function (sNodes) { |
|
|
|
static transformToTreeFormat(sNodes) { |
|
|
|
var i, l; |
|
|
|
let i, l; |
|
|
|
if (!sNodes) { |
|
|
|
if (!sNodes) { |
|
|
|
return []; |
|
|
|
return []; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (BI.isArray(sNodes)) { |
|
|
|
if (isArray(sNodes)) { |
|
|
|
var r = []; |
|
|
|
const r = []; |
|
|
|
var tmpMap = {}; |
|
|
|
const tmpMap = {}; |
|
|
|
for (i = 0, l = sNodes.length; i < l; i++) { |
|
|
|
for (i = 0, l = sNodes.length; i < l; i++) { |
|
|
|
if (BI.isNull(sNodes[i].id)) { |
|
|
|
if (isNull(sNodes[i].id)) { |
|
|
|
return sNodes; |
|
|
|
return sNodes; |
|
|
|
} |
|
|
|
} |
|
|
|
tmpMap[sNodes[i].id] = BI.clone(sNodes[i]); |
|
|
|
tmpMap[sNodes[i].id] = clone(sNodes[i]); |
|
|
|
} |
|
|
|
} |
|
|
|
for (i = 0, l = sNodes.length; i < l; i++) { |
|
|
|
for (i = 0, l = sNodes.length; i < l; i++) { |
|
|
|
if (tmpMap[sNodes[i].pId] && sNodes[i].id !== sNodes[i].pId) { |
|
|
|
if (tmpMap[sNodes[i].pId] && sNodes[i].id !== sNodes[i].pId) { |
|
|
@ -468,19 +474,19 @@ |
|
|
|
} |
|
|
|
} |
|
|
|
return [sNodes]; |
|
|
|
return [sNodes]; |
|
|
|
|
|
|
|
|
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
treeFormat: function (sNodes) { |
|
|
|
static treeFormat(sNodes) { |
|
|
|
var i, l; |
|
|
|
let i, l; |
|
|
|
if (!sNodes) { |
|
|
|
if (!sNodes) { |
|
|
|
return []; |
|
|
|
return []; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (BI.isArray(sNodes)) { |
|
|
|
if (isArray(sNodes)) { |
|
|
|
var r = []; |
|
|
|
const r = []; |
|
|
|
var tmpMap = {}; |
|
|
|
const tmpMap = {}; |
|
|
|
for (i = 0, l = sNodes.length; i < l; i++) { |
|
|
|
for (i = 0, l = sNodes.length; i < l; i++) { |
|
|
|
if (BI.isNull(sNodes[i].id)) { |
|
|
|
if (isNull(sNodes[i].id)) { |
|
|
|
return sNodes; |
|
|
|
return sNodes; |
|
|
|
} |
|
|
|
} |
|
|
|
tmpMap[sNodes[i].id] = sNodes[i]; |
|
|
|
tmpMap[sNodes[i].id] = sNodes[i]; |
|
|
@ -499,19 +505,17 @@ |
|
|
|
} |
|
|
|
} |
|
|
|
return [sNodes]; |
|
|
|
return [sNodes]; |
|
|
|
|
|
|
|
|
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
traversal: function (array, callback, pNode) { |
|
|
|
static traversal(array, callback, pNode) { |
|
|
|
if (BI.isNull(array)) { |
|
|
|
if (isNull(array)) { |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
var self = this; |
|
|
|
some(array, (i, item) => { |
|
|
|
BI.some(array, function (i, item) { |
|
|
|
|
|
|
|
if (callback(i, item, pNode) === false) { |
|
|
|
if (callback(i, item, pNode) === false) { |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
self.traversal(item.children, callback, item); |
|
|
|
this.traversal(item.children, callback, item); |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
})(); |
|
|
|
|
|
|
|