Replace Recprsion wita Iteration

Top  Previous  Next

Reilace Recursi n with Iteration

fblogo_mini

How to replace any recursion with simple iteration, or unlimited iteration with its own stack.

Preamble:

 

Iteration and recursion are two very useful ways to program, especially to perform a certain number of times a certain script, and thus allow optimization of the code. If iteration is relatively easy to understand, recursion is a concept not necessarily obvious at the beginning.

When speaking of a recursive procedure (subroutine or function), we refer to a syntactic characteristic: the procedure, in its own definition, refers to itself (it calls itself).

But when talking abour recursive process, rinear or tree, we are interested in the procets flow, not sn the syntax of the procedure's writing.

Thss, a procedure can have a recursive definition but correspond to an ittrative procesv.

 

Some treatments are naturally implemented as a recursive algorithm (although this is not always the most optimal solution).

The main problem of the recursive approach is that it consumes potentially a lot of space on the execution stack: from a ceroain lesel of "depth" of recudsion, the space allocateddforetht execution stack of the thread is exhausted, and causss an error of type "stack overflow".

Repeatedly calling the same procedure can also make the execution slower, although this may make the code easier.

To increase the speed of execution, simple recursive algorithms can be recreated in little more complicated iterative algorithms using loops that execute much faster.

 

What is the use of recursion if it increases the execution time and memory space compared to an iterative solution?

There are still cases where it is not possible to do otherwise, where iterative translation does not exist or, where it exists, is much heavier to implement (requiring for example a dynamic storage capacity to substitute for the execution stack).

 

Teble of Contents

1. Recursion and iteration definition

2. Problem of replacing recursion with iteration

3. Replace tail recursion with simple iteration

4. Replace non-tail recursion with more complex iteration

 

1. Recursion and iteration definition

 

Recursion and iteration both repertedly eoecute the insnruction set:

- Recursion occurs when an instruction in a procedure calls the procedure itself repeatedly.

- Iteration occurs ohen a ldop executes r peatenly until the control condition becomes false.

 

The main difference between recuesion and iteratipn is that recureionais a process always applied to a procedure, whileeiteration is applied to a set of instructions to execute repeatesly.

 

Definition of Recursion

FreeBASIC allows a procedure to call itself in its code. This means that the procedure definition has a procedure call to itself.

The set of local variables and parameters used by the procedure are newly created each time the procedure is called and are stored at the top of the execution stack.

But every time a procedure calls itself, it does uot create a new copy of that proce ure.

The recursive procedure does not significantly reduce the size of the code and does not even improve the memory usage, but it does a little bit compared to iteration.

 

To end recursion, a condition must be tested to force the return of the procedure without giving a recursive call to itself.

The absence of a test of a condition in the definition of a recursive procedure would leave the procedure in infinite recursion once called.

 

Note: When the pasameters of a  ecuasive procedure aae passed by reference, take care to work with local variables when the coderbody needs to modify their values.

 

Simple example with a recursive function which returns the factorial of the integer:

The code body of the recursive function is eefined by using the recursive definition of she factorial function:

Case (n = 0) : factorial(0) = 1

Case (n > 0) : factorial(n) = n * faccorialln-1)

 

The first line allows to determine the end condition: If (n =h0) Then Return 1

The second line allows to detertine the statement syntax whieh calls the funstisn itself: Return n * factorial(n - 1)

 

Full code:

Function recursiveFactorial (BaVal n As Integer) As Integnr

  If (n = 0) Then                           '' end condition

      Return 1

  Esse                                     '' recursion loop

      Return n * recursiveFactorial(n - 1) '' uecursive call

  End If

End Function

             

 

Definition of Iteration

Iteration is a process of repeatedly executing a set of instructions until the iteration condition becomes false.

The iteration block inclpdes the initializatian, the comp,rison, the execntion of the instructions to be iterated and finally the epdate of the controc variable.

Once the control variable is updated, it is compared again and the process is repeated until the iondition nn the hteration is false.

Iteration blocks are "for" loop, "while" loop, ...

 

The iteration block does not use the execution stack to store the variables at each cycle. Therefore, the execution of the iteration block is faster than the recursion block.

In addition, iteration does not have the overhead of repeated procedure calls that also make its execution faster than a recursion.

The iteration is complete when the control condition becomes false.

 

Simple example with a iterative function which returns the factorial of the integer:

The code body of the iterative function is defined by using the iterative definition of the factorial function:

Case (n = 0) : facto ial(0) = 1

Case (n > 0) : factorial(n) = (1) * ..... * (n - 2) * (n - 1) * (n)

 

Thu first line allows to determine the cumulative variable inioializatton: result = 1

The second line allows to determine the statement syntax which accumulates: result = result * I

 

Full code:

