简体   繁体   English

JS中的树状数据结构允许最快的节点查找?

[英]Tree-like data structure in JS that allows for fastest node lookup?

How would I go about creating a tree-like data structure in JS, where, I can have access to things like reference to parent node, id based node lookup, having access to length (number) of children nodes, index based lookup etc? 我将如何在JS中创建一个类似树的数据结构,在那里,我可以访问诸如父节点的引用,基于id的节点查找,访问子节点的长度(数量),基于索引的查找等等?

this is basically the API I am envisioning: 这基本上就是我想象的API:

var rootNode = DataStructure.getRoot();
var child1 = rootNode.addNode('child1'); //added a node with id 'child1'
child1.addNode('innerChild1');
child1.addNode('innerChild2');
rootNode.getChildById('child1') //should be same node as var child1
rootNode.getAtIndex(0) //should be same node as var child1
child1.parent() //should be rootNode
child1.getAtIndex(0) // should be node with id 'innerChild1'
child1.getAtIndex(1) // should be node with id 'innerChild2'
child1.length() //should be 2 

etc.. 等等..

I understand its a broad question, but I wonder if anyone could recommend a way to approach this and/or any libraries that might be doing it already? 我理解它的一个广泛的问题,但我想知道是否有人可以推荐一种方法来处理这个和/或任何可能已经这样做的库? Should i just dynamically create an XML and work with its native methods? 我应该动态创建XML并使用其本机方法吗? Would that be the fastest ? 那会是最快的吗?

The data structure you described can be easily implemented as follows: 您描述的数据结构可以很容易地实现如下:

 var Tree = defclass({ constructor: function (parent) { this.parent = parent || null; // null for root node this.children = {}; // for id based lookup this.ids = []; // for index based lookup this.length = 0; // for ease of access }, addNode: function (id) { var children = this.children; if (children.hasOwnProperty(id)) throw new Error(id + " exists"); return children[this.ids[this.length++] = id] = new Tree(this); }, getChildById: function (id) { var children = this.children; if (children.hasOwnProperty(id)) return children[id]; throw new Error(id + " does not exist"); }, getAtIndex: function (index) { return this.getChildById(this.ids[index]); } }); function defclass(prototype) { var constructor = prototype.constructor; constructor.prototype = prototype; return constructor; } 
 <script> setTimeout(function () { var rootNode = new Tree; var child1 = rootNode.addNode("child1"); var innerChild1 = child1.addNode("innerChild1"); var innerChild2 = child1.addNode("innerChild2"); console.assert(rootNode.getChildById("child1") === child1); console.assert(rootNode.getAtIndex(0) === child1); console.assert(child1.parent === rootNode); console.assert(child1.getAtIndex(0) === innerChild1); console.assert(child1.getAtIndex(1) === innerChild2); console.assert(child1.length === 2); alert("success"); }, 0); </script> 

Both id based lookups and index based lookups take constant (ie O(1) ) time . 基于id的查找和基于索引的查找都采用常量(即O(1)时间 Hope that helps. 希望有所帮助。

I have a structure like this in an app. 我在应用程序中有这样的结构。 The API specified would make it difficult to create a structure like you want. 指定的API会使您难以创建所需的结构。 Here are some things I noticed: DataStructure is a singleton, addChild doesn't allow you to add a node with children, and indexes are numbers. 以下是我注意到的一些事情: DataStructure是单例, addChild不允许您添加addChild节点的节点,索引是数字。 How about the following? 以下怎么样?

API API

TreeNode (newable) TreeNode(newable)

Members: 成员:

  • children (Object, indexed on ID) children(对象,在ID上建立索引)
  • root (TreeNode) root(TreeNode)
  • parent (TreeNode) parent(TreeNode)
  • index (String) index(String)
  • attributes (Object) 属性(对象)
  • _referenceCount (int) - useful if your tree has cycles for some reason _referenceCount(int) - 如果您的树由于某种原因而具有循环,则非常有用

Methods: 方法:

  • addChild(TreeNode: treeNode) addChild(TreeNode:treeNode)
    • Register the node with the parent 使用父级注册节点
    • Adds the node by ID to children 按ID将节点添加到子节点
    • Increments reference count of added TreeNode 增加TreeNode的引用计数
  • forEach(callback(TreeNode: treeNode)) forEach(callback(TreeNode:treeNode))
  • removeChild(String: id) removeChild(String:id)
    • Removes node from this Object 从此Object中删除节点
    • Decrement _referenceCount of the indicated child 减少指定孩子的_referenceCount
    • Removes it from the root if _referenceCount is 0 如果_referenceCount为0,则从根目录中删除它

Tree (extends TreeNode) (newable) 树(扩展TreeNode)(新增)

Members: 成员:

  • _nodeMap (Object) _nodeMap(Object)

Methods: 方法:

  • getNodeByID(String: id) getNodeByID(String:id)
    • looks up id in _nodeMap, O(1) lookup time 在_nodeMap中查找id,O(1)查找时间
  • removeNode(String: id) removeNode(String:id)
  • addToNodeMap(TreeNode: treeNode) addToNodeMap(TreeNode:treeNode)

treeFactory (optional) treeFactory(可选)

Methods: 方法:

  • createFromFormatX(Object: a tree of stuff in some specific format) The tree works fine, you should create a factory for your specific case that helps you transform a blob into your fancy data structure. createFromFormatX(对象:某种特定格式的东西树)树工作正常,你应该为你的特定情况创建一个工厂,帮助你将blob转换成你喜欢的数据结构。
  • createFromFormatY, basically another loader mechanism createFromFormatY,基本上是另一个加载器机制

Potential Immutability 潜在的不变性

Nothing here is immutable necessarily. 这里没有什么是不可改变的。 You could however, via use of a new factory method and make more of the above methods private always force immutability of the tree. 但是,您可以通过使用新的工厂方法并使上述方法中的更多内容始终强制树的不变性。 This may or may not be desirable. 这可能是也可能不是所希望的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM