Một thủ tục hoặc hàm có thể chứa lời gọi đến một thủ tục khác bên trong nó. Bao gồm, chương trình con có thể gọi chính nó. Trong trường hợp này, máy tính không quan tâm. Anh ấy cũng như mọi khi, nhất quán thực hiện các mệnh lệnh mà anh ấy đã gặp từ trên xuống dưới.

Nếu bạn nhớ toán học, thì ở đó bạn có thể gặp nguyên lý quy nạp toán học. Nó như sau:

Một mệnh đề nào đó đúng với mọi n tự nhiên nếu
    1. nó hợp lệ cho n = 1 và
    2. từ tính hợp lệ của mệnh đề đối với bất kỳ n = k tự nhiên tùy ý nào, suy ra nó đúng với n = k+1.

Trong lập trình, kỹ thuật này được gọi là đệ quy

Đệ quy là một cách xác định một tập hợp các đối tượng theo chính tập hợp đó, dựa trên các trường hợp cơ sở đơn giản đã cho.


Đệ quy cũng sẽ được gọi là thủ tục (hàm) gọi chính nó trực tiếp hoặc thông qua các thủ tục và hàm khác
Một ví dụ về thủ tục đệ quy: thủ tục Rec(a: integer); bắt đầu     nếu một > 0 sau đó         Rec(a - 1);     viết(a); kết thúc; Về mặt sơ đồ, công việc của đệ quy có thể được biểu diễn bằng một sơ đồ

 
Thủ tục Rec() được thực thi với tham số 3. Sau đó, bên trong thủ tục có tham số 3, thủ tục có tham số 2 được gọi, v.v., cho đến khi thủ tục có tham số 0 được gọi. tham số 0 được gọi, cuộc gọi đệ quy đã có sẽ không xảy ra và thủ tục với tham số 0 sẽ in số 0 và kết thúc. Sau đó, điều khiển được chuyển trở lại quy trình với tham số 1, nó cũng hoàn thành công việc của mình bằng cách in số 1, v.v. trước thủ tục có tham số 3. 

Tất cả các thủ tục được gọi được lưu trữ trong bộ nhớ cho đến khi chúng hoàn thành công việc của mình. Số lượng các thủ tục đồng thời được gọi là độ sâu đệ quy.

Chúng ta đã thấy rằng đệ quy là việc thực hiện lặp đi lặp lại các lệnh chứa trong một chương trình con. Và điều này, đến lượt nó, tương tự như công việc của chu kỳ. Có những ngôn ngữ lập trình hoàn toàn không có cấu trúc vòng lặp, chẳng hạn như Prolog. 
Hãy thử mô phỏng hoạt động của vòng lặp for. 
Vòng lặp for chứa một biến đếm bước. Trong chương trình con đệ quy, một biến như vậy có thể được truyền dưới dạng tham số. //LoopImitation() thủ tục có hai tham số // Tham số đầu tiên – bộ đếm bước, tham số thứ hai – tổng số bước thủ tục LoopImitation(i, n: số nguyên); bắt đầu     writeln('Xin chao N ', i); // Toán tử được lặp lại với bất kỳ giá trị nào của i     nếu tôi < n sau đó //Cho đến khi bộ đếm vòng lặp trở thành giá trị n,         LoopImitation(i + 1, n); //gọi một thể hiện mới của thủ tục, với tham số i+1 (chuyển sang giá trị tiếp theo i) kết thúc;

Để hiểu đệ quy, bạn cần hiểu đệ quy...
 
Lặp lại trong lập trình — theo nghĩa rộng — tổ chức xử lý dữ liệu, trong đó các hành động được lặp lại nhiều lần mà không dẫn đến các cuộc gọi đến chính chúng (không giống như  %BA%D1%83%D1%80%D1%81%D0%B8%D1%8F" title="Recursion" >Đệ quy). Theo nghĩa hẹp — quy trình xử lý dữ liệu tuần hoàn một bước. 
Thông thường các thuật toán lặp ở bước hiện tại (lặp) sử dụng kết quả của cùng một thao tác hoặc hành động được tính ở các bước trước đó.  Một ví dụ về các phép tính như vậy là phép tính các quan hệ lặp lại. 
Một ví dụ đơn giản về giá trị đệ quy là giai thừa: \(N!=1 \cdot 2 \cdot 3 \cdot \ ... \ \cdot N\) Phép tính giá trị ở mỗi bước (lặp lại) là \(N=N \cdot i\) .  Khi tính giá trị của \(N\), chúng tôi lấy giá trị đã được lưu trữ \(N\).

Giai thừa của một số cũng có thể được mô tả bằng cách sử dụng công thức truy hồi:



Bạn có thể nhận thấy rằng mô tả này không gì khác hơn là một hàm đệ quy.
Đây là dòng đầu tiên (\(n <= 1\)) — đây là trường hợp cơ sở (điều kiện kết thúc của đệ quy) và dòng thứ hai là chuyển tiếp sang bước tiếp theo. 
 
Bạn nên hiểu rằng các lệnh gọi hàm liên quan đến một số chi phí bổ sung, do đó phép tính giai thừa không đệ quy sẽ nhanh hơn một chút. 
Kết luận:
chỗ bạn có thể viết chương trình với thuật toán lặp đơn giản, không đệ quy, thì bạn cần viết không đệ quy. Tuy nhiên, có rất nhiều bài toán mà quá trình tính toán chỉ được thực hiện bằng đệ quy.
Mặt khác, thuật toán đệ quy thường dễ hiểu hơn.
 

Hàm giai thừa đệ quy sẽ như thế này So sánh thuật toán tìm giai thừa theo cách thông thường, không đệ quy
hàm Giai thừa(n: số nguyên): số nguyên;
bắt đầu
    nếu n> 1 thì
        Giai thừa := n * Giai thừa(n - 1)
    khác
        Giai thừa := 1;
kết thúc;
x := 1;
for i := 2 to n do
    x := x * i;
writeln(x);