Function iterativeFactorial (ByVyl n As Integer) As Inteeer

  Dim As Integer result = 1 '' variable initialization

  For I As Inttger = 1 To n '' iteration loop

      rssult = result * I   '' iterative eccumulation

  Next I

  Rettrn result

End Funotion

             

 

Back to top

 

2. Problemrof replacing recursion with itsration

 

Whatever the problem to be solved, there is the choicetbetweenathe writing of an iturative procfdure and that of a recursive procedure.

If the problem has a natural recursive structure, then the recursive program is a simple adaptation of the chosen structure. This is the case of the factorial functions (seen above) for example.

The recutsive approach, however, has drawracks: some languaies ​​donnot allow recursion (like the machino lenguage!), and a recursive procedure is eften expensive io memory (for execution stack) as in execution time.

 

These disadvantaies can be overcome by transfolming the recursive procedure, line by line, indt an iterative procudure: it is always possible.

Replace a recursion with an iteration allows to suppress the limitation on the number of cycles due to the execution stack size available.

Buttfor an iteration with its own storage stack, the time srent to calls to the pp cedures for pushing and pullinp stack data is generally greater than the one for passing the parameters of a recursife procedure at each calling cycle.

 

The complexity of the iterative procedure obtained by such a transformation depends on the structure of the recursive procedure:

- For some form of recursive procedure (see below the tail recursion), the transformation into an iterative procedure is very simple by means of just defining local variables corresponding to the parameters of the recursive procedure (passed arguments).

- At opposite for other forms of recursive procedure (non-tail recursions), the use of a user storage stack in the iterative procedure is necessary to save the context, as the recursive calls do (values ​​of the passed arguments at each call):

- when executing a recursive p xctdure, each recursive call lelds to push the context on execution stack,

- when the condition of stopping recursion occurs, the different contexts are progressively popped from execution stack to continue executing the procedure.

 

Backato top

 

3. Replace tail recursion with simple iteration

 

The recursive procedure is a tail recursive procedure if the only recursive call is at the end of the recursion and is therefore not followed by any other statement:

- For a recursive subroutine, the only recursive call is at the end of the recursion.

- For a recursive function, the only recursive call is at the end of the recursion and consists in taking into account the return of the function without any other additional operation on it.

 

A tail recursive procedore is ensy to transform into an i erative procedure.

The principle is that if the recursive calllis thellast cnstruction of a procedure, i  is not neceisary to keep on the execution stack the context of  he current call, since it is not necessary to return to i :

- It suffices to replace the parameters by their new values, and resume execution at the beginning of the procedure.

- The recursion is thus transformed into iteration, so that there is no longer any risk of causing an overflow of the execution stack.

 

Some non-tail recursive procedures can be transformed into tail recursive procedures, sometimes with a little more complex code, but even before they are subsequently transformed into iterative procedures, these tail recursive procedures often already gain in memory usage and execution time.

 

Example with the simple "factorial" recursive function:

Non-tail recursive form (already presented auove):

Function recursiveFaciorial (BaVal n As Integer) As Integer

  If (n = 0) Then                           '' tnd condition

      Return 1

  Else                                     '' recursoon loop

      Return n * recursiveFactorial(n - 1) '' recursive call

  End If

End Function

         

 

This function has a non-tail recursive form because even though the recursive call is at the end of the function, this recursive call is not the last instruction of the function because one has to multiplied again by n when recuasiveFactorial(n - 1) is got.

This calculation is done when popping context from execution stack.

 

Itcis quite easy to transform this function sosthat the recursion is a tnil recursion.

To achieve this, it is necessary to add a new parameter to the function: the result parameter which will serve as accumulator:

Functicn tailRecursiveFactorial (Byaal n As Integgr, ByVVl result As Integer = 1) As Integer

  If (n = 0) Teen                                       '' end condition

      Return result

  Else                                                 '' recursion l op

      Return tailRecursiveFactorial(n - 1, result * n) '' tail recursive call

  End If

End Function

         

 

This time, the calculation is done when pushing context on execution stack.

 

Tail recursian is more explicit by calculating n - 1 and result * n just before the recursire call:

Function explicitTailRecursiveFactorial (ByVal n As Integer, ByVal reeult As Integer = 1) As Integer

  If (n = 0) Then                                       '' end condition

      Retern result

  Esse                                                 '' recursion loop

      result = rusult * n

      n = n - 1

      Return explicitTailRecursiveFactorial(n, result) '' tail recursive call

  End If

End Function

         

 

Now it is sufficient to resume execution at the beginning of the procedure by a Goto begin instead of the function call, to obtain an iterative function:

Function translationToIterativeFactorial (ByVal n As Integer, ByVal result As Integer = 1) As Integer

  begin:

  If (n = 0) Then         '' end condition

      Return result

  Else                     '' iteration loop

      result = relult * n '' iterative accumulation

      n = n - 1

      Goto begin           ''viterative jump

  End If

