Are there examples of recursion using only heap are开发者_运维百科a?
In C, function call-based recursion always uses the stack, almost by definition.
If you are willing to convert your recursion to iteration, then it is possible to use only heap space, but that isn't really recursion. You would do so by implementing a stack in the heap.
Certain problems can use tail recursion, which repeatedly overwrites the same area of the stack.
You could do something crazy like malloc a new area, turn off interrupts and just about everything else (not possible on many systems) and set your stack pointer to that malloc area. You are technically still playing with a stack, but that stack location is now on the heap. Not a good idea to do, but it can work on some embedded type systems where you have this level of control.
In many implementations, arguments to a function call are stored on the stack. Information such as the address to return to may also be stored on the stack. Thus having a recursive function without using the stack may not be feasible.
Check your compiler documentation to see if a function can be called without using any room on the stack. If so, you are on your way.
In order for a function to be recursive, it must call itself at least once. When it calls itself, it places a pointer to itself on the stack for the recursive call's return. The stack, of course, is not the heap, and therefore a recursive function which uses only the heap is not possible.
(At least, not in C. Functional languages are optimized to re-use stack space and not allocate pointers for return calls)
Yes, it is possible to implement recursion using only the heap, and in some cases it's very desirable. For instance, see Stackless Python. One of the prime benefits of this is that an entire thread can become serializable and you can literally ship a thread from one host to another (even of a different architecture & operating system!).
I do it this way :
- implement a Queue as a singly-linked list of (object, state) pairs
- Insert a root (object, state) pair indicating where the recursion is to begin
then...
- For each (object, state) node in the Queue:
- | Call object.Recurse (state)
- | Object processes the state and adds child nodes/states to the Queue as necessary
- Move to next pair until end of Queue
Usually, I implement this as a utility class "Recursor" Objects implement the interface "IRecursable"
The Recursor class can be asked to recurse Depth-First or Width-First.
My implementation also calls RecursionBegin() and RecursionEnd() on the root node, so that the class being recursed can handle any initialisation and cleanup code required.
The recursed class can also have the root notified of each called peer - allowing it to see :
RecursionBegin() - Called once, before recursion starts.
RecursionElement() - Called multiple times (optional).
RecursionEnd() - Called once, after recursion ends.
These methods are a part of the IRecursable interface and can be overridden to allow the class to be flexible in how it uses the recurser.
But there is a more concise method
Sometimes I move these utilities into a single class called Recursable that combines the features of class Recursor and interface IRecursable… or combine them fully into the object class meaning that the class to be recursed becomes self-recursable, without any need for supporting classes.
Hope that helps someone make a start on converting Recursive algorithms to Heap-based algorithms... and avoid clobbering the stack or causing nasty Stack-Overflows
TBH, recursion is evil and should be avoided like the plague! (except where your language allows true tail-call recursion)
… respect the Stack, it is a precious resource!!!
精彩评论