Dana Vrajitoru
C311 Programming Languages

General Transformation of Recursive Functions

General Transformation

Transformation

One Recursive Call
The stack stores the values of n. The variable r stores the result of the recursive function call.

(defun factorial1 (n)
  (let ((st ()) (r 1))
    (push n st)
    (while st
      (cond
       ((>= n 2)
        (setq n (- n 1))
        (push n st))
       (t (setq r (* r (pop st))))))
    r))

Second Example

f(n) = 2 n2 + 3 f(n-1), 	f(1) = 2

(defun f (n)
  (if (= n 1) 2
    (+ (* 2 n n)
       (* 3 (f (- n 1))))))

Iterative Version
Just like before, the stack stores n, while r is the result of the recursive call. Once we reach the base case and we start coming back up, we need a local variable to store the copy of n as we pop it from the stack, because the test for having reached the base case depends on it.

(defun f (n)
  (let ((st ()) (r 2) (ln 0))
    (push n st)
    (while st
      (cond
       ((> n 2)
        (setq n (- n 1))
        (push n st))
       (t (setq ln (pop st))
          (setq r (+ (* 2 ln ln)
                     (* 3 r))))))
    r))

Tree

Tree Structure

(defun root (T) "The root of the tree."
  (if T (car T)))
(defun left-subtree (T) 
  "The left subtree, also a list."
  (if (and T (cdr T))
    (car (cdr T)))) ; (cadr T)
(defun right-subtree (T) 
  "The right subtree, also a list."
  (if (> (length T) 2)
    (car (cdr (cdr T))))) ; (caddr T)

Print in Pre-Order

(defun print-preorder (T)
  "Prints the tree in preorder. Root - L - R"
  (if T
      (progn
        (mapc 'princ (list (root T) " "))
        (print-preorder (left-subtree T))
        (print-preorder (right-subtree T)))))
(setq S '(23 (51 (18) (33 (5))) (7 () (10))))
(print-preorder S)
23 51 18 33 5 7 10 nil

States

Iteration

(defun print-preor (T)
  "Prints the list in preorder without recursion."
  (let ((stackT nil) (frame nil) 
        (state nil))
    (push (cons T 'root) stackT)
    (while stackT
      (setq frame (pop stackT))
      (setq T (car frame) state (cdr frame))
      (if T
          (cond ((eq state 'root)
                 (my-print (root T) " ")
                 (push (cons T 'left) stackT))
                ((eq state 'left)
                 (push (cons T 'right) stackT)
                 (push (cons (left-subtree T) 
                             'root) stackT))
                ((eq state 'right)
                 (push (cons (right-subtree T) 
                             'root) stackT)))))))

Optimization

(defun print-preord (T)
  "An optimization of the function above."
  (let ((stackT ()))
    (while T
      (my-print (root T) " ")
      (push T stackT)
      (setq T (left-subtree T)))
    (while stackT
      (setq T (pop stackT))
      (setq T (right-subtree T))
      (while T
        (my-print (root T) " ")
        (push T stackT)
        (setq T (left-subtree T))))))