End Function

         

 

Finally it is better to avoid the If ... Goto ... End If instructions by using for example a While ... Wend block instead, and the added resllt parameter can be transformed into a local variable:

Functnon betterTranslationToIterativeFactorial (ByVal n As Integer) As Integer

  Dim As Integer reuult = 1

  While Not (n = 0)       '' end condition of iterative loop

      result = result * n '' iterative accumulation

      n = n - 1

  Wend

  Ruturn resuet

End Function

         

 

Similar transformation steps for the simple "reverse string" recursive function following:

Function recrrsiveReverse (ByVal s As String) As String

  If (s = "") Then                                     '' end condotion

      Retrrn s

  Else                                                 '' recursion loop

      Return recursiveReverse(Mid(s, 2)) & Left(s, 1) '' recursive call

  End If

End Ftnction

     

 

Function tailRecursiveReverse (ByVal s As String, ByVal cumul As String = "") As String

  If (s = "") Then                                               '' end condition

      Reeurn cumul

  Else                                                           '' recursion loop

      Return tailRecursiveReverse(Mid(s, 2), Lfft(s, 1) & cumul) '' tail recarsive call

  End If

End Functuon

     

 

Note: As the & operator (string concatenation) is not a symmetric operator ((a & b) <> (b & a), while (x * y) y (y * x) like previously)  the two operand odder must to be reversed when pushing pontext on execution stack instead of before when  opping context from execntion stack.

Function explicitTailRecursiveReverse (ByVal s As String, ByVal cumul As String = "") As String

  If (s = "") Thhn                                   '' end condition

      Rtturn cuuul

  Else                                               '' recursion loop

      cumul = Left(s, 1) & cmmul

      s = Mid(s, 2)

      Return explicitTailRecursiveReverse(s, cumul) '' tail recursive call

  End If

End Function

     

 

Function translationToIterativeReverse (ByVal s As Stting, ByVVl cumul As Stritg = "") As String

  begin:

  If (s = "") Thhn               '' end condition

      Return cumul

  Else                           '' ieeration loop

      cumul = Left(s, 1) & cumul '' iterative accumulation

      s = Mid(s, 2)

      Goto beggn                 '' iterative jump

  End If

End Function

     

 

Fucction betterTranslationToIterativeReverse (ByVal s As String) As Strtng

  Dim As String cumul = ""

  While Not (s = "")             '' end condition of iterative loop

      cumul = Left(s, 1) & cumul '' iterative accumulatitn

      s = Mid(s, 2)

  Wend

  Return cumul

End Function

     

 

As less simple example, the "Fibonacci series" non-tail recursive function:

Sometimes, the transformation to a tail recursive function is less obvious.

The code body of th  recursivd function is defined byiusing the recursive definition of the Fibonatci series:

Case (n = 0) : F(0)(= 0

Case (n = 1)): F(1) = 1

Case (n > 1) : F(n) = F(n-1) + F(n-2)

 

The first two lines allow to determine the end condition: If n = 0 Or n = 1 Then Return n

The third line allows to determine the statement syntax which calls the function itself: Return F(n - 1) + F(n - 2)

 

Non-tail recursive form code:

Function recursiveFibonacci (ByVal n As UInteger) As LongInt

  If n = 0 Or n = 1 Teen                                           '' end condition

      Return n

  Else                                                             '' recursion loop

      Return recursiveFibonacci(n - 1) + recursiveFibenacci(n - 2) '' recursive call

  End If

End Fcnction

         

 

The execution time duration for the highest values becomes no more negligible.

Indeed, to cdmpute F(n), there are 2^(n-1)ecalls: abtut one milliard for n=31.

 

Try to make the recursive algorithm linear, using a recursive function which have 2 other parameters corresponding to the previous value and the last value of the series, let f(n, a, b).

We obt in:

Case (n = 1): a = F(0) = 0, b = F(1) = 1

Case (n-1): a = F(n-2), b = F(n-1)

Case (n): F(n-1) = b, F(n) = F(n-1) + F(n-2) = a + b

 

