Thủ tục đệ quy c. Đệ quy. Nhiệm vụ đào tạo
Để không phải viết một bài báo dài, trong đó sẽ có rất nhiều ví dụ về đệ quy trong C++, tôi sẽ viết thêm một ví dụ về đệ quy ở đây. Qua nhìn chung Những người hiểu cơ bản và sử dụng đệ quy trực tiếp trong các hàm của mình có thể bỏ qua tài liệu này. Đây là một ví dụ về cách sử dụng đệ quy, như trong bài viết Hàm trong C++ dành cho người mới bắt đầu. đệ quy
Bài 1 – Sử dụng đệ quy, hiển thị giai thừa của một số từ 1 đến N
Viết mã
=============================
GIAI ĐOẠN Số 1 viết một chương trình trống
=============================
#bao gồm
#bao gồm
#bao gồm
int chính()
{
hệ thống ("cls");
getch();
trả về 0;
}
Một chương trình trống đã được tạo, tôi nghĩ không cần bình luận
GIAI ĐOẠN số 2 ta viết ta viết chính hàm đệ quy
=========================================
#bao gồm
#bao gồm
#bao gồm
//Hàm đệ quy của chúng ta
int thực tế (int N )
{
//0! = 1, 1!=1, 2!=2, 3!=6... Bởi vì 2 số đầu tiên là số 1 và không theo thứ tự nghiêm ngặt, chúng tôi buộc điểm này trong mã
nếu n<2
return 1
;
nếu không thì trả về n * sự thật(n–1)
// ở đây hàm gọi chính nó
}
int chính()
{
hệ thống ("cls");
cout<
getch();
trả về 0;
}
ddd
============
Phần chính trong chương trình đệ quy C++
trả lại n * sự thật(n–1)
Hàm của chúng tôi tính toán lại để có được giá trị trước đó. Giá trị thực là tham số được truyền cho N từ thời điểm gọi hàm. Mục đích gọi hàm của chúng ta là gọi nó từ khối chính của chương trình. Trong trường hợp của chúng tôi, chúng tôi gọi nó từ một hàm int chính()
Tại sao tôi không viết bài tiếp theo mà viết bài trước? Khi các số được nhân lên, thì đầu tiên 0 * 1 ở đây là giá trị hiện tại của chúng ta là 1 và 0 là giá trị tính toán trước đó. Đây là toàn bộ bản chất của đệ quy, chúng tôi tính giá trị hiện tại bằng cách sử dụng giá trị trước đó, trong khi giá trị trước đó thu được bằng cách tính toán tương tự. Trình biên dịch tự tính toán giá trị trước đó và lưu giá trị này vào bộ nhớ. Tất cả những gì chúng ta cần làm là đưa ra hướng dẫn.
. Nhờ tính năng này của trình biên dịch, một hàm gặp phải lệnh gọi chính nó (trong trường hợp của chúng tôi sự thật(n–1)
) không ghi đè tham số được truyền cho Nđể tính hàm. Tham số được truyền tới N nó vẫn còn trong bộ nhớ. Trong trường hợp này, một vùng bộ nhớ khác được xác định bổ sung trong đó hàm đệ quy của chúng ta thực hiện các phép tính đệ quy để thu được kết quả trước đó.
Mong các lập trình viên tha thứ cho tôi vì nhận xét thiếu suy nghĩ như vậy. Đây gần như là cách người mới bắt đầu cảm nhận đệ quy.
Tôi hy vọng blog C++ dành cho người mới bắt đầu này hữu ích với ai đó và giúp ai đó hiểu khái niệm cơ bản về hàm đệ quy trong C++
Ghi chú. Trong bài viết này, cũng như bài trước, tôi không tính toán từ 1 đến N mà tính theo giá trị được nhập bên trong chương trình. Vấn đề là tôi không muốn viết thêm một dòng mã nào và cho rằng người dùng đã thành thạo trong việc nhập dữ liệu và hiển thị nó trên màn hình.
Đệ quy là một hiện tượng khá phổ biến xảy ra không chỉ trong lĩnh vực khoa học mà còn trong đời sống hàng ngày. Ví dụ: hiệu ứng Droste, tam giác Sierpinski, v.v. Cách dễ nhất để xem đệ quy là hướng camera Web vào màn hình điều khiển máy tính, một cách tự nhiên, sau khi bật nó lên trước. Như vậy, camera sẽ ghi lại hình ảnh của màn hình máy tính và hiển thị lên màn hình này, nó sẽ giống như một vòng khép kín. Kết quả là chúng ta sẽ quan sát thấy thứ gì đó tương tự như một đường hầm.
Trong lập trình, đệ quy có quan hệ mật thiết với hàm, hay nói chính xác hơn là nhờ hàm trong lập trình mà mới có đệ quy hay hàm đệ quy. Nói một cách đơn giản, đệ quy là định nghĩa một phần của hàm (phương thức) thông qua chính nó, tức là nó là hàm gọi chính nó, trực tiếp (trong thân hàm) hoặc gián tiếp (thông qua một hàm khác). Các bài toán đệ quy điển hình là: tìm số n!, Fibonacci. Chúng tôi đã giải quyết những vấn đề như vậy, nhưng sử dụng các vòng lặp, nghĩa là lặp đi lặp lại. Nói chung, mọi thứ được giải lặp lại đều có thể được giải bằng đệ quy, nghĩa là sử dụng hàm đệ quy. Toàn bộ giải pháp bắt nguồn từ việc giải quyết trường hợp chính hoặc, như nó còn được gọi là trường hợp cơ sở. Có một thứ gọi là bước đệ quy hoặc lệnh gọi đệ quy. Trong trường hợp hàm đệ quy được gọi để giải quyết một vấn đề phức tạp (không phải trường hợp cơ bản), một số lệnh gọi hoặc bước đệ quy được thực hiện để giảm vấn đề xuống đơn giản hơn. Và cứ như vậy cho đến khi chúng ta có được lời giải cơ bản. Hãy phát triển một chương trình khai báo hàm đệ quy tính n!
"stdafx.h" #include
// mã Code::Khối
// Mã Dev-C++
// giai thừa.cpp: Xác định điểm vào cho ứng dụng bảng điều khiển. #bao gồm
TRONG dòng 7, 9, 21 Kiểu dữ liệu được khai báo unsigned long int , vì giá trị của giai thừa tăng rất nhanh, chẳng hạn đã là 10! = 3.628.800. Nếu kích thước của kiểu dữ liệu không đủ thì kết quả sẽ là giá trị sai hoàn toàn. Mã khai báo nhiều toán tử hơn mức cần thiết để tìm n!. Điều này được thực hiện để sau khi chạy, chương trình sẽ hiển thị những gì xảy ra ở mỗi bước của lệnh gọi đệ quy. Xin lưu ý các dòng mã được đánh dấu, dòng 23, 24, 28 là một giải pháp đệ quy cho n!. Dòng 23, 24 là nghiệm cơ bản của hàm đệ quy, tức là ngay khi giá trị của biến f sẽ bằng 1 hoặc 0 (vì chúng ta biết rằng 1! = 1 và 0! = 1), các lệnh gọi đệ quy sẽ dừng và các giá trị sẽ bắt đầu được trả về cho mỗi lệnh gọi đệ quy. Khi giá trị của lệnh gọi đệ quy đầu tiên trả về, chương trình sẽ trả về giá trị của giai thừa đã tính. TRONG dòng 28 hàm giai thừa() gọi chính nó, nhưng đối số của nó ít hơn một. Đối số được giảm bớt mỗi lần để đạt được một giải pháp cụ thể. Kết quả của chương trình (xem Hình 1).
Nhập n!: 5 Bước 1 Kết quả= 0 Bước 2 Kết quả= 0 Bước 3 Kết quả= 0 Bước 4 Kết quả= 0 5!=120
Hình 1 - Đệ quy trong C++
Dựa trên kết quả của chương trình, mỗi bước được hiển thị rõ ràng và kết quả ở mỗi bước bằng 0, ngoại trừ lệnh gọi đệ quy cuối cùng. Cần phải tính năm giai thừa. Chương trình đã thực hiện bốn lệnh gọi đệ quy và ở lệnh gọi thứ năm, trường hợp cơ bản đã được tìm thấy. Và khi chương trình đã có lời giải cho trường hợp cơ bản, nó sẽ giải quyết các bước trước đó và đưa ra kết quả tổng thể. Trong Hình 1, chỉ có bốn bước được hiển thị vì ở bước thứ năm, một giải pháp một phần đã được tìm thấy, giải pháp cuối cùng trả về giải pháp cuối cùng, tức là 120. Hình 2 hiển thị sơ đồ tính toán đệ quy 5!. Sơ đồ cho thấy rõ ràng rằng kết quả đầu tiên được trả về khi đạt được một giải pháp cụ thể, nhưng không phải ngay lập tức, sau mỗi lệnh gọi đệ quy.
Hình 2 - Đệ quy trong C++
Vậy tìm được 5! cần biết 4! và nhân nó với 5; 4! = 4 * 3! và như thế. Theo sơ đồ trong Hình 2, phép tính sẽ được rút gọn thành việc tìm một trường hợp đặc biệt, tức là 1!, sau đó các giá trị sẽ lần lượt được trả về cho từng lệnh gọi đệ quy. Cuộc gọi đệ quy cuối cùng sẽ trả về giá trị 5!.
Chúng ta hãy làm lại chương trình tìm giai thừa để có được bảng giai thừa. Để làm điều này, chúng ta sẽ khai báo một vòng lặp for trong đó chúng ta sẽ gọi hàm đệ quy.
// mã Code::Khối // Mã Dev-C++ // giai thừa.cpp: Xác định điểm vào cho ứng dụng bảng điều khiển. #bao gồm TRONG dòng 16 - 19 một vòng lặp được khai báo trong đó hàm đệ quy được gọi. Mọi thứ không cần thiết trong chương trình đều được bình luận. Sau khi bắt đầu chương trình, bạn cần nhập giá trị cần tính giai thừa. Kết quả của chương trình được thể hiện trong Hình 3. Nhập n!: 14 1!=1 2!=2 3!=6 4!=24 5!=120 6!=720 7!=5040 8!=40320 9!=362880 10!=3628800 11!=39916800 12 !=479001600 13!=6227020800 14!=87178291200 Hình 3 - Đệ quy trong C++ Bây giờ bạn có thể thấy giai thừa tăng nhanh như thế nào; nhân tiện, kết quả đã là 14! là không đúng, đây là hậu quả của việc thiếu kích thước kiểu dữ liệu. Giá trị đúng là 14! = 87178291200. Chúng ta hãy xem xét một vấn đề điển hình khác - tìm số Fibonacci bằng đệ quy. Dưới đây là mã cho giải pháp đệ quy cho vấn đề như vậy. Chúng ta nhập vào cùng một dòng số sê-ri của một số trong chuỗi Fibonacci và chương trình sẽ tìm tất cả các số trong chuỗi Fibonacci có số sê-ri nhỏ hơn hoặc bằng số đã nhập. // fibonacci.cpp: xác định điểm vào cho ứng dụng console. #include "stdafx.h" #include // mã Code::Khối // Mã Dev-C++ // fibonacci.cpp: xác định điểm vào cho ứng dụng console. #bao gồm TRONG dòng 6 thư viện được kết nối Nhập số từ dãy Fibonacci: 30 1 = 0 2 = 1 3 = 1 4 = 2 5 = 3 6 = 5 7 = 8 8 = 13 9 = 21 10 = 34 11 = 55 12 = 89 13 = 144 14 = 233 15 = 377 16 = 610 17 = 987 18 = 1597 19 = 2584 20 = 4181 21 = 6765 22 = 10946 23 = 17711 24 = 28657 25 = 46368 26 = 75025 27 = 121393 28 = 196418 29 = 317811 30 = 514229 Hình 4 - Đệ quy trong C++ Giải pháp là chia một vấn đề phức tạp thành hai vấn đề đơn giản hơn. Ví dụ: để tìm số thứ ba trong dãy Fibonacci, trước tiên bạn phải tìm số thứ nhất và số thứ hai, sau đó cộng chúng lại. Số thứ nhất là trường hợp đặc biệt và bằng 0 (không), số thứ hai cũng là trường hợp đặc biệt và bằng 1. Do đó, số thứ ba trong dãy Fibonacci bằng tổng của số thứ nhất và số thứ hai = 1. Hàm đệ quy mà chúng tôi đã lập trình để tìm kiếm các số dãy Fibonacci được suy luận theo cách gần giống nhau. Hãy phát triển một chương trình đệ quy khác để giải quyết vấn đề kinh điển - “Tháp Hà Nội”. Cho ba thanh, trên một trong số đó có một chồng số đĩa thứ n và các đĩa không có cùng kích thước (các đĩa có đường kính khác nhau) và được sắp xếp sao cho khi bạn di chuyển từ trên xuống dưới. dọc theo thanh, đường kính của các đĩa tăng dần. Nghĩa là, các đĩa nhỏ hơn chỉ nên nằm trên các đĩa lớn hơn. Bạn cần di chuyển chồng đĩa này từ thanh ban đầu sang bất kỳ thanh nào khác trong số hai thanh còn lại (thường đây là thanh thứ ba). Sử dụng một trong các thanh làm thanh phụ. Bạn chỉ có thể di chuyển một đĩa mỗi lần và đĩa lớn hơn không bao giờ được nằm trên đĩa nhỏ hơn. Giả sử bạn cần di chuyển ba đĩa từ thanh thứ nhất sang thanh thứ ba, nghĩa là thanh thứ hai là thanh phụ. Giải pháp trực quan cho vấn đề này được triển khai trong Flash. Bấm vào nút bắt đầu để bắt đầu hoạt ảnh, nút dừng để dừng hoạt ảnh. Chương trình phải được viết cho số đĩa thứ n. Vì chúng ta đang giải bài toán này một cách đệ quy nên trước tiên chúng ta cần tìm các trường hợp đặc biệt của lời giải. Trong bài toán này, chỉ có một trường hợp đặc biệt - đó là khi chỉ cần di chuyển một đĩa và trong trường hợp này, ngay cả một thanh phụ cũng không cần thiết, nhưng đơn giản là chúng ta không chú ý đến điều này. Bây giờ cần tổ chức giải pháp đệ quy nếu số lượng đĩa nhiều hơn một. Xin giới thiệu một số ký hiệu để khỏi viết quá nhiều: <Б>
- thanh mà các đĩa được đặt ban đầu (thanh cơ sở); Hơn nữa, khi mô tả thuật toán giải bài toán, chúng ta sẽ sử dụng các ký hiệu này. Để di chuyển ba đĩa từ <Б>
TRÊN <Ф>
trước tiên chúng ta cần di chuyển hai đĩa từ <Б>
TRÊN <П>
và sau đó di chuyển đĩa thứ ba (lớn nhất) sang <Ф>
, bởi vì <Ф>
miễn phí Để di chuyển Nđĩa với <Б>
TRÊN <Ф>
chúng ta cần phải di chuyển trước n-1đĩa với <Б>
TRÊN <П>
và sau đó di chuyển đĩa thứ n (lớn nhất) sang <Ф>
, bởi vì <Ф>
miễn phí Sau này bạn cần phải di chuyển n-1đĩa với <П>
TRÊN <Ф>
, trong khi sử dụng thanh <Б>
như một phụ trợ. Ba hành động này là toàn bộ thuật toán đệ quy. Thuật toán tương tự trong mã giả: // hanoi_tower.cpp: Xác định điểm vào cho ứng dụng console. // Chương trình giải đệ quy bài toán Tháp Hà Nội #include "stdafx.h" #include // mã Code::Khối // Mã Dev-C++ // hanoi_tower.cpp: Xác định điểm vào cho ứng dụng console. // Chương trình giải đệ quy bài toán Tháp Hà Nội #include Hình 5 thể hiện một ví dụ về chương trình đệ quy Tháp Hà Nội. Đầu tiên, chúng tôi nhập số đĩa bằng ba, sau đó chúng tôi nhập thanh cơ sở (đầu tiên) và chỉ định thanh cuối cùng (thứ ba). Tự động thanh thứ hai trở thành thanh phụ. Chương trình tạo ra kết quả hoàn toàn trùng khớp với giải pháp hoạt hình cho vấn đề này. Nhập số đĩa: 3 Nhập số thanh cơ bản: 1 Nhập số thanh cuối cùng: 3 1) 1 -> 3 2) 1 -> 2 3) 3 -> 2 4) 1 -> 3 5) 2 -> 1 6) 2 -> 3 7) 1 -> 3 Hình 5 - Đệ quy trong C++ Từ hình vẽ có thể thấy rằng đầu tiên đĩa di chuyển từ thanh 1 sang thanh 3, sau đó từ thanh 1 sang thanh 2, từ thanh 3 sang thanh 3.hai, v.v. Nghĩa là, chương trình chỉ hiển thị trình tự chuyển động của đĩa và số bước tối thiểu mà tất cả các đĩa sẽ được di chuyển. Tất cả những vấn đề này có thể được giải quyết lặp đi lặp lại. Câu hỏi được đặt ra là: “Giải quyết theo phương pháp lặp hay đệ quy, cái nào tốt hơn?” Tôi trả lời: “Nhược điểm của đệ quy là nó tiêu tốn nhiều tài nguyên máy tính hơn so với phép lặp. Điều này dẫn đến tải nặng cho cả RAM và bộ xử lý. Nếu rõ ràng là một vấn đề cụ thể có thể được giải theo cách lặp đi lặp lại thì nó nên được sử dụng theo cách khác, sử dụng đệ quy!” Tùy thuộc vào vấn đề đang được giải quyết, độ phức tạp của việc viết chương trình sẽ thay đổi khi sử dụng phương pháp giải này hoặc phương pháp giải khác. Nhưng thường xuyên hơn, một vấn đề được giải quyết bằng phương pháp đệ quy từ quan điểm về khả năng đọc mã sẽ rõ ràng và ngắn gọn hơn nhiều. Xin chào Habrahabr! Trong bài viết này chúng ta sẽ nói về các vấn đề đệ quy và cách giải quyết chúng. Trong lập trình, đệ quy có quan hệ mật thiết với hàm, hay nói chính xác hơn là nhờ hàm trong lập trình mà mới có đệ quy hay hàm đệ quy. Nói một cách đơn giản, đệ quy là định nghĩa một phần của hàm (phương thức) thông qua chính nó, tức là nó là hàm gọi chính nó, trực tiếp (trong thân hàm) hoặc gián tiếp (thông qua một hàm khác). Rất nhiều điều đã được nói về sự đệ quy. Dưới đây là một số tài nguyên tốt: từ mạng Bất kỳ thuật toán nào được thực hiện ở dạng đệ quy đều có thể được viết lại ở dạng lặp và ngược lại. Câu hỏi đặt ra là liệu điều này có cần thiết hay không và nó sẽ hiệu quả đến mức nào. Những lập luận sau đây có thể được đưa ra để biện minh cho điều này. Để bắt đầu, chúng ta có thể nhớ lại các định nghĩa về đệ quy và lặp lại. Đệ quy là một cách tổ chức xử lý dữ liệu trong đó chương trình gọi chính nó trực tiếp hoặc với sự trợ giúp của các chương trình khác. Lặp lại là một cách tổ chức xử lý dữ liệu trong đó một số hành động nhất định được lặp lại nhiều lần mà không dẫn đến lệnh gọi chương trình đệ quy. Sau đó, chúng ta có thể kết luận rằng chúng có thể thay thế cho nhau, nhưng không phải lúc nào cũng có cùng chi phí về tài nguyên và tốc độ. Để chứng minh điều này, chúng ta có thể đưa ra ví dụ sau: có một hàm trong đó để tổ chức một thuật toán nhất định, có một vòng lặp thực hiện một chuỗi hành động tùy thuộc vào giá trị hiện tại của bộ đếm (nó có thể không phụ thuộc vào Nó). Vì có một chu trình, có nghĩa là cơ thể lặp lại một chuỗi hành động - sự lặp lại của chu trình. Bạn có thể di chuyển các thao tác vào một chương trình con riêng biệt và chuyển cho nó giá trị bộ đếm, nếu có. Sau khi hoàn thành việc thực hiện chương trình con, chúng tôi kiểm tra các điều kiện để thực hiện vòng lặp và nếu nó đúng, chúng tôi tiến hành gọi chương trình con mới; nếu sai, chúng tôi hoàn thành việc thực thi. Bởi vì Chúng ta đặt tất cả nội dung của vòng lặp vào một chương trình con, nghĩa là điều kiện để thực hiện vòng lặp cũng được đặt trong chương trình con và có thể lấy được thông qua giá trị trả về của hàm, các tham số được truyền bằng tham chiếu hoặc con trỏ tới chương trình con , cũng như các biến toàn cục. Hơn nữa, thật dễ dàng để chỉ ra rằng một lệnh gọi đến một chương trình con nhất định từ một vòng lặp có thể dễ dàng được chuyển đổi thành một lệnh gọi hoặc không gọi (trả về một giá trị hoặc đơn giản là hoàn thành công việc) của một chương trình con từ chính nó, được hướng dẫn bởi một số điều kiện (những điều kiện mà trước đây ở trạng thái vòng lặp). Bây giờ, nếu bạn nhìn vào chương trình trừu tượng của chúng tôi, nó gần giống như chuyển các giá trị cho một chương trình con và sử dụng chúng, chương trình con sẽ thay đổi khi nó kết thúc, tức là. chúng tôi đã thay thế vòng lặp bằng lệnh gọi đệ quy đến một chương trình con để giải một thuật toán nhất định. Nhiệm vụ đưa đệ quy vào một cách tiếp cận lặp lại là có tính đối xứng. Tóm lại, chúng ta có thể bày tỏ những suy nghĩ sau: đối với mỗi cách tiếp cận, có một loại nhiệm vụ riêng, được xác định bởi các yêu cầu cụ thể cho một nhiệm vụ cụ thể. Bạn có thể tìm hiểu thêm về điều này Vì vậy hàm đệ quy bao gồm Giải pháp lớp công khai ( public static int recursion(int n) ( // thoát điều kiện // Trường hợp cơ sở // khi nào dừng lặp lại đệ quy? if (n == 1) ( return 1; ) // Bước đệ quy / trả về điều kiện đệ quy đệ quy( n - 1) * n; ) public static void main(String args) ( System.out.println(recursion(5)); // gọi hàm đệ quy ) ) Ở đây điều kiện cơ bản là điều kiện khi n=1. Vì chúng ta biết rằng 1!=1 và để tính 1! chúng tôi không cần bất cứ điều gì. Để tính 2! chúng ta có thể sử dụng 1!, tức là 2!=1!*2. Để tính 3! chúng ta cần 2!*3... Để tính n! chúng ta cần (n-1)!*n. Đây là bước đệ quy. Nói cách khác, để lấy giá trị giai thừa của một số n, chỉ cần nhân giá trị giai thừa của số trước đó với n là đủ. Thẻ: Xin chào Habrahabr! Trong bài viết này chúng ta sẽ nói về các vấn đề đệ quy và cách giải quyết chúng. Trong lập trình, đệ quy có quan hệ mật thiết với hàm, hay nói chính xác hơn là nhờ hàm trong lập trình mà mới có đệ quy hay hàm đệ quy. Nói một cách đơn giản, đệ quy là định nghĩa một phần của hàm (phương thức) thông qua chính nó, tức là nó là hàm gọi chính nó, trực tiếp (trong thân hàm) hoặc gián tiếp (thông qua một hàm khác). Rất nhiều điều đã được nói về sự đệ quy. Dưới đây là một số tài nguyên tốt: từ mạng Bất kỳ thuật toán nào được thực hiện ở dạng đệ quy đều có thể được viết lại ở dạng lặp và ngược lại. Câu hỏi đặt ra là liệu điều này có cần thiết hay không và nó sẽ hiệu quả đến mức nào. Những lập luận sau đây có thể được đưa ra để biện minh cho điều này. Để bắt đầu, chúng ta có thể nhớ lại các định nghĩa về đệ quy và lặp lại. Đệ quy là một cách tổ chức xử lý dữ liệu trong đó chương trình gọi chính nó trực tiếp hoặc với sự trợ giúp của các chương trình khác. Lặp lại là một cách tổ chức xử lý dữ liệu trong đó một số hành động nhất định được lặp lại nhiều lần mà không dẫn đến lệnh gọi chương trình đệ quy. Sau đó, chúng ta có thể kết luận rằng chúng có thể thay thế cho nhau, nhưng không phải lúc nào cũng có cùng chi phí về tài nguyên và tốc độ. Để chứng minh điều này, chúng ta có thể đưa ra ví dụ sau: có một hàm trong đó để tổ chức một thuật toán nhất định, có một vòng lặp thực hiện một chuỗi hành động tùy thuộc vào giá trị hiện tại của bộ đếm (nó có thể không phụ thuộc vào Nó). Vì có một chu trình, có nghĩa là cơ thể lặp lại một chuỗi hành động - sự lặp lại của chu trình. Bạn có thể di chuyển các thao tác vào một chương trình con riêng biệt và chuyển cho nó giá trị bộ đếm, nếu có. Sau khi hoàn thành việc thực hiện chương trình con, chúng tôi kiểm tra các điều kiện để thực hiện vòng lặp và nếu nó đúng, chúng tôi tiến hành gọi chương trình con mới; nếu sai, chúng tôi hoàn thành việc thực thi. Bởi vì Chúng ta đặt tất cả nội dung của vòng lặp vào một chương trình con, nghĩa là điều kiện để thực hiện vòng lặp cũng được đặt trong chương trình con và có thể lấy được thông qua giá trị trả về của hàm, các tham số được truyền bằng tham chiếu hoặc con trỏ tới chương trình con , cũng như các biến toàn cục. Hơn nữa, thật dễ dàng để chỉ ra rằng một lệnh gọi đến một chương trình con nhất định từ một vòng lặp có thể dễ dàng được chuyển đổi thành một lệnh gọi hoặc không gọi (trả về một giá trị hoặc đơn giản là hoàn thành công việc) của một chương trình con từ chính nó, được hướng dẫn bởi một số điều kiện (những điều kiện mà trước đây ở trạng thái vòng lặp). Bây giờ, nếu bạn nhìn vào chương trình trừu tượng của chúng tôi, nó gần giống như chuyển các giá trị cho một chương trình con và sử dụng chúng, chương trình con sẽ thay đổi khi nó kết thúc, tức là. chúng tôi đã thay thế vòng lặp bằng lệnh gọi đệ quy đến một chương trình con để giải một thuật toán nhất định. Nhiệm vụ đưa đệ quy vào một cách tiếp cận lặp lại là có tính đối xứng. Tóm lại, chúng ta có thể bày tỏ những suy nghĩ sau: đối với mỗi cách tiếp cận, có một loại nhiệm vụ riêng, được xác định bởi các yêu cầu cụ thể cho một nhiệm vụ cụ thể. Bạn có thể tìm hiểu thêm về điều này Vì vậy hàm đệ quy bao gồm Giải pháp lớp công khai ( public static int recursion(int n) ( // thoát điều kiện // Trường hợp cơ sở // khi nào dừng lặp lại đệ quy? if (n == 1) ( return 1; ) // Bước đệ quy / trả về điều kiện đệ quy đệ quy( n - 1) * n; ) public static void main(String args) ( System.out.println(recursion(5)); // gọi hàm đệ quy ) ) Ở đây điều kiện cơ bản là điều kiện khi n=1. Vì chúng ta biết rằng 1!=1 và để tính 1! chúng tôi không cần bất cứ điều gì. Để tính 2! chúng ta có thể sử dụng 1!, tức là 2!=1!*2. Để tính 3! chúng ta cần 2!*3... Để tính n! chúng ta cần (n-1)!*n. Đây là bước đệ quy. Nói cách khác, để lấy giá trị giai thừa của một số n, chỉ cần nhân giá trị giai thừa của số trước đó với n là đủ. Thẻ: Thêm thẻ
<П>
- thanh phụ hoặc thanh trung gian;
<Ф>
— thanh cuối cùng – thanh mà các đĩa cần được di chuyển tới.
n-1 chuyển tới <П>
N chuyển tới <Ф>
n-1 di chuyển từ <П>
TRÊN <Ф>
, Trong khi sử dụng <Б>
như một phụ trợNói ngắn gọn về đệ quy
Đệ quy là một hiện tượng khá phổ biến xảy ra không chỉ trong lĩnh vực khoa học mà còn trong đời sống hàng ngày. Ví dụ: hiệu ứng Droste, tam giác Sierpinski, v.v. Một cách để xem đệ quy là hướng camera Web vào màn hình điều khiển máy tính, một cách tự nhiên, sau khi bật nó lên trước. Như vậy, camera sẽ ghi lại hình ảnh của màn hình máy tính và hiển thị lên màn hình này, nó sẽ giống như một vòng khép kín. Kết quả là chúng ta sẽ quan sát thấy thứ gì đó tương tự như một đường hầm.
Giả định rằng về mặt lý thuyết, người đọc đã quen thuộc với đệ quy và biết nó là gì. Trong bài viết này chúng ta sẽ chú ý hơn tới các bài toán đệ quy. Nhiệm vụ
Khi học đệ quy, cách hiểu đệ quy hiệu quả nhất là giải quyết vấn đề. Làm thế nào để giải quyết vấn đề đệ quy?
Trước hết, bạn cần hiểu rằng đệ quy là một dạng quá mức cần thiết. Nói chung, mọi thứ được giải lặp lại đều có thể được giải bằng đệ quy, nghĩa là sử dụng hàm đệ quy.
Cũng giống như một phép liệt kê (chu trình), đệ quy phải có điều kiện dừng - Trường hợp cơ sở (nếu không, cũng giống như một chu trình, đệ quy sẽ hoạt động mãi mãi - vô hạn). Điều kiện này là trường hợp đệ quy đi tới (bước đệ quy). Ở mỗi bước, một hàm đệ quy được gọi cho đến khi lệnh gọi tiếp theo kích hoạt điều kiện cơ bản và quá trình đệ quy dừng lại (hay nói đúng hơn là quay lại lệnh gọi hàm cuối cùng). Toàn bộ giải pháp bắt nguồn từ việc giải quyết trường hợp cơ bản. Trong trường hợp hàm đệ quy được gọi để giải quyết một vấn đề phức tạp (không phải trường hợp cơ bản), một số lệnh gọi hoặc bước đệ quy được thực hiện để giảm vấn đề xuống đơn giản hơn. Và cứ như vậy cho đến khi chúng ta có được lời giải cơ bản.
Hãy xem xét điều này bằng cách sử dụng ví dụ về việc tìm giai thừa:
Thêm thẻ Nói ngắn gọn về đệ quy
Đệ quy là một hiện tượng khá phổ biến xảy ra không chỉ trong lĩnh vực khoa học mà còn trong đời sống hàng ngày. Ví dụ: hiệu ứng Droste, tam giác Sierpinski, v.v. Một cách để xem đệ quy là hướng camera Web vào màn hình điều khiển máy tính, một cách tự nhiên, sau khi bật nó lên trước. Như vậy, camera sẽ ghi lại hình ảnh của màn hình máy tính và hiển thị lên màn hình này, nó sẽ giống như một vòng khép kín. Kết quả là chúng ta sẽ quan sát thấy thứ gì đó tương tự như một đường hầm.
Giả định rằng về mặt lý thuyết, người đọc đã quen thuộc với đệ quy và biết nó là gì. Trong bài viết này chúng ta sẽ chú ý hơn tới các bài toán đệ quy. Nhiệm vụ
Khi học đệ quy, cách hiểu đệ quy hiệu quả nhất là giải quyết vấn đề. Làm thế nào để giải quyết vấn đề đệ quy?
Trước hết, bạn cần hiểu rằng đệ quy là một dạng quá mức cần thiết. Nói chung, mọi thứ được giải lặp lại đều có thể được giải bằng đệ quy, nghĩa là sử dụng hàm đệ quy.
Cũng giống như một phép liệt kê (chu trình), đệ quy phải có điều kiện dừng - Trường hợp cơ sở (nếu không, cũng giống như một chu trình, đệ quy sẽ hoạt động mãi mãi - vô hạn). Điều kiện này là trường hợp đệ quy đi tới (bước đệ quy). Ở mỗi bước, một hàm đệ quy được gọi cho đến khi lệnh gọi tiếp theo kích hoạt điều kiện cơ bản và quá trình đệ quy dừng lại (hay nói đúng hơn là quay lại lệnh gọi hàm cuối cùng). Toàn bộ giải pháp bắt nguồn từ việc giải quyết trường hợp cơ bản. Trong trường hợp hàm đệ quy được gọi để giải quyết một vấn đề phức tạp (không phải trường hợp cơ bản), một số lệnh gọi hoặc bước đệ quy được thực hiện để giảm vấn đề xuống đơn giản hơn. Và cứ như vậy cho đến khi chúng ta có được lời giải cơ bản.
Hãy xem xét điều này bằng cách sử dụng ví dụ về việc tìm giai thừa: