Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I think the approach through "BinaryTree"s assumes too much of a fixed structure and unnecessarily defines your interface in a nongeneric way. Doing this makes it difficult to reuse algorithms as your tree expands into non-binary forms. Instead, you will need to code your interfaces for multiple styles when such is not necessary or useful.</p> <p>Also, coding with hasLeft/hasRight checks means every access is a two step process. Checking existence of a fixed position will not provide for efficient algorithms. Instead, I think you will find that adding a generic property that may be binary left/right or binary red/black or a character index or anything else will allow much more reuse of your algorithms and checking that data can be done only by those algorithms that need it (specific binary algorithms).</p> <p>From a semantic view, you want to encode some basic properties first, and then specialise. When you are "at" a node inside an algorithm, you want to be able to first find the children <em>edges</em>. This should be a container range of edge structures that allow you to navigate to the children nodes. Since it can be a generic container, it could have 0, 2, 5, 1, or even a 100 edges in it. Many algorithms do not care. If it has 0, iterating over the range will do nothing - no need to check hasX or hasY. For each edge, you should be able to get the node of the child, and recurse for whatever algorithm you wish.</p> <p>This is basically the approach boost takes in it's Graph library, and it allows for expansion of tree algorithms to graphs where they are applicable, for even better generic algorithm reuse.</p> <p>So already you have a basic interface with this</p> <pre><code>TreeNode: getChildEdges: () -&gt; TreeEdgeRange TreeEdge: getChildNode: () -&gt; TreeNode </code></pre> <p>and whatever range-to-object your favorite language enjoys. D has a particularly useful range syntax, for instance.</p> <p>You will want to have some basic Tree object that gives you nodes. Something like</p> <pre><code>Tree: getTreeNodes: () -&gt; TreeNodeRange </code></pre> <p>starts you out.</p> <p>Now, if you want to support BinaryTrees, do so as a restriction on this interface. Note that you don't really need any new interface methods, you just need to enforce more invariants - that every TreeNode has 0, 1, or 2 childEdges. Just make an interface type that indicates this semantic restriction:</p> <pre><code>BinaryTree : Tree </code></pre> <p>And if you want to support rooted trees, adding an interface layer with</p> <pre><code>RootedTree : Tree: getRoot: () -&gt; TreeNode </code></pre> <p>adds that capability.</p> <p>The basic idea is that you shouldn't have to add interface methods to add semantic requirements if you are making your classes more specific down the hierarchy. Only add interface methods if there is a new semantic behavior that needs accessed. Otherwise - enforce new invariants on the generic interface.</p> <p>Eventually, you'll want to decorate nodes and edges with structures that hold data about the node or edge, so you can build Tries and Red-Black trees and all the great tools of advanced algorithmics. So you will want to have</p> <pre><code>PropertiedTreeNode&lt;Property&gt; : TreeNode: getProperty: () -&gt; Property PropertiedTreeEdge&lt;Property&gt; : TreeEdge: getProperty: () -&gt; Property </code></pre> <p>Since this is something you will want to allow generic algorithms to work on, the type information of whether a property is a part of the Tree or not should be generic and something algorithms can ignore. This puts you on the design track of boost, where these issues have been resolved very elegantly. I would recommend studying that library if you want ideas on how to build a generic tree algorithm library.</p> <p>If you follow the above guidelines of types-equating-to-semantic-descriptions, then thee SubTree should be obvious - it's exactly the same type as the tree it is coming from! In fact, you really should not have a SubTree type at all. Instead, you should just have a method of the specific TreeNode type you are dealing with</p> <pre><code>PropertiedTreeNode&lt;Property&gt;: getSubTree: () -&gt; PropertiedTree&lt;Property&gt; </code></pre> <p>And, as in boost, as you encode more of the information of the capabilities of Tree in it's generic properties, you can get new Tree types with broader interface contracts.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload