Khái niệm đệ quy trong lập trình

Admin

10/09/2023

Share

khai niem de quy trong lap trinh 687431

1. Hiểu một cách đơn giản, đệ quy là gì?

Đầu tiên, chúng ta cần hiểu về khái niệm phương thức trong lập trình. Phương thức là một tập hợp các lệnh được sử dụng để máy tính thực hiện các hành động theo ý muốn của người viết, và có thể chứa các tham số đầu vào. Đệ quy xảy ra khi một phương thức tự gọi hoặc định nghĩa lại chính nó.

Xem ví dụ đơn giản dưới đây. Đề bài: Tính tiến đến từ 0 đến n.

public int sum(int n) {
if (n >= 1) {
      return sum(n - 1) + n;
}
return n;
}

Giải thích:.

  • Phương thức sum() nhận một tham số n và trả về giá trị của tham số đó khi chương trình thực thi hoàn tất bằng cách sử dụng lệnh “return n”.
  • Để đạt được mục tiêu đó, chương trình sẽ thực hiện một loạt các lệnh điều kiện “if(n>=1)” để tái định nghĩa phương thức sum thành “sum(n-1) + n” mỗi lần lặp. Phương thức mới này sẽ thay đổi giá trị của n theo từng vòng lặp của điều kiện cho đến khi không còn thỏa mãn điều kiện nữa.
  • Khi chương trình thực hiện lệnh “return n”, giá trị của n sẽ được tính toán từ phương thức có điều kiện được định nghĩa ở trên.
  • Như vậy, hai yếu tố cần thiết để thực hiện một phương pháp đệ quy là:.

  • Có một điều kiện dừng được áp đặt: Tìm ra quy luật của phương thức và tìm giá trị cụ thể khi thỏa mãn một điều kiện nhất định. Tại bước này, chưa có phương thức đệ quy nào được gọi.
  • Phương pháp đệ quy: Phương pháp đệ quy sẽ liên tục gọi lại chính nó cho đến khi đạt được điều kiện dừng ở bước 1.
  • Xem nhiều:  iPhone CPO là gì? Cách nhận biết iP CPO, Có nên mua không?

    Mỗi khi sử dụng đệ quy, chương trình sẽ chạy một vòng và bộ nhớ Stack sẽ được chồng thêm một lớp dữ liệu. Điều này có thể dẫn đến lãng phí bộ nhớ nếu không phân tích kỹ các vòng chạy đệ quy để đảm bảo tính toán hiệu quả. Vấn đề này có thể được giải quyết bằng cách tối ưu hóa đòn bẩy đệ quy đuôi.

    Đơn giản, đệ quy là gì?Viết code bất cẩn, sẽ có n số khung đệ quy ghi đè lên bộ nhớ Stack

    2. Đệ quy đuôi và đệ quy đầu

    Vậy câu hỏi đặt ra là đệ quy đuôi khác với đệ quy đầu ở đâu. Chúng ta gọi là đệ quy đuôi khi phương thức đệ quy được đặt ở cuối, sau khi chương trình chạy qua điều kiện dừng. Còn lại thì ta gọi đó là đệ quy đầu. Ví dụ, phương thức ở phần 2 là đệ quy đầu, giờ hãy tiếp tục biến đổi một chút và ta có phương thức đệ quy đuôi tính lũy tiến từ currentSum đến n.

    public int tailSum(int currentSum, int n) {
       		 if (n <= 1) {
            	return currentSum + n;
        	}
        		return tailSum(currentSum + n, n - 1);
          }
    

    Phương thức đệ quy đuôi được ưu tiên xử lý dứt điểm, không cần chạy nhiều vòng xử lý điều kiện như phương thức đệ quy đầu, giảm nguy cơ tràn bộ nhớ Stack.

    3. Đối chiếu giữa đệ quy và vòng lặp

    Phép đệ quy có ưu điểm lớn nhất là tiếp cận vấn đề bằng những đoạn code sạch, gọn gàng, dễ đọc và dễ hiểu. Tuy nhiên, nhược điểm rõ ràng của phép đệ quy là nguy cơ cao tràn bộ nhớ Stack như đã được giải thích trước đó.

    Xem nhiều:  OEM là gì? Một số kiến thức cần nắm rõ về các mặt hàng OEM

    Cùng giải quyết một vấn đề nhưng một giải pháp khác để thay thế đệ quy là sử dụng vòng lặp.

    Đề bài giống với bài toán tính lũy tiến n ở trên, ta có cách giải quyết với vòng lặp như sau:.

    public int iterativeSum(int n) {
                 int sum = 0;
                 if(n < 0) {
                 return 0;
          }
                 for(int i=0; i<=n; i++) {
                sum += i;
          }
                return sum;
    }
    

    Mặc dù vòng lặp có lợi thế là chỉ cần một vòng duy nhất được gọi và không cần lo lắng về vấn đề tràn bộ nhớ Stack. Tuy nhiên, vòng lặp cũng có nhược điểm so với đệ quy là việc viết mã xử lý sẽ trở nên dài và phức tạp hơn.

    4. Các ví dụ mở rộng của đệ quy

    Đáng kinh ngạc về sức mạnh thực sự của đệ quy là thay vì phải tạo ra các thuật toán dài dòng với vòng lặp, đệ quy cho phép chúng ta áp dụng tư duy toán học trực tiếp vào thuật toán một cách dễ dàng.

    Đề bài: Nhập giá trị n và tìm đơn vị của mười lần n.

    Lũy thừa 100 101 102 103 10n-1 10n
    Đơn vị 1 10 100 1000

    Để giải quyết vấn đề, chúng ta thực hiện những bước sau đây:.

  • Để tính giá trị của 10n, ta cần phân tích quy luật bài toán bằng cách tính giá trị của 10n-1 nhân với 10 trước.
  • Nhưng để nhận được giá trị của 10n-1 thì chúng ta phải tính đơn vị 10(n-1)-1 trước đó.
  • Ta xác định được số cuối là 10 và 1. Đây là “điều kiện dừng”. Sau khi xác định điều kiện dừng, ta chỉ cần thiết kế phương trình đệ quy phù hợp.
  • Từ phân tích trên, chúng ta có thể xác định hai trường hợp là n = 0 và n > 0 (đây là những trường hợp sử dụng đệ quy).
  • public int powerOf10(int n) {
                if (n == 0) {
                return 1;
          }
                return powerOf10(n-1) * 10;
    }
    

    5. Chuỗi Fibonacci và phương pháp đệ quy

    Dãy Fibonacci là một chuỗi vô hạn các số tự nhiên, bắt đầu bằng hai số 0 và 1. Dãy này được xây dựng theo quy tắc mỗi số trong dãy luôn bằng tổng của hai số trước nó. Dưới đây là một số số Fibonacci: 0 1 1 2 3 5 8 13 21 34 55 ….

    Xem nhiều:  5+ Cách khắc phục laptop không nhận tai nghe hiệu quả, nhanh chóng
    Dãy số Fibonacci 0 1 1 2 3 5 8
    Số thứ tự 1 2 3 4 5 6 7 n

    Để tìm số Fibonacci thứ n, chúng ta cần sử dụng phương pháp đệ quy và xác định quy luật và điều kiện dừng của dãy số Fibonacci.

  • Quy tắc, chúng ta nhận thấy số n sẽ là tổng của 2 chữ số đứng sau nó là (n-2) + (n-1).
  • Và chúng ta biết chắc chắn rằng n1 = 0 và n2 = 1 là điều kiện kết thúc của dãy số.
  • Như vậy, chúng ta sẽ phân chia thành 2 trường hợp và thực hiện phương pháp đệ quy như sau:
  • public int fibonacci(int n) {
                if (n <= 1) {
                return n;
          }
                return fibonacci(n-1) + fibonacci(n-2);
    }
    

    6. Đệ quy trong biểu diễn số thập phân dưới dạng nhị phân

    Hãy thử đặt ra một tình huống khi chúng ta cần chuyển đổi một số từ hệ thập phân sang hệ nhị phân, và thực hiện các bước sau:

  • Quy luật chuyển đổi từ số thập phân sang nhị phân là chia số n cho 2 và giữ lại phần dư (0 hoặc 1). Tiếp tục lấy thương chia cho 2 cho đến khi đạt trường hợp 1 chia cho 2 (0 dư 1).
  • Khi số n = 0, điều kiện dừng của quy luật là 0 chia 2 vẫn là 0. Khi n = 1, điều kiện dừng là 1 chia cho 2 bằng 0 dư 1.
  • Như vậy chúng ta phân chia thành 2 trường hợp và tiến hành đệ quy như sau:.
  • public String toBinary(int n) {
    if (n <= 1 ) {
        return String.valueOf(n);
    }
        return toBinary(n / 2) + String.valueOf(n % 2);
          }
    

    7. Tổng kết

    Đệ quy là một khái niệm cơ bản trong lập trình và rất hiệu quả trong tư duy giải quyết vấn đề. Nhiều bài toán sau khi phân tích có thể được giải quyết bằng đệ quy và nếu tiếp cận bằng đệ quy, nhiều bài toán khác cũng sẽ giảm được đoạn code dài dòng.

    Xem nhiều:  Secure Boot là gì? Hướng dẫn cài đặt chế độ Secure Boot