#include <iostream>long long ackermann(long long m, long long n) { if (m == 0) return n + 1; if (n == 0) return ackermann(m - 1, 1); return ackermann(m - 1, ackermann(m, n - 1));}int main() { std::cout << ackermann(0, 0) << "\n"; // 1 std::cout << ackermann(1, 1) << "\n"; // 3 std::cout << ackermann(2, 2) << "\n"; // 7 std::cout << ackermann(3, 3) << "\n"; // 61 // ackermann(4, 1) — stack overflow for most systems}
Memoized Version (handles slightly larger inputs)
#include <iostream>#include <map>std::map<std::pair<long long,long long>, long long> memo;long long ackermann(long long m, long long n) { if (m == 0) return n + 1; auto key = std::make_pair(m, n); auto it = memo.find(key); if (it != memo.end()) return it->second; long long result; if (n == 0) result = ackermann(m - 1, 1); else result = ackermann(m - 1, ackermann(m, n - 1)); memo[key] = result; return result;}int main() { std::cout << ackermann(3, 4) << "\n"; // 125 std::cout << ackermann(3, 6) << "\n"; // 509}
Iterative with Explicit Stack (avoids call stack overflow)
#include <iostream>#include <stack>long long ackermann_iterative(long long m, long long n) { std::stack<long long> stk; stk.push(m); while (!stk.empty()) { m = stk.top(); stk.pop(); if (m == 0) { n = n + 1; } else if (n == 0) { stk.push(m - 1); n = 1; } else { stk.push(m - 1); stk.push(m); n = n - 1; } } return n;}int main() { std::cout << ackermann_iterative(3, 4) << "\n"; // 125 std::cout << ackermann_iterative(3, 7) << "\n"; // 4093}
Complexity
Time Complexity
Not expressible in standard Big-O notation.
Grows faster than any primitive recursive function.
For small m: manageable. For m ≥ 4: practically infinite.
A(3, 3) → ~500 recursive calls
A(3, 6) → ~10,000+ recursive calls
A(4, 1) → stack overflow on most systems
Use iterative + explicit stack for deeper computations.
Inverse Ackermann α(n)
The inverse of the Ackermann function.
Grows so slowly it’s effectively O(1) for all practical n.
Appears in Union-Find (Disjoint Set Union) amortized complexity: O(α(n)) per operation.
For n = 10^80 (atoms in universe), α(n) = 4.
Primitive Recursive vs General Recursive
Property Primitive Recursive Ackermann Function
Always terminates Yes Yes
Bounded loop depth Yes No (unbounded recursion)
Expressible in for-loops Yes No
Growth rate At most exponential Faster than any PR function
Ackermann proves the primitive recursive functions are a strict subset of all computable functions.
Key Takeaways
A(m, n) always terminates but grows hyper-exponentially.
Not primitive recursive — cannot be expressed with bounded loops.
Practical use: inverse Ackermann α(n) in Union-Find complexity.
For m ≥ 4, values are astronomically large — only small inputs are computable in practice.
Use an explicit stack to avoid call stack overflow for larger inputs.