TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

The Great Tree-List Recursion Problem

47 点作者 lrsjng大约 6 年前

8 条评论

StefanKarpinski大约 6 年前
&lt;rant on pointer-heavy data structures&gt;<p>The continuing emphasis on pointer-heavy data structures in computer science curricula is really doing a massive disservice to students and all the employers that go on to hire those students. Pointer-heavy data structures are TERRIBLE on modern hardware. They were great back in the era when pointers were small (≤32 bits) and unpredictable memory access was roughly the same speed as CPU operations. We have left that era long ago. Today pointers are a whopping 64 bits and looking up your next node through a pointer is so slow that it&#x27;s the CPU equivalent of taking a ten year sabbatical.<p>For example: at what size does it become better to use a list rather than a vector when doing lots of insertions and deletions which are O(1) for lists and O(n) for vectors? NEVER. It is always better to use a vector. Don&#x27;t take if from me, this is according to Bjarne Stroustrup:<p><a href="https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=YQs6IC-vgmo" rel="nofollow">https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=YQs6IC-vgmo</a><p>Pointer-heavy data structures like linked lists are so bad for memory locality and storage overhead on modern hardware that it is impossible for them to catch up with contiguous memory vectors.<p>There are still situations where you need a tree but if you do, try very hard to use a representation like a binary array heap where the child links are implicit. Or if you must use &quot;pointers&quot; consider allocating all the values in a contiguous block and storing the link structure separately as 32-bit or smaller integer indexes into the data array. This at least improves the memory overhead and locality.<p>&lt;&#x2F;rant&gt;
评论 #19335770 未加载
评论 #19329710 未加载
kazinator大约 6 年前
Lol, I made a C library on this very topic years twenty years ago.<p><a href="http:&#x2F;&#x2F;www.kylheku.com&#x2F;~kaz&#x2F;austin.html" rel="nofollow">http:&#x2F;&#x2F;www.kylheku.com&#x2F;~kaz&#x2F;austin.html</a><p>&quot;Austin&quot; provides several container data structures in a single instance. With a function call it can be instructed to change the representation from any one of them to any other. E.g. a red-black tree can be told to become an AVL tree or sorted list and so on.<p>When I wrote this and announced it, a gentleman from Austria named Carl Van Tast contributed the AVL. I&#x27;ve not encountered him since; I remember telling him it was Van-Tast-ic. That could why I haven&#x27;t encountered him since.<p>The API is in &quot;udict.h&quot; (universal dictionary). The algorithms are enumerated thus:<p><pre><code> #define UDICT_LIST 0 #define UDICT_BST 1 #define UDICT_REDBLACK 2 #define UDICT_SPLAY 3 #define UDICT_AVL 4</code></pre>
cousin_it大约 6 年前
I think there&#x27;s a simpler solution, with one loop and no recursion, in O(n) time and O(1) space.<p><pre><code> static Node treeToCycle(Node root) { Node pseudoRoot = new Node(); pseudoRoot.left = null; pseudoRoot.right = root; Node tail = pseudoRoot; Node rest = root; while (rest != null) { if (rest.left == null) { rest.left = tail; tail = rest; rest = rest.right; } else { Node temp = rest.left; rest.left = temp.right; temp.right = rest; rest = temp; tail.right = temp; } } Node head = pseudoRoot.right; head.left = tail; tail.right = head; return head; }</code></pre>
评论 #19345393 未加载
benmmurphy大约 6 年前
there is is an alternative solution where you basically do it using an inorder traversal. it uses more stack space because it holds 1 node pointer in global state and two node pointers between the left and right recursion. While the building a list solution just holds a single node pointer during the left and right recursion.<p>lets say you want to convert a tree to single linked list in order then you can just do an in order traversal of the tree and keep track of the previous node and assign previous.left = current_node and this is fine because if you are at the successor to a node then the whole of the previous nodes left subtree has been visited because it is smaller and you will never need to follow the left pointer again.<p><pre><code> previous = nil in_order(tree) do |node| if previous previous.left = node end previous = node end </code></pre> however, you can&#x27;t do node.right = previous until you have visited the right subtree of the current node so you can&#x27;t use exactly the same code for a doubly linked list. however, if you do the fix up after you have finished processing the current node then it works fine. so if you have an iteration that will give you both an inorder and postorder callback and a way of sharing state between them you can just do the fixup in the postorder callback where it is safe.<p><pre><code> previous = nil head = nil multi_order(tree) do |node, order, state| if order == :inorder if previous fixup_state = [node, previous] else head = node end previous = node fixup_state #passed back into iterator and is return in post_order callback else if state fixup_node, fixup_previous = state fixup_previous.left = fixup_node fixup_node.right = fixup_previous end end end previous.next = head head.prev = previous head</code></pre>
eklitzke大约 6 年前
I did this exact problem on Leetcode the other day: <a href="https:&#x2F;&#x2F;leetcode.com&#x2F;problems&#x2F;convert-binary-search-tree-to-sorted-doubly-linked-list&#x2F;" rel="nofollow">https:&#x2F;&#x2F;leetcode.com&#x2F;problems&#x2F;convert-binary-search-tree-to-...</a>
评论 #19328074 未加载
mrburton大约 6 年前
Why wouldn&#x27;t you do a pre-order traversal and connect the appropriate nodes? When they say &quot;recursion is key&quot;, that&#x27;s actually misleading and this problem doesn&#x27;t seem hard at all.<p>What am I missing?
评论 #19325944 未加载
评论 #19324842 未加载
tristanj大约 6 年前
There is a follow up to this question. Given two (balanced) binary search trees, where the first BST has N nodes and the second has M nodes, how would you merge both trees in linear time and constant space?<p>(The solution is here if you are interested <a href="https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;7540546&#x2F;merging-2-binary-search-trees" rel="nofollow">https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;7540546&#x2F;merging-2-binary...</a> )
alkibiades大约 6 年前
don’t get what’s so great about this? was asked this during a facebook interview and solved it on the spot
评论 #19328066 未加载