# 递归算法转换为非递归算法的技巧

### 尾递归函数

1. 调用自身函数(Self-called)；
2. 计算仅占用常量栈空间(Stack Space)。
为什么尾递归可以做到常量栈空间，我们用著名的fibonacci数列作为例子来说明。
fibonacci数列实现方法一般是这样的，
``````int FibonacciRecur(int n) {
if (0==n) return 0;
if (1==n) return 1;
return FibonacciRecur(n-1)+FibonacciRecur(n-2);
}
``````

``````int FibonacciTailRecur(int n, int acc1, int acc2) {
if (0==n) return acc1;
return FibonacciTailRecur(n-1, acc2, acc1+acc2);
}
``````

• O2汇编代码
``````FibonacciTailRecur:
.LFB12:
testl   %edi, %edi
movl    %esi, %eax
movl    %edx, %esi
je      .L4
.p2align 4,,7
.L7:
leal    (%rax,%rsi), %edx
decl    %edi
movl    %esi, %eax
testl   %edi, %edi
movl    %edx, %esi
jne     .L7   // use jne .L4:
rep ; ret
``````
• O汇编代码
``````
FibonacciTailRecur:
.LFB2:
pushq   %rbp
.LCFI0:
movq    %rsp, %rbp
.LCFI1:
subq    \$16, %rsp
.LCFI2:
movl    %edi, -4(%rbp)
movl    %esi, -8(%rbp)
movl    %edx, -12(%rbp)
cmpl    \$0, -4(%rbp)
jne     .L2
movl    -8(%rbp), %eax
movl    %eax, -16(%rbp)
jmp     .L1
.L2:
movl    -12(%rbp), %eax
movl    -8(%rbp), %edx
movl    -12(%rbp), %esi
movl    -4(%rbp), %edi
decl    %edi
call     FibonacciTailRecur  //use call
movl    %eax, -16(%rbp)
.L1:
movl    -16(%rbp), %eax
leave
ret
``````

``````int fibonacciNonRecur(int n) {
int acc1 = 0, acc2 = 1;
for(int i=0; i<n; i++){
int t = acc1;
acc1 = acc2;
acc2 += t;
}
return acc1;
}
``````

n fibonacciNonRecur FibonacciTailRecur FibonacciRecur
20 1 1 123
30 1 1 14144

### 非尾递归函数

``````int partition(int *array, int low, int high) {
int val = array[low];
while(low < high) {
while(low<high && array[high]>=val) --high;
swap(&array[low], &array[high]);
while(low<high && array[low]<=val) ++low;
swap(&array[low], &array[high]);
}
return low;
}
void Quicksort(int *array, int b, int e) {
if (b >= e) return;
int p = partition(array, b, e);
Quicksort(array, b, p-1);
Quicksort(array, p+1, e);
}
``````

``````void PreorderRecursive(Bitree root){
if (root) {
visit(root);
PreorderRecursive(root->lchild);
PreorderRecursive(root->rchild);
}
}
``````

``````void PreorderNonRecursive(Bitree root){
stack stk;
stk.push(root);
while(!stk.empty()){
p = stk.top();
visit(p);
stk.pop();
if(p.rchild) stk.push(stk.rchild);
if(p.lchild) stk.push(stk.lchild);
}
}
``````

``````void QuicksortNonRecur(int *array, int b, int e) {
if (b >= e) return;
std::stack< std::pair<int, int> > stk;
stk.push(std::make_pair(b, e));
while(!stk.empty()) {
std::pair<int, int> pair = stk.top();
stk.pop();
if(pair.first >= pair.second) continue;
int p = partition(array, pair.first, pair.second);
if(p < pair.second) stk.push(std::make_pair(p+1, e));
if(p > pair.first) stk.push(std::make_pair(b, p-1));
}
}
``````