tree-traversal http://www.e-learn.cn/tag/tree-traversal zh-hans How to traverse a Btree? http://www.e-learn.cn/topic/4023685 <span>How to traverse a Btree?</span> <span><span lang="" about="/user/176" typeof="schema:Person" property="schema:name" datatype="">浪尽此生</span></span> <span>2021-01-28 06:27:17</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><h3>问题</h3><br /><p>I have a Btree and I'm trying to figure out how traverse it so that the keys are displayed ascending order. </p> <p>All I can figure out is that this can be done with a recursive function.</p> <p>What's the pseudo-code to do it?</p> <br /><h3>回答1:</h3><br /><p>Assuming you have a definition like:</p> <pre><code>template &lt;class T&gt; class btree_node { btree_node **child; // an array of child nodes T **element; // the elements in this node unsigned int child_count; // the number of children // the number of elements is 1 less then child_count }; </code></pre> <p>Then you'll need do something like this:</p> <pre><code>void btree_inorder(node): for (int i = 0; i &lt; node.child_count; ++i) { btree_inorder(node.child[i]); handle_element(node.element[i]); } btree_inorder(node.child[node.child_count-1]); </code></pre> <br /><br /><br /><h3>回答2:</h3><br /><pre><code>void traversalBtree(struct node * root){ int i = 1; if(root != NULL){ while(i &lt;= root-&gt;n){ if(root-&gt;leaf == 0) traversalBtree(root-&gt;link[i]); printf("\t%d", root-&gt;key[i]); i++; } if(root-&gt;leaf == 0) traversalBtree(root-&gt;link[i]); } } </code></pre> <br /><br /><p>来源:<code>https://stackoverflow.com/questions/2799966/how-to-traverse-a-btree</code></p></div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field--label">标签</div> <div class="field--items"> <div class="field--item"><a href="/tag/c-0" hreflang="zh-hans">c++</a></div> <div class="field--item"><a href="/tag/g" hreflang="zh-hans">g++</a></div> <div class="field--item"><a href="/tag/traversal" hreflang="zh-hans">traversal</a></div> <div class="field--item"><a href="/tag/b-tree" hreflang="zh-hans">b-tree</a></div> <div class="field--item"><a href="/tag/tree-traversal" hreflang="zh-hans">tree-traversal</a></div> </div> </div> Wed, 27 Jan 2021 22:27:17 +0000 浪尽此生 4023685 at http://www.e-learn.cn Amortized Time Calculation in AVL tree http://www.e-learn.cn/topic/3978731 <span>Amortized Time Calculation in AVL tree</span> <span><span lang="" about="/user/232" typeof="schema:Person" property="schema:name" datatype="">旧巷老猫</span></span> <span>2020-12-27 07:24:49</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><h3>问题</h3><br /><p>My professor showed the following problem in class and mentioned that the answer is O(1) while mine was quit different, I hope to get some help knowing of what mistakes did I made.</p> <p><strong>Question:</strong></p> <p>Calculate the <strong>Amortized Time Complexity</strong> for F method in AVL tree, when we start from the minimal node and each time we call F over the last found member.</p> <p><strong>Description of F:</strong> when we are at specific node F continues just like inorder traversal starting from the current one until the next one in inorder traversal for the next call.</p> <hr /><p><strong>What I did:</strong></p> <p>First I took an random series of m calls to F.</p> <p>I said for the first one we need O(log n) - to find the most minimal node then for the next node we need to do inorder again but continues one more step so O(log n)+1 an so on until I scan m elements.</p> <p>Which gets me to:</p> <p></p> <p>To calculate Amortized Time we do T(m)/m then I get:</p> <p></p> <p>Which isn't O(1) for sure.</p> <br /><h3>回答1:</h3><br /><p>The algorithm doesn't start by searching for any node, but instead is already passed a node and will start from that node. E.g. pseudocode for <code>F</code> would look like this:</p> <pre><code>F(n): if n has right child n = right child of n while n has left child n = left child of n return n else prev = n cur = parent of n while prev is right child of cur and cur is not root prev = cur cur = parent of prev if cur is root and prev is right child of cur error "Reached end of traversal" else return cur </code></pre> <p>The above code basically does an in-order traversal of a tree starting from a node until the next node is reached.</p> <p>Amortized runtime:<br /> Pick an arbitrary tree and <code>m</code>. Let <code>r_0</code> be the lowest common ancestor of all nodes visited by <code>F</code>. Now define <code>r_(n + 1)</code> as the lowest common ancestor of all nodes in the right subtree of <code>r_n</code> that will be returned by <code>F</code>. This recursion bottoms out for <code>r_u</code>, which will be the <code>m</code>-th node in in-order traversal. Any <code>r_n</code> will be returned by <code>F</code> in some iteration, so all nodes in the left subtree of <code>r_n</code> will be returned by <code>F</code> as well.</p> <p>All nodes that will be visited by <code>F</code> are either also returned by <code>F</code> or are nodes on the path from <code>r_0</code> to <code>r_u</code>. Since <code>r_0</code> is an ancestor of <code>r_1</code> and <code>r_1</code> is an ancestor of <code>r_2</code>, etc., the path from <code>r_0</code> to <code>r_u</code> can be at most as long as the right subtree is high. The height of the tree is limited by <code>log_phi(m + 2)</code>, so in total at most</p> <pre><code>m + log_phi(m + 2) </code></pre> <p>nodes will be visited during <code>m</code> iterations of <code>F</code>. All nodes visited by <code>F</code> form a subtree, so there are at most <code>2 * (m + log_phi(m + 2))</code> edges that will be traversed by the algorithm, leading to an amortized runtime-complexity of</p> <pre><code>2 * (m + log_phi(m + 2)) / m = 2 + 2 * log_phi(m + 2) / m = O(1) </code></pre> <p>(The above bounds are in reality considerably tighter, but for the calculation presented here completely sufficient)</p> <br /><br /><p>来源:<code>https://stackoverflow.com/questions/65314222/amortized-time-calculation-in-avl-tree</code></p></div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field--label">标签</div> <div class="field--items"> <div class="field--item"><a href="/tag/algorithm" hreflang="zh-hans">algorithm</a></div> <div class="field--item"><a href="/tag/time-complexity" hreflang="zh-hans">time-complexity</a></div> <div class="field--item"><a href="/tag/avl-tree" hreflang="zh-hans">avl-tree</a></div> <div class="field--item"><a href="/tag/tree-traversal" hreflang="zh-hans">tree-traversal</a></div> <div class="field--item"><a href="/tag/amortized-analysis" hreflang="zh-hans">amortized-analysis</a></div> </div> </div> Sat, 26 Dec 2020 23:24:49 +0000 旧巷老猫 3978731 at http://www.e-learn.cn Find Path to Specified Node in Binary Tree (Python) http://www.e-learn.cn/topic/3664289 <span>Find Path to Specified Node in Binary Tree (Python)</span> <span><span lang="" about="/user/139" typeof="schema:Person" property="schema:name" datatype="">删除回忆录丶</span></span> <span>2020-06-12 22:09:16</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><h3>问题</h3><br /><p>I'm having trouble computing the path from the root to a specified node in a binary tree (this is specifically about a Python solution to this problem).</p> <p>Here's an example. Given the binary tree below, if I specify the node whose value is 4, I want to return [1, 2, 4]. If I specify the node whose value is 5, I want to return [1, 2, 5].</p> <pre><code> 1 / \ 2 3 / \ 4 5 </code></pre> <p>Here's my attemped solution.</p> <pre><code>class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None def path(root, k, l=[]): if not root: return [] if root.val == k: return l # Pre-order traversal: Visit root, then left, then right. l.append(root.val) path(root.left, k, l) path(root.right, k, l) return l </code></pre> <p>Now if I run this</p> <pre><code>&gt;&gt;&gt; a = TreeNode(1) &gt;&gt;&gt; b = TreeNode(2) &gt;&gt;&gt; c = TreeNode(3) &gt;&gt;&gt; d = TreeNode(4) &gt;&gt;&gt; e = TreeNode(5) &gt;&gt;&gt; a.left = b &gt;&gt;&gt; a.right = c &gt;&gt;&gt; b.left = d &gt;&gt;&gt; b.right = e &gt;&gt;&gt; path(a, 4) # should be [1, 2, 4] [1, 2, 5, 3] </code></pre> <p>You can see that I don't get the expected. I'm sure it has to do with my traversal algorithm, but I can't figure out where I'm going wrong. Any help is greatly appreciated.</p> <br /><h3>回答1:</h3><br /><p>The missing <code>4</code> is caused by the fact that you never append it. In your success case:</p> <pre><code>if root.val == k: return l </code></pre> <p>… you need to d this:</p> <pre><code>if root.val == k: l.append(root.val) return l </code></pre> <hr /><p>The extra <code>3</code> and <code>5</code> are caused by the fact that you <em>always</em> append the value in the intermediate case, even for the nodes where you're going to backtrack. </p> <p>You can fix that by only appending it if either of the recursive calls returns a non-empty list, but then of course you'll have the nodes out of order. The easiest fix for that is to <em>intentionally</em> get the nodes out of order:</p> <pre><code># Pre-order traversal: Visit root, then left, then right. if path(root.left, k, l) or path(root.right, k, l): l.append(root.val) </code></pre> <p>… and then reverse the list at the end, e.g., in a wrapper function:</p> <pre><code>def path2(root, k): return list(reversed(path(root, k))) </code></pre> <hr /><p>However, there's still one problem left in your code, right here:</p> <pre><code>def path(root, k, l=[]): </code></pre> <p>That <code>[]</code> that's the default value for <code>l</code> gets created one time, when the <code>def</code> is executed, and then reused on every call. That means that <code>path2(a, 4)</code> will return the right answer the first time, <code>[1, 2, 4]</code>, but when you call it a second time, it'll keep appending to that same list and return <code>[1, 2, 4, 1, 2, 4]</code>.</p> <p>There are a couple idiomatic ways around this, but in our case, since we're already using that <code>path2</code> wrapper function, we might as well just fix it there:</p> <pre><code>def path2(root, k): return list(reversed(path(root, k, []))) </code></pre> <p>… and then get rid of the default value on <code>path</code>.</p> <hr /><p>However, you might want to consider starting over with an easier-to-understand version:</p> <pre><code>def path(root, k): if not root: return [] if root.val == k: return [root.val] res = path(root.left, k) if res: return [root.val] + res res = path(root.right, k) if res: return [root.val] + res return [] </code></pre> <p>(You can make this is a bit shorter; I went out of my way to make everything explicit here.)</p> <p>For many recursive problems, inverting them and passing up an accumulator is an important optimization, because tail-call elimination can remove one of the branches from the stack. Even though Python doesn't do TCE, it's <em>still</em> worth learning how to do things the tail-calling way, just for your own understanding (and in case you ever write code in another language, of course). But learn how to do the simpler version first, and only then try to invert it.</p> <br /><br /><p>来源:<code>https://stackoverflow.com/questions/49227541/find-path-to-specified-node-in-binary-tree-python</code></p></div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field--label">标签</div> <div class="field--items"> <div class="field--item"><a href="/tag/python" hreflang="zh-hans">python</a></div> <div class="field--item"><a href="/tag/binary-tree" hreflang="zh-hans">binary-tree</a></div> <div class="field--item"><a href="/tag/depth-first-search" hreflang="zh-hans">depth-first-search</a></div> <div class="field--item"><a href="/tag/tree-traversal" hreflang="zh-hans">tree-traversal</a></div> </div> </div> Fri, 12 Jun 2020 14:09:16 +0000 删除回忆录丶 3664289 at http://www.e-learn.cn Find Path to Specified Node in Binary Tree (Python) http://www.e-learn.cn/topic/3664287 <span>Find Path to Specified Node in Binary Tree (Python)</span> <span><span lang="" about="/user/21" typeof="schema:Person" property="schema:name" datatype="">淺唱寂寞╮</span></span> <span>2020-06-12 22:05:57</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><h3>问题</h3><br /><p>I'm having trouble computing the path from the root to a specified node in a binary tree (this is specifically about a Python solution to this problem).</p> <p>Here's an example. Given the binary tree below, if I specify the node whose value is 4, I want to return [1, 2, 4]. If I specify the node whose value is 5, I want to return [1, 2, 5].</p> <pre><code> 1 / \ 2 3 / \ 4 5 </code></pre> <p>Here's my attemped solution.</p> <pre><code>class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None def path(root, k, l=[]): if not root: return [] if root.val == k: return l # Pre-order traversal: Visit root, then left, then right. l.append(root.val) path(root.left, k, l) path(root.right, k, l) return l </code></pre> <p>Now if I run this</p> <pre><code>&gt;&gt;&gt; a = TreeNode(1) &gt;&gt;&gt; b = TreeNode(2) &gt;&gt;&gt; c = TreeNode(3) &gt;&gt;&gt; d = TreeNode(4) &gt;&gt;&gt; e = TreeNode(5) &gt;&gt;&gt; a.left = b &gt;&gt;&gt; a.right = c &gt;&gt;&gt; b.left = d &gt;&gt;&gt; b.right = e &gt;&gt;&gt; path(a, 4) # should be [1, 2, 4] [1, 2, 5, 3] </code></pre> <p>You can see that I don't get the expected. I'm sure it has to do with my traversal algorithm, but I can't figure out where I'm going wrong. Any help is greatly appreciated.</p> <br /><h3>回答1:</h3><br /><p>The missing <code>4</code> is caused by the fact that you never append it. In your success case:</p> <pre><code>if root.val == k: return l </code></pre> <p>… you need to d this:</p> <pre><code>if root.val == k: l.append(root.val) return l </code></pre> <hr /><p>The extra <code>3</code> and <code>5</code> are caused by the fact that you <em>always</em> append the value in the intermediate case, even for the nodes where you're going to backtrack. </p> <p>You can fix that by only appending it if either of the recursive calls returns a non-empty list, but then of course you'll have the nodes out of order. The easiest fix for that is to <em>intentionally</em> get the nodes out of order:</p> <pre><code># Pre-order traversal: Visit root, then left, then right. if path(root.left, k, l) or path(root.right, k, l): l.append(root.val) </code></pre> <p>… and then reverse the list at the end, e.g., in a wrapper function:</p> <pre><code>def path2(root, k): return list(reversed(path(root, k))) </code></pre> <hr /><p>However, there's still one problem left in your code, right here:</p> <pre><code>def path(root, k, l=[]): </code></pre> <p>That <code>[]</code> that's the default value for <code>l</code> gets created one time, when the <code>def</code> is executed, and then reused on every call. That means that <code>path2(a, 4)</code> will return the right answer the first time, <code>[1, 2, 4]</code>, but when you call it a second time, it'll keep appending to that same list and return <code>[1, 2, 4, 1, 2, 4]</code>.</p> <p>There are a couple idiomatic ways around this, but in our case, since we're already using that <code>path2</code> wrapper function, we might as well just fix it there:</p> <pre><code>def path2(root, k): return list(reversed(path(root, k, []))) </code></pre> <p>… and then get rid of the default value on <code>path</code>.</p> <hr /><p>However, you might want to consider starting over with an easier-to-understand version:</p> <pre><code>def path(root, k): if not root: return [] if root.val == k: return [root.val] res = path(root.left, k) if res: return [root.val] + res res = path(root.right, k) if res: return [root.val] + res return [] </code></pre> <p>(You can make this is a bit shorter; I went out of my way to make everything explicit here.)</p> <p>For many recursive problems, inverting them and passing up an accumulator is an important optimization, because tail-call elimination can remove one of the branches from the stack. Even though Python doesn't do TCE, it's <em>still</em> worth learning how to do things the tail-calling way, just for your own understanding (and in case you ever write code in another language, of course). But learn how to do the simpler version first, and only then try to invert it.</p> <br /><br /><p>来源:<code>https://stackoverflow.com/questions/49227541/find-path-to-specified-node-in-binary-tree-python</code></p></div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field--label">标签</div> <div class="field--items"> <div class="field--item"><a href="/tag/python" hreflang="zh-hans">python</a></div> <div class="field--item"><a href="/tag/binary-tree" hreflang="zh-hans">binary-tree</a></div> <div class="field--item"><a href="/tag/depth-first-search" hreflang="zh-hans">depth-first-search</a></div> <div class="field--item"><a href="/tag/tree-traversal" hreflang="zh-hans">tree-traversal</a></div> </div> </div> Fri, 12 Jun 2020 14:05:57 +0000 淺唱寂寞╮ 3664287 at http://www.e-learn.cn How to print a binary tree in as a structure of nodes in Python http://www.e-learn.cn/topic/3642632 <span>How to print a binary tree in as a structure of nodes in Python</span> <span><span lang="" about="/user/32" typeof="schema:Person" property="schema:name" datatype="">倾然丶 夕夏残阳落幕</span></span> <span>2020-05-14 07:25:17</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><h3>问题</h3><br /><p>I have a python code to convert a string mathematical expression into a binary tree and order the nodes of the tree so the left child will be always smaller than the right child. I want to print the binary tree in the following order. </p> <p>For example consider the mathematical expression ((2 * 75) / 4). buildParseTree() converts the string expression into a tree and printNodeInLevels() rearranges the nodes so left child is smaller than the right right child at each level. Operands &lt; operators and operators are orders as '+' &lt; '-' &lt; '*' &lt; '/'. If the structure of the tree is like this</p> <pre><code> + /\ 4 * /\ 2 75 </code></pre> <p>I want to print it as follows. How should I go about this? Because the length of the mathematical expressions vary all the time e.g (24 * 2), ((5 - 1) * (2 / 3)), (20 - (5 + 4)) etc</p> <pre><code>Node("+") #root .addkid(Node("*") #right child at level 1 .addkid(Node("75")) #right child at level 2 .addkid(Node("2")) #left child at level 2 ) .addkid(Node("4")) #left child at level 1 </code></pre> <p>I have worked out the method to print nodes by their levels as in an in-order traversal pattern.If I call the method as follows it will print the following:</p> <pre><code>pt = buildParseTree("( ( 2 * 74 ) / 4 )") printNodesInLevels(pt) </code></pre> <p>output:</p> <pre><code>/ 4 * 2 74 </code></pre> <br /><h3>回答1:</h3><br /><p>Here is a function I created to print any binary tree structure.</p> <p>It is very generic and only needs a starting node (root) and a function (or lambda) to obtain a label and the left/right children nodes:</p> <p>You would typically use it like this on your Node class:</p> <pre><code>printBTree(rootNode,lambda n: (n.operand, n.left, n.right) ) # assuming the Node class has a string property named operand # and left,right properties that return a Node or None </code></pre> <p>A quadratic equation (-b +/- sqrt(b**2 - 4*a*c))/(2*a) could then print like this:</p> <pre><code># / # ___/ \__ # +/- * # / \ / \ # - sqrt 2 a # \ \ # b - # __/ \_ # ** * # / \ / \ # b 2 4 * # / \ # a c </code></pre> <p>Here is the printBTree function :</p> <pre><code>import functools as fn def printBTree(node, nodeInfo=None, inverted=False, isTop=True): # node value string and sub nodes stringValue, leftNode, rightNode = nodeInfo(node) stringValueWidth = len(stringValue) # recurse to sub nodes to obtain line blocks on left and right leftTextBlock = [] if not leftNode else printBTree(leftNode,nodeInfo,inverted,False) rightTextBlock = [] if not rightNode else printBTree(rightNode,nodeInfo,inverted,False) # count common and maximum number of sub node lines commonLines = min(len(leftTextBlock),len(rightTextBlock)) subLevelLines = max(len(rightTextBlock),len(leftTextBlock)) # extend lines on shallower side to get same number of lines on both sides leftSubLines = leftTextBlock + [""] * (subLevelLines - len(leftTextBlock)) rightSubLines = rightTextBlock + [""] * (subLevelLines - len(rightTextBlock)) # compute location of value or link bar for all left and right sub nodes # * left node's value ends at line's width # * right node's value starts after initial spaces leftLineWidths = [ len(line) for line in leftSubLines ] rightLineIndents = [ len(line)-len(line.lstrip(" ")) for line in rightSubLines ] # top line value locations, will be used to determine position of current node &amp; link bars firstLeftWidth = (leftLineWidths + [0])[0] firstRightIndent = (rightLineIndents + [0])[0] # width of sub node link under node value (i.e. with slashes if any) # aims to center link bars under the value if value is wide enough # # ValueLine: v vv vvvvvv vvvvv # LinkLine: / \ / \ / \ / \ # linkSpacing = min(stringValueWidth, 2 - stringValueWidth % 2) leftLinkBar = 1 if leftNode else 0 rightLinkBar = 1 if rightNode else 0 minLinkWidth = leftLinkBar + linkSpacing + rightLinkBar valueOffset = (stringValueWidth - linkSpacing) // 2 # find optimal position for right side top node # * must allow room for link bars above and between left and right top nodes # * must not overlap lower level nodes on any given line (allow gap of minSpacing) # * can be offset to the left if lower subNodes of right node # have no overlap with subNodes of left node minSpacing = 2 rightNodePosition = fn.reduce(lambda r,i: max(r,i[0] + minSpacing + firstRightIndent - i[1]), \ zip(leftLineWidths,rightLineIndents[0:commonLines]), \ firstLeftWidth + minLinkWidth) # extend basic link bars (slashes) with underlines to reach left and right # top nodes. # # vvvvv # __/ \__ # L R # linkExtraWidth = max(0, rightNodePosition - firstLeftWidth - minLinkWidth ) rightLinkExtra = linkExtraWidth // 2 leftLinkExtra = linkExtraWidth - rightLinkExtra # build value line taking into account left indent and link bar extension (on left side) valueIndent = max(0, firstLeftWidth + leftLinkExtra + leftLinkBar - valueOffset) valueLine = " " * max(0,valueIndent) + stringValue slash = "\\" if inverted else "/" backslash = "/" if inverted else "\\" uLine = "¯" if inverted else "_" # build left side of link line leftLink = "" if not leftNode else ( " " * firstLeftWidth + uLine * leftLinkExtra + slash) # build right side of link line (includes blank spaces under top node value) rightLinkOffset = linkSpacing + valueOffset * (1 - leftLinkBar) rightLink = "" if not rightNode else ( " " * rightLinkOffset + backslash + uLine * rightLinkExtra ) # full link line (will be empty if there are no sub nodes) linkLine = leftLink + rightLink # will need to offset left side lines if right side sub nodes extend beyond left margin # can happen if left subtree is shorter (in height) than right side subtree leftIndentWidth = max(0,firstRightIndent - rightNodePosition) leftIndent = " " * leftIndentWidth indentedLeftLines = [ (leftIndent if line else "") + line for line in leftSubLines ] # compute distance between left and right sublines based on their value position # can be negative if leading spaces need to be removed from right side mergeOffsets = [ len(line) for line in indentedLeftLines ] mergeOffsets = [ leftIndentWidth + rightNodePosition - firstRightIndent - w for w in mergeOffsets ] mergeOffsets = [ p if rightSubLines[i] else 0 for i,p in enumerate(mergeOffsets) ] # combine left and right lines using computed offsets # * indented left sub lines # * spaces between left and right lines # * right sub line with extra leading blanks removed. mergedSubLines = zip(range(len(mergeOffsets)), mergeOffsets, indentedLeftLines) mergedSubLines = [ (i,p,line + (" " * max(0,p)) ) for i,p,line in mergedSubLines ] mergedSubLines = [ line + rightSubLines[i][max(0,-p):] for i,p,line in mergedSubLines ] # Assemble final result combining # * node value string # * link line (if any) # * merged lines from left and right sub trees (if any) treeLines = [leftIndent + valueLine] + ( [] if not linkLine else [leftIndent + linkLine] ) + mergedSubLines # invert final result if requested treeLines = reversed(treeLines) if inverted and isTop else treeLines # return intermediate tree lines or print final result if isTop : print("\n".join(treeLines)) else : return treeLines </code></pre> <p>Here's an example of the kind of output it produces, using a simple TreeNode class.</p> <pre><code>class TreeNode: def __init__(self,rootValue): self.value = rootValue self.left = None self.right = None def addValue(self,newValue): if newValue == self.value: return self if newValue &lt; self.value: if self.left : return self.left.addValue(newValue) self.left = TreeNode(newValue) return self.left if self.right : return self.right.addValue(newValue) self.right = TreeNode(newValue) return self.right def printTree(self): printBTree(self,lambda n:(str(n.value),n.left,n.right)) root = TreeNode(80) root.addValue(50) root.addValue(90) root.addValue(10) root.addValue(60) root.addValue(30) root.addValue(70) root.addValue(55) root.addValue(5) root.addValue(35) root.addValue(85) root.printTree() </code></pre> <p>This produces the following output:</p> <pre><code># 80 # ___/ \___ # 50 90 # __/ \__ / # 10 60 85 # / \ / \ # 5 30 55 70 # \ # 35 </code></pre> <p>The function is generic enough to process binary tree structures that are not stored in an object hierarchy. Here's an example of how it can be used to print from a list containing a heap tree:</p> <pre><code>def printHeapTree(tree, inverted=False): def getNode(index): left = index * 2 + 1 right = index * 2 + 2 left = left if left &lt; len(tree) and tree[left] else None right = right if right &lt; len(tree) and tree[right] else None return (str(tree[index]), left, right) printBTree(0,getNode,inverted) formula = ["+","4","*",None,None,"2","75"] printHeapTree(formula) # + # / \ # 4 * # / \ # 2 75 </code></pre> <p>The function will automatically adjust the indentations for wider labels : </p> <pre><code>family = [ "Me","Paul","Rosa","Vincent","Jody","John","Kate"] printHeapTree(family) # Me # ___/ \___ # Paul Rosa # / \ / \ # Vincent Jody John Kate </code></pre> <p>It can also print the tree upside down (as would be appropriate for a family tree):</p> <pre><code>printHeapTree(family,inverted=True) # Vincent Jody John Kate # \ / \ / # Paul Rosa # ¯¯¯\ /¯¯¯ # Me </code></pre> <br /><br /><br /><h3>回答2:</h3><br /><p>Well to begin with you should read PEP8 code convention for python, as it says function, attributes and variables should be in snake_case.</p> <p>You are printing in an iterative way so that means you just can't print it in an isosceles triangle because you cannot know what is the size of the base (the lowest part of the tree), in an iterative way you should print it like a triangle with 90 degrees angle.</p> <p>Or you could gather all of the information into a lists or a strings and format that later and print it. Think about the head and then the children with lines between them.</p> <br /><br /><br /><h3>回答3:</h3><br /><p>A simple and rough one:</p> <pre><code>from collections import deque def print_tree(root): res = [] q = deque([root]) while q: row = [] for _ in range(len(q)): node = q.popleft() if not node: row.append("#") continue row.append(node.val) q.append(node.left) q.append(node.right) res.append(row) rows = len(res) base = 2**(rows) for r in range(rows): for v in res[r]: print("." * (base), end = "") print(v, end = "") print("." * (base - 1), end = "") print("|") base //= 2 print_tree(root) </code></pre> <br /><br /><p>来源:<code>https://stackoverflow.com/questions/48850446/how-to-print-a-binary-tree-in-as-a-structure-of-nodes-in-python</code></p></div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field--label">标签</div> <div class="field--items"> <div class="field--item"><a href="/tag/python" hreflang="zh-hans">python</a></div> <div class="field--item"><a href="/tag/binary-tree" hreflang="zh-hans">binary-tree</a></div> <div class="field--item"><a href="/tag/tree-traversal" hreflang="zh-hans">tree-traversal</a></div> </div> </div> Wed, 13 May 2020 23:25:17 +0000 倾然丶 夕夏残阳落幕 3642632 at http://www.e-learn.cn How to print a binary tree in as a structure of nodes in Python http://www.e-learn.cn/topic/3642621 <span>How to print a binary tree in as a structure of nodes in Python</span> <span><span lang="" about="/user/20" typeof="schema:Person" property="schema:name" datatype="">这一生的挚爱</span></span> <span>2020-05-14 07:19:31</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><h3>问题</h3><br /><p>I have a python code to convert a string mathematical expression into a binary tree and order the nodes of the tree so the left child will be always smaller than the right child. I want to print the binary tree in the following order. </p> <p>For example consider the mathematical expression ((2 * 75) / 4). buildParseTree() converts the string expression into a tree and printNodeInLevels() rearranges the nodes so left child is smaller than the right right child at each level. Operands &lt; operators and operators are orders as '+' &lt; '-' &lt; '*' &lt; '/'. If the structure of the tree is like this</p> <pre><code> + /\ 4 * /\ 2 75 </code></pre> <p>I want to print it as follows. How should I go about this? Because the length of the mathematical expressions vary all the time e.g (24 * 2), ((5 - 1) * (2 / 3)), (20 - (5 + 4)) etc</p> <pre><code>Node("+") #root .addkid(Node("*") #right child at level 1 .addkid(Node("75")) #right child at level 2 .addkid(Node("2")) #left child at level 2 ) .addkid(Node("4")) #left child at level 1 </code></pre> <p>I have worked out the method to print nodes by their levels as in an in-order traversal pattern.If I call the method as follows it will print the following:</p> <pre><code>pt = buildParseTree("( ( 2 * 74 ) / 4 )") printNodesInLevels(pt) </code></pre> <p>output:</p> <pre><code>/ 4 * 2 74 </code></pre> <br /><h3>回答1:</h3><br /><p>Here is a function I created to print any binary tree structure.</p> <p>It is very generic and only needs a starting node (root) and a function (or lambda) to obtain a label and the left/right children nodes:</p> <p>You would typically use it like this on your Node class:</p> <pre><code>printBTree(rootNode,lambda n: (n.operand, n.left, n.right) ) # assuming the Node class has a string property named operand # and left,right properties that return a Node or None </code></pre> <p>A quadratic equation (-b +/- sqrt(b**2 - 4*a*c))/(2*a) could then print like this:</p> <pre><code># / # ___/ \__ # +/- * # / \ / \ # - sqrt 2 a # \ \ # b - # __/ \_ # ** * # / \ / \ # b 2 4 * # / \ # a c </code></pre> <p>Here is the printBTree function :</p> <pre><code>import functools as fn def printBTree(node, nodeInfo=None, inverted=False, isTop=True): # node value string and sub nodes stringValue, leftNode, rightNode = nodeInfo(node) stringValueWidth = len(stringValue) # recurse to sub nodes to obtain line blocks on left and right leftTextBlock = [] if not leftNode else printBTree(leftNode,nodeInfo,inverted,False) rightTextBlock = [] if not rightNode else printBTree(rightNode,nodeInfo,inverted,False) # count common and maximum number of sub node lines commonLines = min(len(leftTextBlock),len(rightTextBlock)) subLevelLines = max(len(rightTextBlock),len(leftTextBlock)) # extend lines on shallower side to get same number of lines on both sides leftSubLines = leftTextBlock + [""] * (subLevelLines - len(leftTextBlock)) rightSubLines = rightTextBlock + [""] * (subLevelLines - len(rightTextBlock)) # compute location of value or link bar for all left and right sub nodes # * left node's value ends at line's width # * right node's value starts after initial spaces leftLineWidths = [ len(line) for line in leftSubLines ] rightLineIndents = [ len(line)-len(line.lstrip(" ")) for line in rightSubLines ] # top line value locations, will be used to determine position of current node &amp; link bars firstLeftWidth = (leftLineWidths + [0])[0] firstRightIndent = (rightLineIndents + [0])[0] # width of sub node link under node value (i.e. with slashes if any) # aims to center link bars under the value if value is wide enough # # ValueLine: v vv vvvvvv vvvvv # LinkLine: / \ / \ / \ / \ # linkSpacing = min(stringValueWidth, 2 - stringValueWidth % 2) leftLinkBar = 1 if leftNode else 0 rightLinkBar = 1 if rightNode else 0 minLinkWidth = leftLinkBar + linkSpacing + rightLinkBar valueOffset = (stringValueWidth - linkSpacing) // 2 # find optimal position for right side top node # * must allow room for link bars above and between left and right top nodes # * must not overlap lower level nodes on any given line (allow gap of minSpacing) # * can be offset to the left if lower subNodes of right node # have no overlap with subNodes of left node minSpacing = 2 rightNodePosition = fn.reduce(lambda r,i: max(r,i[0] + minSpacing + firstRightIndent - i[1]), \ zip(leftLineWidths,rightLineIndents[0:commonLines]), \ firstLeftWidth + minLinkWidth) # extend basic link bars (slashes) with underlines to reach left and right # top nodes. # # vvvvv # __/ \__ # L R # linkExtraWidth = max(0, rightNodePosition - firstLeftWidth - minLinkWidth ) rightLinkExtra = linkExtraWidth // 2 leftLinkExtra = linkExtraWidth - rightLinkExtra # build value line taking into account left indent and link bar extension (on left side) valueIndent = max(0, firstLeftWidth + leftLinkExtra + leftLinkBar - valueOffset) valueLine = " " * max(0,valueIndent) + stringValue slash = "\\" if inverted else "/" backslash = "/" if inverted else "\\" uLine = "¯" if inverted else "_" # build left side of link line leftLink = "" if not leftNode else ( " " * firstLeftWidth + uLine * leftLinkExtra + slash) # build right side of link line (includes blank spaces under top node value) rightLinkOffset = linkSpacing + valueOffset * (1 - leftLinkBar) rightLink = "" if not rightNode else ( " " * rightLinkOffset + backslash + uLine * rightLinkExtra ) # full link line (will be empty if there are no sub nodes) linkLine = leftLink + rightLink # will need to offset left side lines if right side sub nodes extend beyond left margin # can happen if left subtree is shorter (in height) than right side subtree leftIndentWidth = max(0,firstRightIndent - rightNodePosition) leftIndent = " " * leftIndentWidth indentedLeftLines = [ (leftIndent if line else "") + line for line in leftSubLines ] # compute distance between left and right sublines based on their value position # can be negative if leading spaces need to be removed from right side mergeOffsets = [ len(line) for line in indentedLeftLines ] mergeOffsets = [ leftIndentWidth + rightNodePosition - firstRightIndent - w for w in mergeOffsets ] mergeOffsets = [ p if rightSubLines[i] else 0 for i,p in enumerate(mergeOffsets) ] # combine left and right lines using computed offsets # * indented left sub lines # * spaces between left and right lines # * right sub line with extra leading blanks removed. mergedSubLines = zip(range(len(mergeOffsets)), mergeOffsets, indentedLeftLines) mergedSubLines = [ (i,p,line + (" " * max(0,p)) ) for i,p,line in mergedSubLines ] mergedSubLines = [ line + rightSubLines[i][max(0,-p):] for i,p,line in mergedSubLines ] # Assemble final result combining # * node value string # * link line (if any) # * merged lines from left and right sub trees (if any) treeLines = [leftIndent + valueLine] + ( [] if not linkLine else [leftIndent + linkLine] ) + mergedSubLines # invert final result if requested treeLines = reversed(treeLines) if inverted and isTop else treeLines # return intermediate tree lines or print final result if isTop : print("\n".join(treeLines)) else : return treeLines </code></pre> <p>Here's an example of the kind of output it produces, using a simple TreeNode class.</p> <pre><code>class TreeNode: def __init__(self,rootValue): self.value = rootValue self.left = None self.right = None def addValue(self,newValue): if newValue == self.value: return self if newValue &lt; self.value: if self.left : return self.left.addValue(newValue) self.left = TreeNode(newValue) return self.left if self.right : return self.right.addValue(newValue) self.right = TreeNode(newValue) return self.right def printTree(self): printBTree(self,lambda n:(str(n.value),n.left,n.right)) root = TreeNode(80) root.addValue(50) root.addValue(90) root.addValue(10) root.addValue(60) root.addValue(30) root.addValue(70) root.addValue(55) root.addValue(5) root.addValue(35) root.addValue(85) root.printTree() </code></pre> <p>This produces the following output:</p> <pre><code># 80 # ___/ \___ # 50 90 # __/ \__ / # 10 60 85 # / \ / \ # 5 30 55 70 # \ # 35 </code></pre> <p>The function is generic enough to process binary tree structures that are not stored in an object hierarchy. Here's an example of how it can be used to print from a list containing a heap tree:</p> <pre><code>def printHeapTree(tree, inverted=False): def getNode(index): left = index * 2 + 1 right = index * 2 + 2 left = left if left &lt; len(tree) and tree[left] else None right = right if right &lt; len(tree) and tree[right] else None return (str(tree[index]), left, right) printBTree(0,getNode,inverted) formula = ["+","4","*",None,None,"2","75"] printHeapTree(formula) # + # / \ # 4 * # / \ # 2 75 </code></pre> <p>The function will automatically adjust the indentations for wider labels : </p> <pre><code>family = [ "Me","Paul","Rosa","Vincent","Jody","John","Kate"] printHeapTree(family) # Me # ___/ \___ # Paul Rosa # / \ / \ # Vincent Jody John Kate </code></pre> <p>It can also print the tree upside down (as would be appropriate for a family tree):</p> <pre><code>printHeapTree(family,inverted=True) # Vincent Jody John Kate # \ / \ / # Paul Rosa # ¯¯¯\ /¯¯¯ # Me </code></pre> <br /><br /><br /><h3>回答2:</h3><br /><p>Well to begin with you should read PEP8 code convention for python, as it says function, attributes and variables should be in snake_case.</p> <p>You are printing in an iterative way so that means you just can't print it in an isosceles triangle because you cannot know what is the size of the base (the lowest part of the tree), in an iterative way you should print it like a triangle with 90 degrees angle.</p> <p>Or you could gather all of the information into a lists or a strings and format that later and print it. Think about the head and then the children with lines between them.</p> <br /><br /><br /><h3>回答3:</h3><br /><p>A simple and rough one:</p> <pre><code>from collections import deque def print_tree(root): res = [] q = deque([root]) while q: row = [] for _ in range(len(q)): node = q.popleft() if not node: row.append("#") continue row.append(node.val) q.append(node.left) q.append(node.right) res.append(row) rows = len(res) base = 2**(rows) for r in range(rows): for v in res[r]: print("." * (base), end = "") print(v, end = "") print("." * (base - 1), end = "") print("|") base //= 2 print_tree(root) </code></pre> <br /><br /><p>来源:<code>https://stackoverflow.com/questions/48850446/how-to-print-a-binary-tree-in-as-a-structure-of-nodes-in-python</code></p></div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field--label">标签</div> <div class="field--items"> <div class="field--item"><a href="/tag/python" hreflang="zh-hans">python</a></div> <div class="field--item"><a href="/tag/binary-tree" hreflang="zh-hans">binary-tree</a></div> <div class="field--item"><a href="/tag/tree-traversal" hreflang="zh-hans">tree-traversal</a></div> </div> </div> Wed, 13 May 2020 23:19:31 +0000 这一生的挚爱 3642621 at http://www.e-learn.cn How to detect circular reference in a Tree? http://www.e-learn.cn/topic/3522310 <span>How to detect circular reference in a Tree?</span> <span><span lang="" about="/user/215" typeof="schema:Person" property="schema:name" datatype="">我的梦境</span></span> <span>2020-03-23 08:18:05</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><h3>问题</h3><br /><p>I have a Node class as follows:</p> <pre><code>public class Node{ Object data; List&lt;Node&gt; children; } </code></pre> <p>I need to traverse this tree in post order and I am using Guava TreeTraverser for for the same. </p> <pre><code> TreeTraverser&lt;Node&gt; treeTraverser = new TreeTraverser&lt;Node&gt;() { @Override public Iterable&lt;Node&gt; children(Node node) { return node.children; } }; treeTraverser.postOrderTraversal(node); </code></pre> <p>The catch is that there chances that the given tree could have circular dependencies(means it could be a cyclic graph). What would be an efficient way to detect circular dependencies?</p> <br /><h3>回答1:</h3><br /><p>By definition, a tree is an acyclic connected graph. Therefore, there is no such thing as a tree with circular dependencies.</p> <p>You can find cycles in a graph by applying depth-first traversal, and looking for nodes that have been visited the way down. If you visit a node that you have seen during prior steps of DFS, the graph is <em>not</em> a tree.</p> <p>See this Q&amp;A for advanced cycle detection algorithms.</p> <br /><br /><br /><h3>回答2:</h3><br /><p>In simple words <code>Tree is a non cyclic data structure</code> and when there are cycles then it becomes a <code>Graph</code>.</p> <p></p> <p>Above is an example of a graph. You can represent it using Adjacency list or adjacency matrix. You can refer to http://krishnalearnings.blogspot.in/2015/11/basics-of-graph-in-computer-science.html for basics of Graphs.</p> <p>In the picture above we can represent it as below (In your question, you have used an adjacency list kind of representation).</p> <pre><code>int[][] graph = { {0,1,0,0,0,0}, {0,0,1,0,0,0}, {0,0,0,1,1,0}, {0,0,0,0,0,0}, {0,0,0,0,0,1}, {0,1,0,0,0,0}, }; </code></pre> <p>1 represents an edge from corresponding row numbered vertex to column numbered vertex.</p> <p>We can write a simple method to detect the presence of cycle and also print any one cycle in the graph.</p> <pre><code>static int[] cycleElements; static int cycleElementIndex = 0; static boolean cycleFound = false; static final int NEW = 0; static final int PUSHED = 1; static final int POPPED = 2; public static int findCycle(int[][] graph,int N, int u, int[] states){ for(int v = 0; v &lt; N; v++){ if(graph[u][v] == 1){ if(states[v] == PUSHED){ // cycle found cycleFound = true; return v; }else if(states[v] == NEW){ states[v] = PUSHED; int poppedVertex = findCycle(graph, N, v, states); states[v] = POPPED; if(cycleFound){ if(poppedVertex == u){ cycleElements[cycleElementIndex++] = v; cycleElements[cycleElementIndex++] = u; cycleFound = false; }else{ cycleElements[cycleElementIndex++] = v; return poppedVertex; } } } } } return -1; } public static void main(String[] args) { int N = 6; int[][] graph = { {0,1,0,0,0,0}, {0,0,1,0,0,0}, {0,0,0,1,1,0}, {0,0,0,0,0,0}, {0,0,0,0,0,1}, {0,1,0,0,0,0}, }; cycleElements = new int[N]; int[] states = new int[N]; states[0] = PUSHED; findCycle(graph,N,0,states); for(int i = 0; i &lt; cycleElementIndex; i++){ System.out.println(cycleElements[i]); } } </code></pre> <p>You can easily transform above approach to adjacency list if you wish, though representation does not matter much ( only adjacency list may save your space as compared to adjacency matrix) </p> <br /><br /><p>来源:<code>https://stackoverflow.com/questions/37907339/how-to-detect-circular-reference-in-a-tree</code></p></div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field--label">标签</div> <div class="field--items"> <div class="field--item"><a href="/tag/java" hreflang="zh-hans">java</a></div> <div class="field--item"><a href="/tag/data-structures" hreflang="zh-hans">data-structures</a></div> <div class="field--item"><a href="/tag/tree" hreflang="zh-hans">tree</a></div> <div class="field--item"><a href="/tag/guava" hreflang="zh-hans">Guava</a></div> <div class="field--item"><a href="/tag/tree-traversal" hreflang="zh-hans">tree-traversal</a></div> </div> </div> Mon, 23 Mar 2020 00:18:05 +0000 我的梦境 3522310 at http://www.e-learn.cn How to detect circular reference in a Tree? http://www.e-learn.cn/topic/3522308 <span>How to detect circular reference in a Tree?</span> <span><span lang="" about="/user/171" typeof="schema:Person" property="schema:name" datatype="">人走茶凉</span></span> <span>2020-03-23 08:18:02</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><h3>问题</h3><br /><p>I have a Node class as follows:</p> <pre><code>public class Node{ Object data; List&lt;Node&gt; children; } </code></pre> <p>I need to traverse this tree in post order and I am using Guava TreeTraverser for for the same. </p> <pre><code> TreeTraverser&lt;Node&gt; treeTraverser = new TreeTraverser&lt;Node&gt;() { @Override public Iterable&lt;Node&gt; children(Node node) { return node.children; } }; treeTraverser.postOrderTraversal(node); </code></pre> <p>The catch is that there chances that the given tree could have circular dependencies(means it could be a cyclic graph). What would be an efficient way to detect circular dependencies?</p> <br /><h3>回答1:</h3><br /><p>By definition, a tree is an acyclic connected graph. Therefore, there is no such thing as a tree with circular dependencies.</p> <p>You can find cycles in a graph by applying depth-first traversal, and looking for nodes that have been visited the way down. If you visit a node that you have seen during prior steps of DFS, the graph is <em>not</em> a tree.</p> <p>See this Q&amp;A for advanced cycle detection algorithms.</p> <br /><br /><br /><h3>回答2:</h3><br /><p>In simple words <code>Tree is a non cyclic data structure</code> and when there are cycles then it becomes a <code>Graph</code>.</p> <p></p> <p>Above is an example of a graph. You can represent it using Adjacency list or adjacency matrix. You can refer to http://krishnalearnings.blogspot.in/2015/11/basics-of-graph-in-computer-science.html for basics of Graphs.</p> <p>In the picture above we can represent it as below (In your question, you have used an adjacency list kind of representation).</p> <pre><code>int[][] graph = { {0,1,0,0,0,0}, {0,0,1,0,0,0}, {0,0,0,1,1,0}, {0,0,0,0,0,0}, {0,0,0,0,0,1}, {0,1,0,0,0,0}, }; </code></pre> <p>1 represents an edge from corresponding row numbered vertex to column numbered vertex.</p> <p>We can write a simple method to detect the presence of cycle and also print any one cycle in the graph.</p> <pre><code>static int[] cycleElements; static int cycleElementIndex = 0; static boolean cycleFound = false; static final int NEW = 0; static final int PUSHED = 1; static final int POPPED = 2; public static int findCycle(int[][] graph,int N, int u, int[] states){ for(int v = 0; v &lt; N; v++){ if(graph[u][v] == 1){ if(states[v] == PUSHED){ // cycle found cycleFound = true; return v; }else if(states[v] == NEW){ states[v] = PUSHED; int poppedVertex = findCycle(graph, N, v, states); states[v] = POPPED; if(cycleFound){ if(poppedVertex == u){ cycleElements[cycleElementIndex++] = v; cycleElements[cycleElementIndex++] = u; cycleFound = false; }else{ cycleElements[cycleElementIndex++] = v; return poppedVertex; } } } } } return -1; } public static void main(String[] args) { int N = 6; int[][] graph = { {0,1,0,0,0,0}, {0,0,1,0,0,0}, {0,0,0,1,1,0}, {0,0,0,0,0,0}, {0,0,0,0,0,1}, {0,1,0,0,0,0}, }; cycleElements = new int[N]; int[] states = new int[N]; states[0] = PUSHED; findCycle(graph,N,0,states); for(int i = 0; i &lt; cycleElementIndex; i++){ System.out.println(cycleElements[i]); } } </code></pre> <p>You can easily transform above approach to adjacency list if you wish, though representation does not matter much ( only adjacency list may save your space as compared to adjacency matrix) </p> <br /><br /><p>来源:<code>https://stackoverflow.com/questions/37907339/how-to-detect-circular-reference-in-a-tree</code></p></div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field--label">标签</div> <div class="field--items"> <div class="field--item"><a href="/tag/java" hreflang="zh-hans">java</a></div> <div class="field--item"><a href="/tag/data-structures" hreflang="zh-hans">data-structures</a></div> <div class="field--item"><a href="/tag/tree" hreflang="zh-hans">tree</a></div> <div class="field--item"><a href="/tag/guava" hreflang="zh-hans">Guava</a></div> <div class="field--item"><a href="/tag/tree-traversal" hreflang="zh-hans">tree-traversal</a></div> </div> </div> Mon, 23 Mar 2020 00:18:02 +0000 人走茶凉 3522308 at http://www.e-learn.cn Inorder tree traversal: Which definition is correct? http://www.e-learn.cn/topic/3265712 <span>Inorder tree traversal: Which definition is correct?</span> <span><span lang="" about="/user/15" typeof="schema:Person" property="schema:name" datatype="">假装没事ソ</span></span> <span>2020-01-20 14:22:42</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><h3>问题</h3><br /><p>I have the following text from an academic course I took a while ago about inorder traversal (they also call it pancaking) of a <strong>binary tree</strong> (not BST):</p> <p><em>Inorder tree traversal</em></p> <blockquote> <p>Draw a line around the outside of the tree. Start to the left of the root, and go around the outside of the tree, to end up to the right of the root. Stay as close to the tree as possible, but do not cross the tree. (Think of the tree — its branches and nodes — as a solid barrier.) The order of the nodes is the order in which this line passes underneath them. If you are unsure as to when you go “underneath” a node, remember that a node “to the left” always comes first.</p> </blockquote> <p>Here's the example used (slightly different tree from below)</p> <p></p><p></p><img class="b-lazy" data-src="https://i0.wp.com/farm4.static.flickr.com/3661/3624141531_094985f47e_o.png" data-original="https://i0.wp.com/farm4.static.flickr.com/3661/3624141531_094985f47e_o.png" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><p></p> <p>However when I do a search on google, I get a conflicting definition. For example the wikipedia example:</p> <p></p><p></p><img class="b-lazy" data-src="https://www.eimg.top/images/2020/03/28/c8d886daee94d55b3dafd41b0e620567.png" data-original="https://www.eimg.top/images/2020/03/28/c8d886daee94d55b3dafd41b0e620567.png" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><p></p> <blockquote> <p>Inorder traversal sequence: A, B, C, D, E, F, G, H, I (leftchild,rootnode,right node)</p> </blockquote> <p>But according to (my understanding of) definition #1, this should be</p> <blockquote> <p>A, B, D, C, E, F, G, I, H</p> </blockquote> <p><strong>Can anyone clarify which definition is correct?</strong> They might be both describing different traversal methods, but happen to be using the same name. I'm having trouble believing the peer-reviewed academic text is wrong, but can't be certain.</p> <br /><h3>回答1:</h3><br /><p>In my bad attempt at the drawing here's the order that shows how they should be picked. </p><p></p><img class="b-lazy" data-src="https://i0.wp.com/web.archive.org/web/20140926210320/https://imagebin.antiyes.com/images/0590294001233104834_3.jpg" data-original="https://i0.wp.com/web.archive.org/web/20140926210320/https://imagebin.antiyes.com/images/0590294001233104834_3.jpg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><p></p> <p>pretty much pick the node that is directly above the line being drawn,. </p> <br /><br /><br /><h3>回答2:</h3><br /><p>Forget the definitions, it's so much easier to just apply the algorithm:</p> <pre><code>void inOrderPrint(Node root) { if (root.left != null) inOrderPrint(root.left); print(root.name); if (root.right != null) inOrderPrint(root.right); } </code></pre> <p>It's just three lines. Rearrange the order for pre- and post- order.</p> <br /><br /><br /><h3>回答3:</h3><br /><p>If you read carefully you see that the first "definition" says to start <em>left</em> of the root and that the order of the nodes is determined by when you pass <em>under</em> them. So <code>B</code> is not the first node, as you pass it from the left on the way to <code>A</code>, then first pass <em>under</em> <code>A</code> after which you go up and pass <em>under</em> <code>B</code>. Therefore it seems that both definitions give the same result.</p> <br /><br /><br /><h3>回答4:</h3><br /><p>I personally found this lecture quite helpful. </p> <br /><br /><br /><h3>回答5:</h3><br /><p>Both definitions give the same result. Don't be fooled by the <em>letters</em> in the first example - look at the numbers along the path. The second example does use letters to denote the path - perhaps that is what is throwing you off.</p> <p>For example, in your example order showing how you thought the second tree would be traversed using the algorithm of the first one, you place "D" after "B" but you shouldn't because there is still a left-hand child node of D available (that's why the first item says "the order in which this line passes <strong>underneath</strong> them." </p> <br /><br /><br /><h3>回答6:</h3><br /><p>this may be late but it could be useful for anyone later .. u just need not to ignore the dummy or null nodes e.g the Node G has a left null node .. considering this null node will make every thing alright .. </p> <br /><br /><br /><h3>回答7:</h3><br /><p>The proper traversal would be: as far left as possible with leaf nodes (not root nodes)</p> <h2>Left Root Right</h2> <h2>A B NULL</h2> <h2>C D E</h2> <h2>Null F G</h2> <h2>H I NULL</h2> <p>F is root or left, i am not sure</p> <br /><br /><br /><h3>回答8:</h3><br /><p>I think the first binary tree with the root of <code>a</code> is a Binary tree which is not correctly constructed.</p> <p>Try to implement so that all the left side of the tree is less than the root and all the right side of the tree is greater than or equal to the root.</p> <br /><br /><br /><h3>回答9:</h3><br /><blockquote> <p>But according to (my understanding of) definition #1, this should be</p> <pre><code>A, B, D, C, E, F, G, I, H </code></pre> </blockquote> <p>Unfortunately, your understanding is wrong.</p> <p>Whenever you arrive at a node, you must descend to an available left node, before you look at the current node, then you look at an available right node. When you chose D before C, you didn't descend to the left node first.</p> <br /><br /><br /><h3>回答10:</h3><br /><p>Hey according to me as mentioned in wiki is correct the sequence for a inorder traversal is left-root-right.</p> <p>Till A, B, C, D, E, F i think you have understood already. Now after root F the next node is G that doesn't hav a left node but a right node so as per the rule (left-root-right) its null-g-right. Now I is the right node of G but I has a left node hence the traversal would be GHI. This is correct.</p> <p>Hope this helps.</p> <br /><br /><br /><h3>回答11:</h3><br /><p>For an inline tree traversal you have to keep in mind that the order of traversal is left-node-right. For the above diagram that you are conflicted on, your error occurs when you read a parent node before reading any leaf(children) nodes to the left.</p> <p>The proper traversal would be: as far left as possible with leaf nodes(A), return to parent node(B), move to the right, but since D has a child to its left you move down again(C), back up to C's parent(D), to D's right child(E), reverse back to the root(F), move to the right leaf(G), move to G's leaf but since it has a left leaf node move there(H), return to parent(I).</p> <p>the above traversal reads the node when I have it listed in parenthesis.</p> <br /><br /><br /><h3>回答12:</h3><br /><p>package datastructure;</p> <p>public class BinaryTreeTraversal {</p> <pre><code>public static Node&lt;Integer&gt; node; public static Node&lt;Integer&gt; sortedArrayToBST(int arr[], int start, int end) { if (start &gt; end) return null; int mid = start + (end - start) / 2; Node&lt;Integer&gt; node = new Node&lt;Integer&gt;(); node.setValue(arr[mid]); node.left = sortedArrayToBST(arr, start, mid - 1); node.right = sortedArrayToBST(arr, mid + 1, end); return node; } public static void main(String[] args) { int[] test = new int[] { 1, 2, 3, 4, 5, 6, 7 }; Node&lt;Integer&gt; node = sortedArrayToBST(test, 0, test.length - 1); System.out.println("preOrderTraversal &gt;&gt; "); preOrderTraversal(node); System.out.println(""); System.out.println("inOrderTraversal &gt;&gt; "); inOrderTraversal(node); System.out.println(""); System.out.println("postOrderTraversal &gt;&gt; "); postOrderTraversal(node); } public static void preOrderTraversal(Node&lt;Integer&gt; node) { if (node != null) { System.out.print(" " + node.toString()); preOrderTraversal(node.left); preOrderTraversal(node.right); } } public static void inOrderTraversal(Node&lt;Integer&gt; node) { if (node != null) { inOrderTraversal(node.left); System.out.print(" " + node.toString()); inOrderTraversal(node.right); } } public static void postOrderTraversal(Node&lt;Integer&gt; node) { if (node != null) { postOrderTraversal(node.left); postOrderTraversal(node.right); System.out.print(" " + node.toString()); } } </code></pre> <p>}</p> <p>package datastructure;</p> <p>public class Node {</p> <pre><code>E value = null; Node&lt;E&gt; left; Node&lt;E&gt; right; public E getValue() { return value; } public void setValue(E value) { this.value = value; } public Node&lt;E&gt; getLeft() { return left; } public void setLeft(Node&lt;E&gt; left) { this.left = left; } public Node&lt;E&gt; getRight() { return right; } public void setRight(Node&lt;E&gt; right) { this.right = right; } @Override public String toString() { return " " +value; } </code></pre> <p>}</p> <p>preOrderTraversal &gt;&gt; 4 2 1 3 6 5 7 inOrderTraversal &gt;&gt; 1 2 3 4 5 6 7 postOrderTraversal &gt;&gt; 1 3 2 5 7 6 4</p> <br /><br /><br /><h3>回答13:</h3><br /><pre><code>void inorder (NODE root) { if (root != NULL) { inorder (root-&gt;llink); printf ("%d\t", root-&gt;info); inorder (root-&gt;rlink); } } </code></pre> <p>This the most simplest approach to recursive definition of in-order traversal, just call this function in the main function to get the in-order traversal of a given binary tree.</p> <br /><br /><br /><h3>回答14:</h3><br /><p>It is correct for preorder,nt for inorder</p> <br /><br /><p>来源:<code>https://stackoverflow.com/questions/486039/inorder-tree-traversal-which-definition-is-correct</code></p></div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field--label">标签</div> <div class="field--items"> <div class="field--item"><a href="/tag/data-structures" hreflang="zh-hans">data-structures</a></div> <div class="field--item"><a href="/tag/binary-tree" hreflang="zh-hans">binary-tree</a></div> <div class="field--item"><a href="/tag/tree-traversal" hreflang="zh-hans">tree-traversal</a></div> </div> </div> Mon, 20 Jan 2020 06:22:42 +0000 假装没事ソ 3265712 at http://www.e-learn.cn Inorder tree traversal: Which definition is correct? http://www.e-learn.cn/topic/3265707 <span>Inorder tree traversal: Which definition is correct?</span> <span><span lang="" about="/user/95" typeof="schema:Person" property="schema:name" datatype="">。_饼干妹妹</span></span> <span>2020-01-20 14:22:19</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><h3>问题</h3><br /><p>I have the following text from an academic course I took a while ago about inorder traversal (they also call it pancaking) of a <strong>binary tree</strong> (not BST):</p> <p><em>Inorder tree traversal</em></p> <blockquote> <p>Draw a line around the outside of the tree. Start to the left of the root, and go around the outside of the tree, to end up to the right of the root. Stay as close to the tree as possible, but do not cross the tree. (Think of the tree — its branches and nodes — as a solid barrier.) The order of the nodes is the order in which this line passes underneath them. If you are unsure as to when you go “underneath” a node, remember that a node “to the left” always comes first.</p> </blockquote> <p>Here's the example used (slightly different tree from below)</p> <p></p><p></p><img class="b-lazy" data-src="https://i0.wp.com/farm4.static.flickr.com/3661/3624141531_094985f47e_o.png" data-original="https://i0.wp.com/farm4.static.flickr.com/3661/3624141531_094985f47e_o.png" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><p></p> <p>However when I do a search on google, I get a conflicting definition. For example the wikipedia example:</p> <p></p><p></p><img class="b-lazy" data-src="https://www.eimg.top/images/2020/03/28/da475d4ec37b9739cbd87fc386634171.png" data-original="https://www.eimg.top/images/2020/03/28/da475d4ec37b9739cbd87fc386634171.png" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><p></p> <blockquote> <p>Inorder traversal sequence: A, B, C, D, E, F, G, H, I (leftchild,rootnode,right node)</p> </blockquote> <p>But according to (my understanding of) definition #1, this should be</p> <blockquote> <p>A, B, D, C, E, F, G, I, H</p> </blockquote> <p><strong>Can anyone clarify which definition is correct?</strong> They might be both describing different traversal methods, but happen to be using the same name. I'm having trouble believing the peer-reviewed academic text is wrong, but can't be certain.</p> <br /><h3>回答1:</h3><br /><p>In my bad attempt at the drawing here's the order that shows how they should be picked. </p><p></p><img class="b-lazy" data-src="https://i0.wp.com/web.archive.org/web/20140926210320/https://imagebin.antiyes.com/images/0590294001233104834_3.jpg" data-original="https://i0.wp.com/web.archive.org/web/20140926210320/https://imagebin.antiyes.com/images/0590294001233104834_3.jpg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><p></p> <p>pretty much pick the node that is directly above the line being drawn,. </p> <br /><br /><br /><h3>回答2:</h3><br /><p>Forget the definitions, it's so much easier to just apply the algorithm:</p> <pre><code>void inOrderPrint(Node root) { if (root.left != null) inOrderPrint(root.left); print(root.name); if (root.right != null) inOrderPrint(root.right); } </code></pre> <p>It's just three lines. Rearrange the order for pre- and post- order.</p> <br /><br /><br /><h3>回答3:</h3><br /><p>If you read carefully you see that the first "definition" says to start <em>left</em> of the root and that the order of the nodes is determined by when you pass <em>under</em> them. So <code>B</code> is not the first node, as you pass it from the left on the way to <code>A</code>, then first pass <em>under</em> <code>A</code> after which you go up and pass <em>under</em> <code>B</code>. Therefore it seems that both definitions give the same result.</p> <br /><br /><br /><h3>回答4:</h3><br /><p>I personally found this lecture quite helpful. </p> <br /><br /><br /><h3>回答5:</h3><br /><p>Both definitions give the same result. Don't be fooled by the <em>letters</em> in the first example - look at the numbers along the path. The second example does use letters to denote the path - perhaps that is what is throwing you off.</p> <p>For example, in your example order showing how you thought the second tree would be traversed using the algorithm of the first one, you place "D" after "B" but you shouldn't because there is still a left-hand child node of D available (that's why the first item says "the order in which this line passes <strong>underneath</strong> them." </p> <br /><br /><br /><h3>回答6:</h3><br /><p>this may be late but it could be useful for anyone later .. u just need not to ignore the dummy or null nodes e.g the Node G has a left null node .. considering this null node will make every thing alright .. </p> <br /><br /><br /><h3>回答7:</h3><br /><p>The proper traversal would be: as far left as possible with leaf nodes (not root nodes)</p> <h2>Left Root Right</h2> <h2>A B NULL</h2> <h2>C D E</h2> <h2>Null F G</h2> <h2>H I NULL</h2> <p>F is root or left, i am not sure</p> <br /><br /><br /><h3>回答8:</h3><br /><p>I think the first binary tree with the root of <code>a</code> is a Binary tree which is not correctly constructed.</p> <p>Try to implement so that all the left side of the tree is less than the root and all the right side of the tree is greater than or equal to the root.</p> <br /><br /><br /><h3>回答9:</h3><br /><blockquote> <p>But according to (my understanding of) definition #1, this should be</p> <pre><code>A, B, D, C, E, F, G, I, H </code></pre> </blockquote> <p>Unfortunately, your understanding is wrong.</p> <p>Whenever you arrive at a node, you must descend to an available left node, before you look at the current node, then you look at an available right node. When you chose D before C, you didn't descend to the left node first.</p> <br /><br /><br /><h3>回答10:</h3><br /><p>Hey according to me as mentioned in wiki is correct the sequence for a inorder traversal is left-root-right.</p> <p>Till A, B, C, D, E, F i think you have understood already. Now after root F the next node is G that doesn't hav a left node but a right node so as per the rule (left-root-right) its null-g-right. Now I is the right node of G but I has a left node hence the traversal would be GHI. This is correct.</p> <p>Hope this helps.</p> <br /><br /><br /><h3>回答11:</h3><br /><p>For an inline tree traversal you have to keep in mind that the order of traversal is left-node-right. For the above diagram that you are conflicted on, your error occurs when you read a parent node before reading any leaf(children) nodes to the left.</p> <p>The proper traversal would be: as far left as possible with leaf nodes(A), return to parent node(B), move to the right, but since D has a child to its left you move down again(C), back up to C's parent(D), to D's right child(E), reverse back to the root(F), move to the right leaf(G), move to G's leaf but since it has a left leaf node move there(H), return to parent(I).</p> <p>the above traversal reads the node when I have it listed in parenthesis.</p> <br /><br /><br /><h3>回答12:</h3><br /><p>package datastructure;</p> <p>public class BinaryTreeTraversal {</p> <pre><code>public static Node&lt;Integer&gt; node; public static Node&lt;Integer&gt; sortedArrayToBST(int arr[], int start, int end) { if (start &gt; end) return null; int mid = start + (end - start) / 2; Node&lt;Integer&gt; node = new Node&lt;Integer&gt;(); node.setValue(arr[mid]); node.left = sortedArrayToBST(arr, start, mid - 1); node.right = sortedArrayToBST(arr, mid + 1, end); return node; } public static void main(String[] args) { int[] test = new int[] { 1, 2, 3, 4, 5, 6, 7 }; Node&lt;Integer&gt; node = sortedArrayToBST(test, 0, test.length - 1); System.out.println("preOrderTraversal &gt;&gt; "); preOrderTraversal(node); System.out.println(""); System.out.println("inOrderTraversal &gt;&gt; "); inOrderTraversal(node); System.out.println(""); System.out.println("postOrderTraversal &gt;&gt; "); postOrderTraversal(node); } public static void preOrderTraversal(Node&lt;Integer&gt; node) { if (node != null) { System.out.print(" " + node.toString()); preOrderTraversal(node.left); preOrderTraversal(node.right); } } public static void inOrderTraversal(Node&lt;Integer&gt; node) { if (node != null) { inOrderTraversal(node.left); System.out.print(" " + node.toString()); inOrderTraversal(node.right); } } public static void postOrderTraversal(Node&lt;Integer&gt; node) { if (node != null) { postOrderTraversal(node.left); postOrderTraversal(node.right); System.out.print(" " + node.toString()); } } </code></pre> <p>}</p> <p>package datastructure;</p> <p>public class Node {</p> <pre><code>E value = null; Node&lt;E&gt; left; Node&lt;E&gt; right; public E getValue() { return value; } public void setValue(E value) { this.value = value; } public Node&lt;E&gt; getLeft() { return left; } public void setLeft(Node&lt;E&gt; left) { this.left = left; } public Node&lt;E&gt; getRight() { return right; } public void setRight(Node&lt;E&gt; right) { this.right = right; } @Override public String toString() { return " " +value; } </code></pre> <p>}</p> <p>preOrderTraversal &gt;&gt; 4 2 1 3 6 5 7 inOrderTraversal &gt;&gt; 1 2 3 4 5 6 7 postOrderTraversal &gt;&gt; 1 3 2 5 7 6 4</p> <br /><br /><br /><h3>回答13:</h3><br /><pre><code>void inorder (NODE root) { if (root != NULL) { inorder (root-&gt;llink); printf ("%d\t", root-&gt;info); inorder (root-&gt;rlink); } } </code></pre> <p>This the most simplest approach to recursive definition of in-order traversal, just call this function in the main function to get the in-order traversal of a given binary tree.</p> <br /><br /><br /><h3>回答14:</h3><br /><p>It is correct for preorder,nt for inorder</p> <br /><br /><p>来源:<code>https://stackoverflow.com/questions/486039/inorder-tree-traversal-which-definition-is-correct</code></p></div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field--label">标签</div> <div class="field--items"> <div class="field--item"><a href="/tag/data-structures" hreflang="zh-hans">data-structures</a></div> <div class="field--item"><a href="/tag/binary-tree" hreflang="zh-hans">binary-tree</a></div> <div class="field--item"><a href="/tag/tree-traversal" hreflang="zh-hans">tree-traversal</a></div> </div> </div> Mon, 20 Jan 2020 06:22:19 +0000 。_饼干妹妹 3265707 at http://www.e-learn.cn