版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/michael51/article/details/88213507
class Node {
constructor(data) {
this.data = data;
this.parent = null;
this.children = [];
}
}
class MultiwayTree {
constructor() {
this._root = null;
}
//深度优先遍历
traverseDF(callback) {
let stack = [], found = false;
stack.unshift(this._root);
let currentNode = stack.shift();
while (!found && currentNode) {
found = callback(currentNode) === true ? true : false;
if (!found) {
stack.unshift(...currentNode.children);
currentNode = stack.shift();
}
}
}
//广度优先遍历
traverseBF(callback) {
let queue = [], found = false;
queue.push(this._root);
let currentNode = queue.shift();
while (!found && currentNode) {
found = callback(currentNode) === true ? true : false;
if (!found) {
queue.push(...currentNode.children)
currentNode = queue.shift();
}
}
}
contains(callback, traversal) {
traversal.call(this, callback);
}
add(data, toData, traversal) {
let node = new Node(data)
if (this._root === null) {
this._root = node;
return this;
}
let parent = null,
callback = function (node) {
if (node.data === toData) {
parent = node;
return true;
}
};
this.contains(callback, traversal);
if (parent) {
parent.children.push(node);
node.parent = parent;
return this;
} else {
throw new Error('Cannot add node to a non-existent parent.');
}
}
remove(data, fromData, traversal) {
let parent = null,
childToRemove = null,
callback = function (node) {
if (node.data === fromData) {
parent = node;
return true;
}
};
this.contains(callback, traversal);
if (parent) {
let index = this._findIndex(parent.children, data);
if (index < 0) {
throw new Error('Node to remove does not exist.');
} else {
childToRemove = parent.children.splice(index, 1);
}
} else {
throw new Error('Parent does not exist.');
}
return childToRemove;
}
_findIndex(arr, data) {
let index = -1;
for (let i = 0, len = arr.length; i < len; i++) {
if (arr[i].data === data) {
index = i;
break;
}
}
return index;
}
}
//图示
//http://note.youdao.com/noteshare?id=2e5ea66c27407329937f432fc2457aef&sub=1BE0366303D84814AF4B2E5A0A3E4960
var tree = new MultiwayTree();
tree.add('a')
.add('b', 'a', tree.traverseBF)
.add('c', 'a', tree.traverseBF)
.add('d', 'a', tree.traverseBF)
.add('e', 'b', tree.traverseBF)
.add('f', 'b', tree.traverseBF)
.add('g', 'c', tree.traverseBF)
.add('h', 'c', tree.traverseBF)
.add('i', 'd', tree.traverseBF)
.add('x', 'f', tree.traverseBF)
.add('y', 'x', tree.traverseBF);
console.group('深度优先遍历');
tree.traverseDF(function (node) {
console.log(node.data);
});
console.groupEnd();
console.group('广度优先遍历');
tree.traverseBF(function (node) {
console.log(node.data);
});
console.groupEnd();
// 深度优先查找
console.group('深度优先查找f');
tree.contains(function (node) {
console.log(node.data);
if (node.data === 'f') {
return true;
}
}, tree.traverseDF);
console.groupEnd()
// 广度优先查找
console.group('广度优先查找f');
tree.contains(function (node) {
console.log(node.data);
if (node.data === 'f') {
return true;
}
}, tree.traverseBF);
console.groupEnd();
//按照深度优先遍历并且移除g和c。
tree.remove('g', 'c', tree.traverseBF);
console.group('移除元素之后再次深度优先遍历');
tree.traverseDF(function (node) {
console.log(node.data);
});
console.groupEnd();