Hiểu biết hiện đại về đệ quy: định nghĩa về chức năng và truy cập vào nó từ bên ngoài và từ chức năng này. Người ta tin rằng đệ quy được sinh ra bởi các nhà toán học: tính giai thừa, chuỗi vô hạn, số gãy, phân số liên tục … Tuy nhiên, đệ quy có thể được tìm thấy ở khắp mọi nơi. Các quy luật tự nhiên khách quan “coi” đệ quy là thuật toán chính và hình thức biểu hiện (tồn tại) không quá nhiều đối với các đối tượng của thế giới vật chất, mà nói chung là thuật toán chính của chuyển động.
Những người thuộc các chuyên ngành khác nhau trong các lĩnh vực khoa học và công nghệ khác nhau sử dụng thuật toán đệ quy f (x), trong đó "x ~ /=f (x)". Một hàm tự gọi là một giải pháp mạnh, nhưng việc hình thành và hiểu giải pháp này, trong hầu hết các trường hợp, là một nhiệm vụ rất khó khăn.
Vào thời cổ đại, đệ quy được sử dụng để tăng không gian cung điện. Thông qua hệ thống gương chiếu thẳng vào nhau, bạn có thể tạo ra các hiệu ứng không gian ba chiều tuyệt đẹp. Nhưng nó có dễ hiểu như thế nào khôngđiều chỉnh các gương này? Việc xác định vị trí của một điểm trong không gian, được phản chiếu qua nhiều tấm gương thậm chí còn khó hơn.
Đệ quy, thuật toán đệ quy: ý nghĩa và cú pháp
Bài toán, được hình thành bằng cách lặp lại một chuỗi hoạt động, có thể được giải một cách đệ quy. Một thuật toán đơn giản (tính toán phương trình bậc hai, tập lệnh để điền thông tin vào trang web, đọc tệp, gửi tin nhắn …) không yêu cầu đệ quy.
Sự khác biệt chính của thuật toán cho phép giải pháp đệ quy:
- có một thuật toán cần được thực hiện nhiều lần;
- thuật toán cần dữ liệu luôn thay đổi;
- thuật toán không phải thay đổi mọi lúc;
- có một điều kiện cuối cùng: thuật toán là đệ quy - không phải là vô hạn.
Nói chung, không thể lập luận rằng thực thi một lần là điều kiện cần thiết để không có lý do cho đệ quy. Bạn cũng không thể yêu cầu điều kiện cuối cùng bắt buộc: đệ quy vô hạn có phạm vi riêng.
Thuật toán là đệ quy: khi một chuỗi hoạt động được thực hiện lặp đi lặp lại, trên dữ liệu thay đổi mỗi lần và mỗi lần cho ra một kết quả mới.
Công thức đệ quy
Sự hiểu biết toán học về đệ quy và tương tự của nó trong lập trình là khác nhau. Toán học, mặc dù có những dấu hiệu của lập trình, nhưng lập trình là toán học ở mức độ cao hơn nhiều.
Một thuật toán được viết tốt giống như một tấm gương phản chiếu trí tuệ của tác giả. Chungcông thức đệ quy trong lập trình là "f (x)", trong đó "x ~ /=f (x)" có ít nhất hai cách diễn giải. Ở đây "~" là sự giống nhau hoặc không có kết quả và "=" là sự hiện diện của kết quả của hàm.
Tùy chọn đầu tiên: động dữ liệu.
- function "f (x)" có một thuật toán đệ quy và bất biến;
- "x" và kết quả "f (x)" có giá trị mới mỗi lần, kết quả "f (x)" là tham số "x" mới của hàm này.
Tùy chọn thứ hai: mã động lực.
- function "f (x)" có một số thuật toán tinh chỉnh (phân tích) dữ liệu;
- phân tích dữ liệu - một phần của mã và triển khai các thuật toán đệ quy thực hiện hành động mong muốn - phần thứ hai của mã;
- kết quả của hàm "f (x)" không phải là.
Không có kết quả là bình thường. Lập trình không phải là toán học, ở đây kết quả không cần phải được trình bày rõ ràng. Một hàm đệ quy có thể chỉ cần phân tích cú pháp các trang web và điền vào cơ sở dữ liệu hoặc khởi tạo các đối tượng theo đầu vào đến.
Dữ liệu và đệ quy
Lập trình các thuật toán đệ quy không phải là để tính giai thừa, trong đó hàm nhận mỗi khi một giá trị nhất định lớn hơn hoặc nhỏ hơn một - tùy chọn triển khai tùy thuộc vào sở thích của nhà phát triển.
Cách giai thừa "8!",thuật toán tuân theo đúng công thức này.
Xử lý thông tin là "toán học" của một thứ tự hoàn toàn khác. Các hàm và thuật toán đệ quy ở đây hoạt động trên các chữ cái, từ, cụm từ, câu và đoạn văn. Mỗi cấp độ tiếp theo sử dụng cấp độ trước đó.
Luồng dữ liệu đầu vào được phân tích trong một loạt các điều kiện, nhưng quá trình phân tích nói chung là đệ quy. Không có ý nghĩa gì khi viết các thuật toán duy nhất cho tất cả các biến thể của luồng đầu vào. Nên có một chức năng. Ở đây, các thuật toán đệ quy là những ví dụ về cách tạo một dòng đầu ra phù hợp với đầu vào. Đây không phải là đầu ra của thuật toán đệ quy, nhưng nó là giải pháp mong muốn và cần thiết.
Trừu tượng, đệ quy và OOP
Lập trình hướng đối tượng (OOP) và đệ quy về cơ bản là các thực thể khác nhau, nhưng chúng bổ sung cho nhau một cách hoàn hảo. Tính trừu tượng không liên quan gì đến đệ quy, nhưng thông qua lăng kính của OOP, nó tạo ra khả năng triển khai đệ quy theo ngữ cảnh.
Ví dụ: thông tin đang được phân tích cú pháp và các chữ cái, từ, cụm từ, câu và đoạn văn được đánh dấu riêng biệt. Rõ ràng, nhà phát triển sẽ cung cấp việc tạo các phiên bản của các đối tượng thuộc năm loại này và đưa ra giải pháp thuật toán đệ quy ở mỗi cấp độ.
Trong khi đó, nếu ở cấp độ các chữ cái “không có ý nghĩa gì để tìm kiếm ý nghĩa”, thì ngữ nghĩa sẽ xuất hiện ở cấp độ từ. Bạn có thể chia từ thành động từ, danh từ, trạng từ, giới từ … Bạn có thể đi xa hơn và xác định các trường hợp.
Ở cấp độ cụm từ, ngữ nghĩa được bổ sung bằng các dấu câu và logiccác tổ hợp từ. Ở cấp độ câu, mức độ ngữ nghĩa hoàn hảo hơn được tìm thấy và một đoạn văn có thể được coi là một ý nghĩ hoàn chỉnh.
Phát triển hướng đối tượng xác định trước sự kế thừa của các thuộc tính và phương thức và đề xuất bắt đầu hệ thống phân cấp của các đối tượng với việc tạo ra một tổ tiên hoàn toàn trừu tượng. Đồng thời, không nghi ngờ gì nữa, việc phân tích từng hậu duệ sẽ là đệ quy và sẽ không khác biệt quá nhiều ở cấp độ kỹ thuật ở nhiều vị trí (chữ cái, từ, cụm từ và câu). Các đoạn văn, giống như những suy nghĩ hoàn chỉnh, có thể nổi bật so với danh sách này, nhưng chúng không phải là bản chất.
Điều quan trọng là phần áp đảo của thuật toán có thể được xây dựng ở cấp độ tổ tiên trừu tượng, tinh chỉnh nó ở cấp độ của mỗi phần tử con với dữ liệu và phương thức được gọi từ cấp độ trừu tượng. Trong bối cảnh này, tính trừu tượng mở ra chân trời mới cho phép đệ quy.
Đặc điểm lịch sử của OOP
OOP đã đến với thế giới phần mềm hai lần, mặc dù một số chuyên gia có thể chỉ ra sự xuất hiện của điện toán đám mây và các ý tưởng hiện đại về các đối tượng và lớp như một vòng mới trong sự phát triển của công nghệ CNTT.
Các thuật ngữ "đối tượng" và "mục tiêu" trong ngữ cảnh hiện đại của OOP thường được gán cho những năm 50 và 60 của thế kỷ trước, nhưng chúng gắn liền với năm 1965 và sự xuất hiện của Simula, Lisp, Algol, Smalltalk.
Vào những ngày đó, lập trình chưa được phát triển đặc biệt và không thể đáp ứng đầy đủ các khái niệm mang tính cách mạng. Cuộc đấu tranh về ý tưởng và phong cách lập trình (chủ yếu là C / C ++ và Pascal) vẫn còn rất xa và cơ sở dữ liệu vẫn đang được hình thành về mặt khái niệm.
Vào cuối những năm 80 và đầu những năm 90, các đối tượng xuất hiện trong Pascal và mọi người đều nhớ đến các lớp trong C / C ++ - điều này đánh dấu một vòng quan tâm mới đối với OOP và khi đó các công cụ, chủ yếu là ngôn ngữ lập trình, đã trở nên không chỉ hỗ trợ các ý tưởng hướng đối tượng, nhưng phát triển cho phù hợp.
Tất nhiên, nếu các thuật toán đệ quy trước đây chỉ là các hàm được sử dụng trong mã chung của chương trình, thì giờ đây đệ quy có thể trở thành một phần của các thuộc tính của một đối tượng (lớp), mang lại những cơ hội thú vị trong bối cảnh kế thừa.
Tính năng của OOP hiện đại
Sự phát triển của OOP được khai báo ban đầu các đối tượng (lớp) là tập hợp dữ liệu và thuộc tính (phương thức). Trên thực tế, đó là về dữ liệu có cú pháp và ý nghĩa. Nhưng sau đó không thể giới thiệu OOP như một công cụ để quản lý các đối tượng thực.
OOP đã trở thành công cụ quản lý các đối tượng "bản chất máy tính". Một tập lệnh, một nút, một mục menu, một thanh menu, một thẻ trong cửa sổ trình duyệt là một đối tượng. Nhưng không phải là một cái máy, một sản phẩm thực phẩm, một từ hay một câu. Các đối tượng thực vẫn nằm ngoài lập trình hướng đối tượng và các công cụ máy tính đã thực hiện một hiện thân mới.
Do sự khác biệt trong các ngôn ngữ lập trình phổ biến, nhiều phương ngữ của OOP đã xuất hiện. Về mặt ngữ nghĩa, chúng thực tế tương đương nhau, và sự tập trung của chúng vào lĩnh vực công cụ chứ không phải lĩnh vực ứng dụng, làm cho việc mô tả các đối tượng thực có thể vượt ra ngoài.các thuật toán và đảm bảo "sự tồn tại" đa nền tảng và đa ngôn ngữ của chúng.
Ngăn xếp và cơ chế gọi hàm
Cơ chế gọi hàm (thủ tục, thuật toán) yêu cầu truyền dữ liệu (tham số), trả về kết quả và ghi nhớ địa chỉ của toán tử phải nhận quyền điều khiển sau khi hàm (thủ tục) hoàn thành.
Thông thường, ngăn xếp được sử dụng cho mục đích này, mặc dù ngôn ngữ lập trình hoặc bản thân nhà phát triển có thể cung cấp nhiều tùy chọn để chuyển quyền điều khiển. Lập trình hiện đại thừa nhận rằng tên của một hàm không chỉ có thể là một tham số: nó có thể được hình thành trong quá trình thực thi thuật toán. Một thuật toán cũng có thể được tạo trong khi thực hiện một thuật toán khác.
Khái niệm về thuật toán đệ quy, khi tên và nội dung của chúng có thể được xác định tại thời điểm hình thành nhiệm vụ (chọn thuật toán mong muốn), mở rộng đệ quy không chỉ về cách thực hiện điều gì đó mà còn cả chính xác người nên làm đi. Việc chọn một thuật toán theo tên "có nghĩa" của nó là rất hứa hẹn, nhưng sẽ gây khó khăn.
Đệ quy trên một tập hợp các hàm
Bạn không thể nói rằng một thuật toán là đệ quy khi nó gọi chính nó và đó là nó. Lập trình không phải là một giáo điều và khái niệm đệ quy không phải là một yêu cầu riêng để gọi chính bạn từ phần thân của thuật toán của riêng bạn.
Ứng dụng thực tế không phải lúc nào cũng cho giải pháp sạch. Thông thường, dữ liệu ban đầu phải được chuẩn bị và kết quả của lệnh gọi đệ quy phải được phân tích trong bối cảnh của toàn bộ vấn đề (toàn bộ thuật toán) trongtổng thể.
Trên thực tế, không chỉ trước khi một hàm đệ quy được gọi, mà còn sau khi nó hoàn thành, một chương trình khác có thể hoặc nên được gọi. Nếu không có vấn đề gì đặc biệt với lệnh gọi: hàm đệ quy A () gọi hàm B (), hàm này thực hiện điều gì đó và gọi A (), thì ngay lập tức sẽ có vấn đề với việc trả về điều khiển. Sau khi hoàn thành lệnh gọi đệ quy, hàm A () phải nhận được quyền điều khiển để gọi lại B (), hàm này sẽ gọi nó một lần nữa. Trả lại quyền điều khiển theo thứ tự trên ngăn xếp trở lại B () là giải pháp sai.
Lập trình viên không bị giới hạn trong việc lựa chọn các tham số và có thể hoàn thành chúng với tên hàm. Nói cách khác, giải pháp lý tưởng là chuyển tên của B () cho A () và để A () tự nó gọi B (). Trong trường hợp này, sẽ không có vấn đề gì với điều khiển trả về và việc triển khai thuật toán đệ quy sẽ minh bạch hơn.
Hiểu và mức độ đệ quy
Vấn đề với việc phát triển các thuật toán đệ quy là bạn cần hiểu động lực của quá trình. Khi sử dụng đệ quy trong các phương thức đối tượng, đặc biệt là ở cấp độ tổ tiên trừu tượng, sẽ có vấn đề trong việc hiểu thuật toán của riêng bạn trong bối cảnh thời gian thực thi của nó.
Hiện tại, không có giới hạn nào về mức lồng nhau của các hàm và dung lượng ngăn xếp trong cơ chế gọi, nhưng có một vấn đề cần hiểu: tại thời điểm nào thì mức dữ liệu hoặc vị trí nào trong thuật toán chung được gọi là đệ quy chức năng và số lượng cuộc gọi mà chính cô ấy là.
Các công cụ gỡ lỗi hiện tại thường không hoạt độngcho lập trình viên biết giải pháp phù hợp.
Vòng lặp và đệ quy
Người ta coi việc thực thi tuần hoàn tương đương với đệ quy. Thật vậy, trong một số trường hợp, thuật toán đệ quy có thể được triển khai theo cú pháp của các cấu trúc có điều kiện và tuần hoàn.
Tuy nhiên, nếu hiểu rõ rằng một chức năng cụ thể phải được thực hiện thông qua thuật toán đệ quy, thì bất kỳ việc sử dụng bên ngoài nào đối với vòng lặp hoặc các câu lệnh điều kiện sẽ bị bỏ qua.
Ý nghĩa ở đây là một giải pháp đệ quy dưới dạng một hàm sử dụng chính nó sẽ là một thuật toán hoàn chỉnh về mặt chức năng. Thuật toán này sẽ yêu cầu người lập trình tạo ra nó với nỗ lực, hiểu được động lực của thuật toán, nhưng nó sẽ là giải pháp cuối cùng mà không cần điều khiển bên ngoài.
Bất kỳ sự kết hợp nào của các toán tử tuần hoàn và điều kiện bên ngoài sẽ không cho phép chúng tôi biểu diễn thuật toán đệ quy dưới dạng một hàm hoàn chỉnh.
Đồng thuận đệ quy và OOP
Trong hầu hết các biến thể của việc phát triển một thuật toán đệ quy, một kế hoạch được nảy sinh để phát triển hai thuật toán. Thuật toán đầu tiên tạo ra một danh sách các đối tượng (phiên bản) trong tương lai và thuật toán thứ hai thực sự là một hàm đệ quy.
Giải pháp tốt nhất sẽ là sắp xếp đệ quy dưới dạng một thuộc tính (phương thức) duy nhất thực sự chứa thuật toán đệ quy và đặt tất cả các công việc chuẩn bị vào hàm tạo đối tượng.
Một thuật toán đệ quy sẽ chỉ là giải pháp phù hợp khi nó hoạt độngchỉ một mình anh ta, không có sự kiểm soát và quản lý từ bên ngoài. Một thuật toán bên ngoài chỉ có thể đưa ra một tín hiệu để hoạt động. Kết quả của công việc này sẽ là giải pháp được mong đợi mà không cần sự hỗ trợ từ bên ngoài.
Đệ quy phải luôn là một giải pháp độc lập hoàn chỉnh.
Hiểu biết trực quan và hoàn thiện chức năng
Khi lập trình hướng đối tượng trở thành tiêu chuẩn trên thực tế, rõ ràng là để viết mã hiệu quả, bạn cần phải thay đổi tư duy của chính mình. Người lập trình phải chuyển từ cú pháp và ngữ nghĩa của ngôn ngữ sang động lực của ngữ nghĩa trong quá trình thực thi thuật toán.
Đặc điểm của đệ quy: nó có thể được áp dụng cho mọi thứ:
- nạo web;
- thao tác tìm kiếm;
- phân tích cú pháp thông tin văn bản;
- đọc hoặc tạo tài liệu MS Word;
- thẻ lấy mẫu hoặc phân tích…
Đặc điểm của OOP: nó cho phép mô tả một thuật toán đệ quy ở cấp độ tổ tiên trừu tượng, nhưng cung cấp cho nó tham chiếu đến các con cháu duy nhất, mỗi thuật toán có bảng dữ liệu và thuộc tính riêng.
Đệ quy là lý tưởng vì nó đòi hỏi tính hoàn chỉnh về mặt chức năng của thuật toán. OOP cải thiện hiệu suất của một thuật toán đệ quy bằng cách cấp cho nó quyền truy cập cho tất cả các phần tử con duy nhất.