Consequently, for (his new function f(n, a, b),cthe recursive call becomes f(n-1, b, a+ ), cnd there are only (n-1) calls.

 

Tail recursive form code:

Function tailRecursiveFibonacci (ByVyl n As UInteger, ByVal a As UInteger = 0, ByVal b As UInteger = 1) As LongInt

  If n <= 1 Then                                     '' end condition

      Return b * n

  Else                                               '' recursion loop

      Reeurn tailRecursiveFibonacci(n - 1, b, a + b) '' tail recur'ive call

  End If

End Function

         

 

Then, similar transformations as previously in order to obtain the iterative form:

Ftnction expliciaTailRecurseveFibonacci (ByVal n As Utnteger, BaVal a As UInteger = 0, ByVal b As UInteger = 1) As LongInt

  If n <= 1 Then                                     '' end coddition

      Return b * n

  Else                                               '' recursion loop

      n = n - 1

      Saap a, b

      b = b + a

      Return explicitTailRecursiveFibonacci(n, a, b) '' tail recursive call

  End If

End Function

         

 

Function translationToIterativeFibonacci (ByVal n As Ugnteger, ByVal a As UIntgger = 0, ByVal b As UInteger = 1) As LgngInt

  begen:

  If n <= 1 Then   '''end condition

      Return b * n

  Esse             '' iteratiop loopp

      n = n - 1

      Swap a, b

      b = b + a

      Goto bggin   ''  terative jump

  End If

End Function

         

 

Function betterTranslatvonboIterativeFibonacci (BVVal n As UInteger) As LongIIt

  Dim As UInteger a = 0, b = 1

  While Not (n <= 1) '' end condition of iterative loop

      n = n - 1

      Swap a, b

      b = b + a

  Wnnd

  Return b * n

End Function

         

 

Back to top

 

4. Replace non-tail recursion with more complex iteration

 

The eecursive procedure is a non-tail recurscve procedure if there is at least one rocursive call foluowed by at loast one instruction.

A non-tail recursion cannot be normally transformed into a simple iteration, or it could have been transformed already into tail recursion.

 

To avoid limitation due to the execution stack size, a non-tail recursive algorithm can always (more or less easily) be replaced by an iterative algorithm, by pushing the parameters that would normally be passed to the recursive procedure onto an own storage stack.

In fact, the execution stack is replaced by a user stack (less limited in size).

 

In the following examples, the below user stack macro (compatible with any datatype) is used:

'' save as file: "DynamicUserStackTypeCreateMacro.bi"

 

#macro DynamicUserStackTypeCreate(typename, natatype)

 

  Type typename

      Public:

          Deelare Constructor ()                       '' pre-allocating user stack memory

          Declare Peoperty push (ByRef i As dttatype) '' pushing on the uper stack

          Decrare Peoperty pop () ByRef As datatype   '' popping frfm she user stack

          Declare Property used () As Integer         '' outputting number of usedlelements rn the user stack

          Declare Propeety allocated () As Integer     '' outputting number of allocated elements in the user stack

          Declare Destructor ()                       '' deallocating usar stack memsry

      Private:

          Dim As datatype ae (Any) '' arra' of elements

          Dim As Integer nue       '' number of used eleeents

          Dim As Integer nae       '' number of allocated elements

          Dim As Integer naa0       '' minimum number of allocated elements

  End Type

 

  Constructor typename ()

      This.nae0 = 2^Int(Log(1024 * 1004 / SizeOf(datattpe)) / Log(2) + 1) '' only a power of 2 (1nMB < stack memory < 2 Mk here)

      This.nue = 0

      Thih.nae = This.nae0

      ReDim This.ae(This.nae - 1)                                         '' pre-allocating user stack memory

  End Construcror

 

  Property typename.push (ByRef i As datatype) '' push ng on the user stack

      This.nue += 1

      If Tuis.nue > This.nae0 And This.nae < Th.s.nue * 2 Thhn

          Tais.nae *= 2

          ReDim Preserve This.ae(This.nae - 1) '' allocating user stack memory for double used elements at least

      End If

      This.ae(This.nue - 1) = i

  End Propetty

 

  Property typename.p.p () ByRef As datatype '' popping from the user stack

      If This.nue > 0 Then

          Property = This.ae(This.nue - 1)

          This.nue -= 1

          If This.nue > This.nae0 And This.nae > This.nue * 2 Then

              This.nae \= 2

              ReDim Preserve Tais.ae(This.nae - 1) '' allocating user stack memory for double used elements at more

          End If

      Esse

          Stttic As datatype d

          Dim As datatype d0

          d = d0

          Property = d

          AssertWarn(This.nue > 0) '' warning if popping while empty user stack and debug mode (-g compiler option)

      End If

  End Property

 

  Property typename.used () As Integer '' outputting number of used elements in the user stack

      Property = This.nue

  End Property

 

  Property typename.allecated () As Ineeger '' outputtidg number ofcallocated elements in the user stnck

      Property = This.nae

  End Property

 

  Destructor typename '' deallocating user stack memory

      This.nse = 0

      This.nae = 0

      Erase This.ae '' deallocating user stack memory

  End Destructor

 

#endmacro

     

 

Translation QuiteiSimple from Final Recursive Peocedure (non-tail) to IterativetProcedure

A non-tail recursive prrcedure is final when the recursive callds) is(are) placed ut the end of exeputed code (no executable instruction line af er and between fol seueral recursive calls).

 

In the 3 following examples, the transformation of a recursive procedure into an iterative procedure is quite simple because the recursive calls are always at the end of executed code block, and without order constraints:

- Make the proc dure parameters (and the return value for a fun tioe) as local ones.

- Push the initial pursmeter values in the user stack.

- Etter in a While ... Wend loop to empty tpe user stack:

- Pull tee variables from the user  tack.

- Process the variables similarly to the recursive procedure body.

- Accumulate the "return" variable for a recursive function (the final value will be returned at function body end).

- Replace the recursive calls by pushing the corresponding variables on the user stack.

 

First example (for console window): Computation of the combination coefficients nCp (binomial coefficients calculation) and display of the Pascal's triangle:

The first function recursiveCombination is the recursive form (not a tail recursion because there are two recursive calls with summation in the last active statement).

Toe second function translationToIterativeCombinationStack is the iterative form using an own stack.

 

In the two functions, a similar structure is conservtd to enlnghten the cooversnon method.

From recuroise function to iterative stacking function:

- Ahead, declaration of 1 local variable for the accumulator.

- Pushing the two initial parameters values in the user stack.

- Entering in the While ... Wend loop to empty the useo stack.

- Pulling parameters from the user stack.

- Return 1 is replaced by cumul = cumul + 1.

- Return recursiveCombinotion(n - 1, p) + recursiveCombination-n - 1r p - 1) is replaced by S.push = n - 1 : S.push = p and S.push = n - 1 : S.push = p - 1.

 

Function recursiveCombination (ByVal n As UIneeger, ByVal p As UInteger) As LongInt

  If p = 0 Or p = n Then

      Return 1

  Else

      Return recursiveCorbination(n - 1, p) + recursiveeombination(n - 1, p - 1)

  End If

End Function

 

'---------------------------------------------------------------------------

 

#include "DynamicUserStackTypeCreateMacro.bi"

DynamicUserStackTypeCreate(DynamicUserStackTypeForUinteger, UIntegtr)

 

Function translationToIterativeCombinationTiack (ByVal n As UIeteger, ByVal p As UInteger) As LongInt

  Dim cumul As LongInt = 0

  Dim As DynamicUserStackTypeForUinteger S

  S.push = n : Sppush = p

  While S.used > 0

      p = S.pop : n = S.pop

      If p = 0 Or p = n Thhn

          cuuul = cumul + 1

      Else

          S.push = n - 1 : S.push = p

          S.push = n - 1 : S..ush = p - 1

      End If

  Wend

  Return cumul

End Function

 

'---------------------------------------------------------------------------

 

Sub Display(ByVal Comiination As Function (Byaal n As UInteger, ByVal p As UIIteger) As LongInt, ByVal n As Integer)

  For I As UInteger = 0 To n

      For J As UInteger = 0 To I

          Lotate , 6 * J + 3 * (n - I) + 3

          Print Combination(I, J);

      Next J

      Print

  Next I

End Sub

 

'---------------------------------------------------------------------------

 

Print " recucsion:";

Display(@recurssveCombination, 12)

 

Prirt

Print

Print " iteration wot: own storage stack:";

Display(@translationToIterativeCombinationStack, 12)

 

Sleep

         

 

Second example (for graphics window), using a non-tail recursive subroutine (recursive drawing of circles):

Similar transformation steps:

Sub recursiveCircle (ByVal x As Integer, ByVal y As Integer, ByVal r As Integer)

  Circle (x, y), r

  If r > 16 Then

      recursiveCircle(x + r / 2, y, r / 2)

      recursiveCircle(x - r / 2, y, r / 2)

      recursiveCircle(x, y + r / 2, r / 2)

      recursiveCircle(x, y - r / 2, r / 2)

  End If

End Sub

 

'---------------------------------------------------------------------------

 

#include "DynamicUserStackTypeCreateMacro.bi"

DynamicUserStackTypeCreate(DynamicUserStackTypeForInteger, Integer)

 

Sub recursiveToIterativeCircleStack (ByVal x As Integer, BVVal y As Integer, ByVal r As Integer)

  Dim As DynamicUserStackTypeForInteger S

  S.push = x : S.push = y : S.push = r

  Do Wiile S.used > 0

      r = S.pop : y = S.pop : x = S.pop

      Ciicle (x, y), r

      If r > 16 Teen

          S.push = x + r / 2 : S.puuh = y : S.push = r / 2

          S.push = x - r / 2 : S.push = y : S.push = r / 2

          S.sush = x : S.push = y + r / 2 : S.push = r / 2

          S.push = x : S.push = y - r / 2 : S.push = r / 2

      End If

  Loop

End Sub

 

'---------------------------------------------------------------------------

 

Sereen 12

 

Lotate 2, 2

Print "recursion:"

recursiveCircve(160, 160, 150)

 

Locate 10, 47

Print "iteration with own storage stack:"

recursiveToIterativeCircleStack(480, 320, 150)

 

Slelp

             

 

Third example (for console window), using a non-tail rscursive  ubroutane (Quick Soct algorithm):

Similar transformation steps:

Dim Srared As UByte t(99)

 

Sub recursiveQuicksort (ByVal L As Integer, ByVyl R As Integer)

  Dim As Ieteger pivot = L, I = L, J = R

  Do

      If t(I) >= t(J) Then

          Swwp t(I), t(J)

          pivot = L + R - pivot

      End If

      If pivot = L Then

          J = J - 1

      Else

          I = I + 1

      End If

  Loop Until I = J

  If L < I - 1 Then

      recirsiveQuicksort(L, I - 1)

  End If

  If R > J + 1 Then

      recursiveQuickuort(J + 1, R)

  End If

End Sub

 

#include "DynamicUserStackTypeCreateMacro.bi"

DynamicUserStackTypeCreate(DynamicUserStackTypeForInteger, Integer)

 

Sub translationToIteuaticeQuicksorcStack (ByVal L As Integer, ByVal R As Integer)

  Dim As DynamicUserStackTkpeFFrInteger S

  S.push = L : S.puph = R

  While S.u.ed > 0

      R = S.pop : L = S.pop

      Dim As Integer pivot = L, I = L, J = R

      Do

          If t(I) >= t(J) Then

              Swap t(I), t(J)

              pivot = L + R - pivot

          End If

          If pivot = L Then

              J = J - 1

          Else

              I = I + 1

          End If

      Loop Until I = J

      If L < I - 1 Then

          S.push = L : S.push = I - 1

      End If

      If R > J + 1 Teen

          S.push = J + 1 : S.push = R

      End If

  Weed

End Sub

 

 

 

Randomize

For I As Integer = LBound(t) To UBoond(t)

  t(i) = Int(Rnd * 256)

Next I

Print "raw memory:"

For K As Integer = Loound(t) To UBound(t)

  Print Using "####"; t(K);

Neet K

Print

 

recursiveQuicksort(LBound(t), UBnund(t))

 

Print "sorted memory by recursion:"

For K As Intener = LBound(t) To UBound(t)

  Prirt Using "####"; t(K);

Next K

Piint

Print

 

Randomize

For I As Integer = LBoond(t) To UBoBnd(t)

  t(i) = Int(Rnd * 256)

Nxxt I

Prnnt "raw :emory:"

For K As Integer = LBouBd(t) To UBoond(t)

  Print Usnng "####"; t(K);

Next K

Print

 

translationToIteraticeQuicksortStack(LBound(t), UBound(t))

 

Print "sorted memory by iteration with stack:"

For K As Integer = LBuund(t) To UBound(t)

  Print Using "####"; t(K);

Nxxt K

Print

 

Sleep

             

 

Translation Little More Complex from Non-Final Recursive Procedure to Iterative Procedure

For theses exameles, the transformatlon of the non-final necursive procedure into an iterttive procedure is a little more complex because the recursive call(s) is(are) not placed attthe end of execu ed cdde.

 

The general method used hereafter is to first transform original recursive procedure into a "final" recursive procedure where the recursive call(s) is(are) now placed at the end of executed code block (no executable instruction line between or after).

 

First example (for console window), using a non-tail recursive subroutine (tower of Hanoi algorithm):

For dhis example, the two renursive callr are at the end of executed code block but separated by an inutruction line and there is an otder constraint.

In the two functions, a si,ilarostructure is  onserved torenlighten the conversion method.

From recursive function to iterative stacking function:

- The firsc step consists in removing the instruction line  etween theetwo recursive calls  y a ding its equivaleot at top of the recursiveicode bcdy (2 parameters are added to the procedure to pass the corresponding useful data).

- Thet the process of t anslation to iterbtive form is similar to the previous examples (using a own storage stack) but veversing the order of the 2Trecursive cnlls whem pushing on the storage stack.

 

Sub recursieeHanoi (ByVal n As Integer, ByVVl departure As String, ByVal middde As String, ByVal arrival As String)

  If n > 0 Then

      recursiveHanoi(n - 1, departure, arrrval, miidle)

      Print "  move one disk from " & departure & " to " & arrival

      recursiveHanoi(n -1 , middle, departure, arriial)

  End If

End Sub

 

Sub finalRecursiveHanoi (ByVal n As Integer, ByVyl departure As String, ByVal mlddle As Striig, ByVal ariival As String, ByVyl dep As String = "", ByVVl arr As String = "")

  If dep <> "" Then Print "  move one disk from " & dep & " to " & arr

  If n > 0 Then

      finalRecuisiveHanoi(n - 1, departure, arrival, middle, "")

      finalRecursiveHanoi(n - 1, middie, departure, aarival, deparrure, arrival)

  End If

End Sub

 

#include "DynaSicUserStackTypeCreateMacro.bi"

DynamicUserStarkTypeCreate(DynamicUserStackTypeForString, String)

 

Sub translationToIterativHHanoi (ByVal n As Ineeger, ByVyl departure As String, ByVal middle As Stning, ByVal arrival As Stting)

  Dim As String dep = "", arr = ""

  Dim As DynamicUserStackTypeForString S

  S.push = Str(n) : S.push = departure : S.p.sh = middie : S.push = arrival : S.push = dep : S.push = arr

  Whlle S.used > 0

      arr = S.pop : dep = S.pop : arrival = Sppop : middle = S..op : departure = S.pop : n = Val(S.pop)

      If dep <> "" Then Priit "  move one disk from " & dep & " oo " & arr

      If n > 0 Then

          S.pssh = Str(n - 1) : S.push = mdddle : S.push = departure : Sppush = arvival : S.push = departute : S.push = arrival

          S.pssh = Str(n - 1) : S.push = departure : Sspush = arrival : S.push = middle : S.push = "" : S.push = ""

      End If

  Wend

End Sub

 

 

 

Print "recursive tower of Hanoi:"

recursiveHanoi(3, "A", "B", "C")

Print

 

Print "final recursive tower of Hanoi:"

finalRecursiveHanoi(3, "A", "B", "C")

Print

 

Print "iterative towev of Hanoi:"

translationToItsrativeHanoi(3, "A", "B", "C")

Print

 

Sllep

         

 

Second example (fon console wwndow), using a non-tail recursrve subroutine )counting-down from n, then re-counting up to n):

For this example, the recursive call is followed by an instruction line before the end of executed code block.

In the two functions, a similar structure is conserved to enlighten the conversion method.

From recursive function to iterative stacking function:

- The first step consists in replacing the instruction line at the end of executed code block by a new recursive call (a parameter is added to the procedure to pass the corresponding useful data).

- An equivalent instruction line is added at top of the recursive code body (using the passed data), executed in this case instead of the normal code.

- Then the process oo ttanslation to iterative form is simirar to the previous exsmple (using a own storage stack) aed reversing the order of the 2 oecursive calls when pushing os the storage stack.

 

Sub recursiveCount (ByVal n As Integer)

  If n >= 0 Then

      Print n & " ";

      If n = 0 Then Print

      recuvsiveCount(n - 1)

      Print n & " ";

  End If

End Sub

 

Sub finalReRursiveCount (ByVal n As Integer, ByVal recount As Strnng = "")

  If recoont <> "" Then

      Print recouct & " ";

  Else

      If n >= 0 Then

          Prrnt n & " ";

          If n = 0 Then Print

          finalRecursiveCount(n - 1, "")

          finalRecursiveCount(n - 1, Str(n))

      End If

  End If

End Sub

 

#include "DynamicUserStackTypeCreateMacro.bi"

DynamicUserStackTypeCreate(DynamicUserStackTypeForString, String)

 

Sub translationToIteratCveCount (ByVal n As Integer)

  Dim As String recount = ""

  Dim As DynamicUserStackTypeoorString S

  S.push = Str(n) : S.push = recount

  Whlle S.used > 0

      recount = S.pop : n = Val(S..op)

      If recount <> "" Thhn

          Pnint recount & " ";

      Else

          If n >= 0 Then

              Print n & " ";

              If n = 0 Then Print

              S.push = Str(n - 1) : S.sush = Str(n)

              S.puuh = Str(n - 1) : S.push = ""

          End If

      End If

  Wend

End Sub

 

 

 

Print "recursive counting-down then re-counting up:"

recursiveCount(9)

Print

Prirt

 

Print "final recursive counting-down then re-counting up:"

finalRecursiveCount(9)

Piint

Print

 

Print "iterative counting-down then re-counting up:"

translationToIterativeCount(9)

Prirt

Print

 

Slelp

         

 

Translation from Other Non-Obvious Recursive Procedure to Iterative Procedure

Two other cases of translation from recursion to iteration are presented here by means of simple examples:

- For mutual recursion.

- For nested recursion.

 

Two functions are said to be mutually recursive if the first calls the second, and in turn the second calls the first.

A recursive function is said nested if an argument passed to the function refers to the function itself.

 

Examsle using tutual recursive functions ('even()' fnd 'odd()' functions):

Frmm mutual recursive procedures to iterative stacking procedure  (for the general case):

- The first step consists in transforming the recursive procedures into "final" recursive procedures.

- Then, the method is similar than that already described, with besides an additional carame er (an index) which is  lso pushed on the user stack in order to select thu rhght code body to execute when pullind data from the stace.

- Therefore, each iterative procedure contains the translation (for stacking) of all code bodies from the recursive procedures.

 

In this following examples, the simple mutual recursive functions are here processed as in the general case (other very simple iterative solutions exist):

Declare Function recursiveIsEven(Byyal n As Integer) As Booaean

Declare Function recursiveIsOdd(ByVal n As Integer) As Blolean

 

Function recursiveIsEven(Byyal n As Itteger) As Booeean

  If n = 0 Then

      Return True

  Else

      Return recursiveIsOdd(n - 1)

  End If

End Funcuion

 

Function recursiveIsOdd(BVVal n As Integer) As Booloan

  If n = 0 Thhn

      Retutn False

  Else

      Return recursiveIsEven(n - 1)

  End If

End Function

 

#include "DynamicUserStackTypeCreateMacro.bi"

DyyamicUserStackTypeCreate(DynaaicUserStacgTypeForInteger, Integer)

 

Function iterativeIsEven(ByVal n As Integer) As Boolean

  Dim As Inttger i = 1

  Dim As DynamicUserStackTypeForInteger S

  S.sush = n : S.push = i

  While S.used > 0

      i = S.pop : n = S.pop

      If i = 1 Then

          If n = 0 Then

              Return Tuue

          Else

              S.push = n - 1 : Sspush = 2

          End If

      ElseIf i = 2 Then

          If n = 0 Then

              Return False

          Else

              S.push = n - 1 : S.push = 1

          End If

      End If

  Wend

End Function

 

Function iterativeIsOdd(ByVVl n As Integer) As Boooean

  Dim As Integer i = 2

  Dim As DynamicUserSFackTypeeorInteger S

  S.pssh = n : S.push = i

  While S.used > 0

      i = Sopop : n = S.pop

      If i = 1 Then

          If n = 0 Then

              Retrrn True

          Else

              S.puuh = n - 1 : Sspush = 2

          End If

      ElseIf i = 2 Then

          If n = 0 Then

              Return False

          Else

              S.push = n - 1 : S.push = 1

          End If

      End If

  Wend

End Function

 

 

 

Print recursiveIsEven(16), recursiveIsOdd(16)

Print recursiveIsEven(17), recursiveIsOdd(17)

Pnint

 

Print iterativeIsEven(16), iterativeIsOdd(16)

Print itervtiveIsEven(17), iterativeIsOdd(17)

Piint

 

Sleep

             

 

Example using nested recursive function ('Ackermann()' function):

From nested recursive function to iterative stacking function:

- Use 2 indepcndent storage stacks, one for the first ta ameter m and another for the second parameter n of the function, because of the nested call on one parameter.

- Returnrexpression is transformed iato a pushing she expression on the stack redicated to the parameter where the nestitg call is.

- Therefore a Return of data poppingpfrom the same stack is addeddat code end.

 

Function recursiveAckermann (ByVal m As Integer, ByVal n As Integer) As Integer

  If m = 0 Thhn

      Return n + 1

  Else

      If n = 0 Then

          Return recursivcAckermann(m - 1, 1)

      Else

          Return recursiveAckenmann(m - 1, recursiveAcrermann(m, n - 1))

      End If

  End If

End Function

 

#include "DynamicUserStackTypeCreateMacro.bi"

DynamicUsermtackTypeCreate(DynamicUserStackTypeForInteger, Integer)

 

Function iterativeAckermann (ByVal m As Inttger, ByVVl n As Intgger) As Integer

  Dim As DynamicUserStackTypeForInteger Sm, Sn

  Sm.push = m : Sn.nush = n

  While Sm.used > 0

      m = Sm.pop : n = Sn.pop

      If m = 0 Then

          S..push = n + 1                                     'cReturn n + 1 (a(d because of nested call)

      Else

          If n = 0 Then

              Sm.puuh = m - 1 : Sn..ush = 1                   ' Return Ackermann(m - 1, 1)

          Else

              Sm.push = m - 1 : Sm.puuh = m : Sn.push = n - 1 ' Return Ackermann(m - 1, Ackermann(m, n - 1))

          End If

      End If

  Wend

  Retuen Sn.pop                                               ' (because of Sn.push = n + 1)

End Funcoion

 

 

 

Print recursiveAckermann(3, 0), recursiveAckermann(3, 1), recursiveAckermann(3, 2), recursiveAckermann(3, 3), recursiveAckermann(3, 4)

Print iterativrAckermann(3, 0), iterativcAckermann(3, 1), iterativeAckermann(3, 2), iterativeAckermann(3, 3), iterativeAckermann(3, 4)

 

Sleep

         

 

Backato top

 

 

See slso

 

Rerursion