เพื่อไม่ให้เขียนบทความใหญ่ๆ สักบทความ ซึ่งจะมีตัวอย่างมากมายของการเรียกซ้ำในภาษา C++ ฉันจะเขียนอีกตัวอย่างหนึ่งของการเรียกซ้ำที่นี่ โดยทั่วไปแล้ว ผู้ที่เข้าใจพื้นฐานและการใช้การเรียกซ้ำโดยตรงในฟังก์ชันของตนสามารถข้ามเนื้อหานี้ได้ นี่คือตัวอย่างของการใช้การเรียกซ้ำ ดังในบทความ ฟังก์ชั่นใน C++ สำหรับผู้เริ่มต้น การเรียกซ้ำ
ปัญหาที่ 1 – การใช้การเรียกซ้ำ แสดงแฟกทอเรียลของตัวเลขตั้งแต่ 1 ถึง N
การเขียนโค้ด
=============================
ขั้นตอนที่ 1 เขียนโปรแกรมเปล่า
=============================
#รวม
#รวม
#รวม
int หลัก()
{
ระบบ("cls");
รับ();
กลับ 0 ;
}
สร้างโปรแกรมเปล่าแล้ว ฉันคิดว่าไม่จำเป็นต้องแสดงความคิดเห็น
ขั้นตอนที่ 2 เราเขียนเราเขียนฟังก์ชันแบบเรียกซ้ำเอง
=========================================
#รวม
#รวม
#รวม
//ฟังก์ชันเรียกซ้ำของเรา
ความเป็นจริงที่แท้จริง (int N )
{
//0! = 1, 1!=1, 2!=2, 3!=6... เพราะ ตัวเลข 2 ตัวแรกเป็นตัวเลขและไม่ได้เรียงลำดับอย่างเข้มงวด เราบังคับใช้จุดนี้ในโค้ด
ถ้าไม่มี<2
return 1
;
มิฉะนั้นให้ส่งคืน n * ข้อเท็จจริง(n–1)
//ในที่นี้ฟังก์ชันจะเรียกตัวมันเอง
}
int หลัก()
{
ระบบ("cls");
ศาล<
รับ();
กลับ 0 ;
}
ddd
============
ส่วนหลักในโปรแกรมเรียกซ้ำ C++
กลับไม่มี * ข้อเท็จจริง(n–1)
ฟังก์ชันของเราจะคำนวณใหม่เพื่อให้ได้ค่าก่อนหน้า ค่าจริงคือพารามิเตอร์ที่ส่งไป nจากจุดที่เรียกใช้ฟังก์ชัน จุดประสงค์ของการเรียกใช้ฟังก์ชันของเราคือการเรียกใช้จากบล็อกหลักของโปรแกรม ในกรณีของเรา เราเรียกมันจากฟังก์ชัน int หลัก()
ทำไมฉันถึงเขียนไม่ใช่อันถัดไป แต่อันก่อนหน้า? เมื่อคูณตัวเลขแล้ว 0 * 1 แรกนี่คือค่าปัจจุบันของเรา 1 และศูนย์คือค่าการคำนวณก่อนหน้า นี่คือสาระสำคัญทั้งหมดของการเรียกซ้ำ เราคำนวณมูลค่าปัจจุบันโดยใช้ค่าก่อนหน้า ในขณะที่ค่าก่อนหน้าจะได้มาจากการคำนวณเดียวกัน คอมไพเลอร์จะคำนวณค่าก่อนหน้าและเก็บค่านี้ไว้ในหน่วยความจำ สิ่งที่เราต้องทำคือให้คำแนะนำ
- ด้วยคุณสมบัติของคอมไพเลอร์นี้ ฟังก์ชันที่พบกับคำสั่งให้เรียกตัวเอง (ในกรณีของเรา ข้อเท็จจริง(n–1)
) จะไม่เขียนทับพารามิเตอร์ที่ส่งไปให้ nเพื่อคำนวณฟังก์ชัน พารามิเตอร์ที่ส่งผ่านไปยัง nมันยังคงอยู่ในความทรงจำ ในกรณีนี้ จะมีการกำหนดพื้นที่หน่วยความจำอื่นเพิ่มเติม โดยที่ฟังก์ชันแบบเรียกซ้ำของเราจะทำการคำนวณแบบเรียกซ้ำเพื่อให้ได้ผลลัพธ์ก่อนหน้า
ขอให้โปรแกรมเมอร์ยกโทษให้ฉันสำหรับการตัดสินที่เคี้ยวเอื้องเช่นนี้ นี่เป็นวิธีที่ผู้เริ่มต้นรับรู้ถึงการเรียกซ้ำโดยประมาณ
ฉันหวังว่าบล็อก C++ สำหรับผู้เริ่มต้นจะมีประโยชน์กับบางคนและช่วยให้ใครบางคนเข้าใจแนวคิดพื้นฐานของฟังก์ชันแบบเรียกซ้ำใน C++
บันทึก. ในบทความนี้ เช่นเดียวกับในบทความก่อนหน้านี้ ฉันไม่ได้คำนวณจาก 1 ถึง N แต่เป็นค่าที่ป้อนภายในโปรแกรม ประเด็นก็คือฉันไม่ต้องการเขียนโค้ดเพิ่มอีกบรรทัดและสันนิษฐานว่าผู้ใช้มีความชำนาญในการป้อนข้อมูลและแสดงข้อมูลบนหน้าจออยู่แล้ว
การเรียกซ้ำเป็นปรากฏการณ์ทั่วไปที่เกิดขึ้นไม่เพียงแต่ในสาขาวิทยาศาสตร์เท่านั้น แต่ยังเกิดขึ้นในชีวิตประจำวันด้วย ตัวอย่างเช่น เอฟเฟ็กต์ Droste, สามเหลี่ยม Sierpinski ฯลฯ วิธีที่ง่ายที่สุดในการดูการเรียกซ้ำคือการชี้กล้องเว็บไปที่หน้าจอคอมพิวเตอร์ตามปกติหลังจากเปิดเครื่อง ดังนั้นกล้องจะบันทึกภาพหน้าจอคอมพิวเตอร์และแสดงบนหน้าจอนี้ก็จะมีลักษณะคล้ายวงปิด ผลก็คือเราจะสังเกตเห็นบางสิ่งที่คล้ายกับอุโมงค์
ในการเขียนโปรแกรม การเรียกซ้ำมีความสัมพันธ์อย่างใกล้ชิดกับฟังก์ชัน ต้องขอบคุณฟังก์ชันในการเขียนโปรแกรมที่มีทั้งฟังก์ชันการเรียกซ้ำหรือฟังก์ชันเรียกซ้ำ พูดง่ายๆ ก็คือ การเรียกซ้ำคือคำจำกัดความของส่วนหนึ่งของฟังก์ชัน (วิธีการ) ผ่านตัวมันเอง นั่นคือ เป็นฟังก์ชันที่เรียกตัวเองโดยตรง (ในร่างกาย) หรือโดยอ้อม (ผ่านฟังก์ชันอื่น) ปัญหาการเรียกซ้ำโดยทั่วไปคือ: การหา n!, ตัวเลขฟีโบนัชชี เราได้แก้ไขปัญหาดังกล่าวแล้ว แต่การใช้ลูปนั่นคือวนซ้ำ โดยทั่วไปแล้ว ทุกสิ่งที่ถูกแก้ไขแบบวนซ้ำสามารถแก้ไขได้แบบวนซ้ำ นั่นคือ การใช้ฟังก์ชันแบบวนซ้ำ วิธีแก้ปัญหาทั้งหมดอยู่ที่การแก้ปัญหาหลักหรือที่เรียกกันว่ากรณีฐาน มีสิ่งเช่นขั้นตอนการเรียกซ้ำหรือการเรียกซ้ำ ในกรณีที่มีการเรียกใช้ฟังก์ชันแบบเรียกซ้ำเพื่อแก้ไขปัญหาที่ซับซ้อน (ไม่ใช่กรณีพื้นฐาน) จะมีการดำเนินการเรียกหรือขั้นตอนแบบเรียกซ้ำจำนวนหนึ่งเพื่อลดปัญหาให้เหลือปัญหาที่ง่ายขึ้น และต่อๆ ไปจนกว่าเราจะได้วิธีแก้ปัญหาเบื้องต้น มาพัฒนาโปรแกรมที่ประกาศฟังก์ชันแบบเรียกซ้ำที่คำนวณ n!
"stdafx.h" #รวม
ศาล
// รหัส รหัส::บล็อก
// รหัส Dev-C++
ใช้เนมสเปซมาตรฐาน; int factorial แบบยาวที่ไม่ได้ลงนาม (int แบบยาวที่ไม่ได้ลงนาม); // ต้นแบบของฟังก์ชันแบบเรียกซ้ำ int i = 1; // การเริ่มต้นตัวแปรโกลบอลเพื่อนับจำนวนการเรียกซ้ำผลลัพธ์ int แบบยาวที่ไม่ได้ลงนาม // ตัวแปรโกลบอลสำหรับจัดเก็บผลลัพธ์ที่ส่งคืนของฟังก์ชันแบบเรียกซ้ำ int main(int argc, char* argv) ( int n; // ตัวแปรโลคอลสำหรับส่งหมายเลขที่ป้อนจากแป้นพิมพ์ cout ในประเภทข้อมูลถูกประกาศเป็น unsigned long int เนื่องจากค่าของแฟกทอเรียลเพิ่มขึ้นอย่างรวดเร็ว เช่น 10 แล้ว! = 3,628,800 หากขนาดของชนิดข้อมูลไม่เพียงพอ ผลลัพธ์ที่ได้จะเป็นค่าที่ไม่ถูกต้องโดยสิ้นเชิง รหัสประกาศตัวดำเนินการมากกว่าที่จำเป็นในการค้นหา n! ซึ่งหลังจากรันแล้ว โปรแกรมจะแสดงสิ่งที่เกิดขึ้นในแต่ละขั้นตอนของการโทรซ้ำ โปรดสังเกตบรรทัดโค้ดที่ไฮไลต์ บรรทัดที่ 23, 24, 28เป็นวิธีแก้ปัญหาแบบเรียกซ้ำของ n!. บรรทัดที่ 23, 24เป็นคำตอบพื้นฐานของฟังก์ชันแบบเรียกซ้ำ ซึ่งก็คือทันทีที่ค่าในตัวแปร ฉจะเท่ากับ 1 หรือ 0 (เนื่องจากเรารู้ว่า 1! = 1 และ 0! = 1) การโทรซ้ำจะหยุดลงและค่าต่างๆ จะเริ่มส่งคืนสำหรับการโทรซ้ำแต่ละครั้ง เมื่อค่าสำหรับการเรียกซ้ำครั้งแรกกลับมา โปรแกรมจะส่งกลับค่าของแฟกทอเรียลที่คำนวณได้ ใน บรรทัดที่ 28ฟังก์ชัน factorial() เรียกตัวเอง แต่อาร์กิวเมนต์มีค่าน้อยกว่าหนึ่งรายการ ข้อโต้แย้งจะลดลงในแต่ละครั้งเพื่อให้ได้วิธีแก้ปัญหาเฉพาะ ผลลัพธ์ของโปรแกรม (ดูรูปที่ 1)
ป้อน n!: 5 ขั้นตอนที่ 1 ผลลัพธ์= 0 ขั้นตอนที่ 2 ผลลัพธ์= 0 ขั้นตอนที่ 3 ผลลัพธ์= 0 ขั้นตอนที่ 4 ผลลัพธ์= 0 5!=120
รูปที่ 1 - การเรียกซ้ำใน C ++
ขึ้นอยู่กับผลลัพธ์ของโปรแกรม แต่ละขั้นตอนจะมองเห็นได้ชัดเจน และผลลัพธ์ในแต่ละขั้นตอนจะเป็นศูนย์ ยกเว้นการเรียกซ้ำครั้งล่าสุด จำเป็นต้องคำนวณแฟคทอเรียลห้าตัว โปรแกรมทำการเรียกซ้ำสี่ครั้ง และในการเรียกครั้งที่ห้าก็พบกรณีพื้นฐาน และเมื่อโปรแกรมมีวิธีแก้ปัญหากรณีฐานแล้ว มันก็แก้ไขขั้นตอนก่อนหน้าและแสดงผลลัพธ์โดยรวม ในรูปที่ 1 มองเห็นได้เพียงสี่ขั้นตอนเท่านั้น เนื่องจากในขั้นตอนที่ห้า พบวิธีแก้ปัญหาบางส่วน ซึ่งท้ายที่สุดแล้วก็ได้ผลลัพธ์สุดท้ายกลับมา นั่นคือ 120 รูปที่ 2 แสดงรูปแบบการคำนวณแบบเรียกซ้ำ 5! แผนภาพแสดงให้เห็นอย่างชัดเจนว่าผลลัพธ์แรกจะถูกส่งกลับเมื่อถึงวิธีแก้ปัญหาเฉพาะ แต่ไม่ใช่ในทันทีหลังจากการเรียกซ้ำแต่ละครั้ง
รูปที่ 2 - การเรียกซ้ำใน C ++
เพื่อหา 5! ต้องรู้4! และคูณด้วย 5; 4! = 4 * 3! และอื่น ๆ ตามแผนภาพที่แสดงในรูปที่ 2 การคำนวณจะลดลงเพื่อค้นหากรณีพิเศษนั่นคือ 1! หลังจากนั้นค่าจะถูกส่งกลับไปยังการโทรซ้ำแต่ละครั้งตามลำดับ การเรียกซ้ำครั้งล่าสุดจะส่งกลับค่า 5!
เรามาปรับปรุงโปรแกรมเพื่อค้นหาแฟกทอเรียลเพื่อให้ได้ตารางแฟคทอเรียลกัน ในการทำเช่นนี้ เราจะประกาศ for loop ซึ่งเราจะเรียกใช้ฟังก์ชันแบบเรียกซ้ำ
ศาล // รหัส รหัส::บล็อก // รหัส Dev-C++ ใช้เนมสเปซมาตรฐาน; int factorial แบบยาวที่ไม่ได้ลงนาม (int แบบยาวที่ไม่ได้ลงนาม); // ต้นแบบของฟังก์ชันแบบเรียกซ้ำ int i = 1; // การเริ่มต้นตัวแปรโกลบอลเพื่อนับจำนวนการเรียกซ้ำผลลัพธ์ int แบบยาวที่ไม่ได้ลงนาม // ตัวแปรโกลบอลสำหรับจัดเก็บผลลัพธ์ที่ส่งคืนของฟังก์ชันแบบเรียกซ้ำ int main(int argc, char* argv) ( int n; // ตัวแปรโลคอลสำหรับส่งหมายเลขที่ป้อนจากแป้นพิมพ์ cout สำหรับ (int k = 1; kมีการประกาศการวนซ้ำซึ่งเรียกใช้ฟังก์ชันแบบเรียกซ้ำ ทุกสิ่งที่ไม่จำเป็นในโปรแกรมจะถูกใส่ความคิดเห็นไว้ หลังจากเริ่มโปรแกรม คุณจะต้องป้อนค่าที่ต้องคำนวณแฟกทอเรียล ผลลัพธ์ของโปรแกรมแสดงในรูปที่ 3 ป้อน 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 รูปที่ 3 - การเรียกซ้ำใน C ++ ตอนนี้คุณสามารถดูได้ว่าแฟคทอเรียลเพิ่มขึ้นเร็วแค่ไหน ผลลัพธ์คือ 14 แล้ว! ไม่ถูกต้อง นี่เป็นผลมาจากการขาดขนาดประเภทข้อมูล ค่าที่ถูกต้องคือ 14! = 87178291200. มาดูปัญหาทั่วไปอีกปัญหาหนึ่ง - การค้นหาหมายเลขฟีโบนัชชีโดยใช้การเรียกซ้ำ ด้านล่างนี้คือโค้ดสำหรับวิธีแก้ปัญหาแบบเรียกซ้ำสำหรับปัญหาดังกล่าว เราป้อนหมายเลขซีเรียลของตัวเลขจากชุด Fibonacci ในบรรทัดเดียวกัน และโปรแกรมจะค้นหาตัวเลขทั้งหมดจากชุด Fibonacci ซึ่งมีหมายเลขซีเรียลน้อยกว่าหรือเท่ากับหมายเลขที่ป้อน // fibonacci.cpp: กำหนดจุดเริ่มต้นสำหรับแอปพลิเคชันคอนโซล #รวม "stdafx.h" #รวม ศาล // รหัส รหัส::บล็อก // fibonacci.cpp: กำหนดจุดเริ่มต้นสำหรับแอปพลิเคชันคอนโซล #รวม ใช้เนมสเปซมาตรฐาน; int factorial แบบยาวที่ไม่ได้ลงนาม (int แบบยาวที่ไม่ได้ลงนาม); // ต้นแบบของฟังก์ชันแบบเรียกซ้ำ int i = 1; // การเริ่มต้นตัวแปรโกลบอลเพื่อนับจำนวนการเรียกซ้ำผลลัพธ์ int แบบยาวที่ไม่ได้ลงนาม // ตัวแปรโกลบอลสำหรับจัดเก็บผลลัพธ์ที่ส่งคืนของฟังก์ชันแบบเรียกซ้ำ int main(int argc, char* argv) ( int n; // ตัวแปรโลคอลสำหรับส่งหมายเลขที่ป้อนจากแป้นพิมพ์ cout สำหรับ (int counter = 1; counterบรรทัดที่ 6 เพื่อใช้ฟังก์ชัน setw() ซึ่งจะจัดแนวคอลัมน์แรกของตัวเลข ซึ่งก็คือตัวเลข ดังที่เราเห็น อันดับแรกตัวเลขจะเป็นตัวเลขหลักเดียวตั้งแต่ 1 ถึง 9 และจากนั้นก็จะมีตัวเลขสองหลัก หากคุณลบฟังก์ชันนี้ ตัวเลขตั้งแต่ 1 ถึง 9 จะเลื่อนไปทางซ้าย ผลลัพธ์ของโปรแกรม (ดูรูปที่ 4) ป้อนตัวเลขจากชุดฟีโบนัชชี: 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 8 = 196418 29 = 317811 30 = 514229 วิธีแก้ปัญหาคือการแบ่งปัญหาที่ซับซ้อนออกเป็นสองปัญหาที่ง่ายกว่า ตัวอย่างเช่น หากต้องการค้นหาตัวเลขที่สามจากชุด Fibonacci คุณต้องค้นหาตัวเลขตัวแรกและตัวที่สองก่อน จากนั้นจึงบวกเข้าด้วยกัน หมายเลขแรกเป็นกรณีพิเศษและเท่ากับ 0 (ศูนย์) หมายเลขที่สองก็เป็นกรณีพิเศษและเท่ากับ 1 ดังนั้น หมายเลขที่สามจากชุดฟีโบนัชชีจึงเท่ากับผลรวมของหมายเลขแรกและหมายเลขที่สอง = 1. ฟังก์ชันเรียกซ้ำที่เราตั้งโปรแกรมไว้เพื่อค้นหาหมายเลขลำดับฟีโบนัชชีโดยให้เหตุผลในลักษณะเดียวกันโดยประมาณ มาพัฒนาโปรแกรมแบบเรียกซ้ำอีกตัวที่ช่วยแก้ปัญหาแบบคลาสสิก - "หอคอยแห่งฮานอย" ให้มาสามแท่งโดยหนึ่งในนั้นมีดิสก์จำนวนที่ n ซ้อนกันและดิสก์มีขนาดไม่เท่ากัน (ดิสก์ที่มีเส้นผ่านศูนย์กลางต่างกัน) และจัดเรียงในลักษณะที่เมื่อคุณย้ายจากบนลงล่าง เส้นผ่านศูนย์กลางของดิสก์จะค่อยๆเพิ่มขึ้นตามแกน นั่นคือดิสก์ขนาดเล็กควรอยู่บนดิสก์ขนาดใหญ่เท่านั้น คุณต้องย้ายดิสก์กองนี้จากแกนเริ่มต้นไปยังอันที่เหลืออีกสองอัน (ส่วนใหญ่มักจะเป็นแท่งที่สาม) ใช้แท่งอันใดอันหนึ่งเป็นตัวเสริม คุณสามารถย้ายดิสก์ได้ครั้งละหนึ่งดิสก์เท่านั้น และไม่ควรวางดิสก์ที่มีขนาดใหญ่กว่าไว้บนดิสก์ที่มีขนาดเล็กกว่า สมมติว่าคุณต้องย้ายดิสก์สามแผ่นจากก้านแรกไปยังก้านที่สาม ซึ่งหมายความว่าก้านที่สองเป็นส่วนเสริม วิธีแก้ปัญหาด้วยภาพสำหรับปัญหานี้ถูกนำไปใช้ใน Flash คลิกที่ปุ่มเริ่มต้นเพื่อเริ่มภาพเคลื่อนไหว ปุ่มหยุดเพื่อหยุด ต้องเขียนโปรแกรมสำหรับดิสก์จำนวนที่ n เนื่องจากเราแก้ไขปัญหานี้แบบวนซ้ำ เราจึงต้องค้นหากรณีพิเศษของวิธีแก้ปัญหาก่อน ในปัญหานี้มีกรณีพิเศษเพียงกรณีเดียว - นี่คือเมื่อจำเป็นต้องย้ายดิสก์เพียงแผ่นเดียวและในกรณีนี้ไม่จำเป็นต้องใช้แกนเสริม แต่เราก็ไม่สนใจเรื่องนี้ ตอนนี้จำเป็นต้องจัดระเบียบโซลูชันแบบเรียกซ้ำหากจำนวนดิสก์มีมากกว่าหนึ่งดิสก์ ให้เราแนะนำสัญกรณ์บางอย่างเพื่อไม่ให้เขียนมากเกินไป: <Б>
- แกนซึ่งดิสก์อยู่ในตอนแรก (แกนฐาน) นอกจากนี้ เมื่ออธิบายอัลกอริทึมในการแก้ปัญหา เราจะใช้สัญลักษณ์เหล่านี้ เพื่อย้ายสามดิสก์จาก <Б>
บน <Ф>
เราต้องย้ายดิสก์ทั้งสองออกก่อน <Б>
บน <П>
จากนั้นย้ายดิสก์แผ่นที่สาม (ใหญ่ที่สุด) ไปที่ <Ф>
, เพราะ <Ф>
ฟรี เพื่อเคลื่อนย้าย nดิสก์ด้วย <Б>
บน <Ф>
เราต้องย้ายก่อน n-1ดิสก์ด้วย <Б>
บน <П>
จากนั้นย้ายดิสก์ที่ n (ใหญ่ที่สุด) ไปที่ <Ф>
, เพราะ <Ф>
ฟรี หลังจากนี้คุณจะต้องย้าย n-1ดิสก์ด้วย <П>
บน <Ф>
ขณะใช้ไม้เท้า <Б>
เป็นตัวช่วย การกระทำทั้งสามนี้เป็นอัลกอริธึมแบบเรียกซ้ำทั้งหมด อัลกอริทึมเดียวกันในรหัสเทียม: // hanoi_tower.cpp: กำหนดจุดเริ่มต้นสำหรับแอปพลิเคชันคอนโซล // โปรแกรมที่แก้ปัญหาหอคอยฮานอยแบบวนซ้ำ #include "stdafx.h" #include ศาล // รหัส รหัส::บล็อก ศาล int help_rod; // บล็อกสำหรับกำหนดจำนวนของแท่งเสริมโดยวิเคราะห์จำนวนของแท่งเริ่มต้นและแท่งสุดท้ายถ้า (basic_rod != 2 && Final_rod != 2) help_rod = 2; อย่างอื่นถ้า (basic_rod != 1 && Final_rod != 1) help_rod = 1; อย่างอื่นถ้า (basic_rod != 3 && Final_rod != 3) help_rod = 3;tower(// เรียกใช้ฟังก์ชันแบบเรียกซ้ำเพื่อแก้ปัญหาหมายเลข Towers of Hanoi, // ตัวแปรที่เก็บจำนวนดิสก์ที่ต้องย้าย basic_rod, // ตัวแปรที่เก็บจำนวนแท่งที่ดิสก์จะเริ่มต้น ตั้งอยู่ help_rod , // ตัวแปรที่เก็บหมายเลขของร็อดซึ่งใช้เป็น Final_rod เสริม); // ตัวแปรจัดเก็บจำนวนแกนที่ต้องย้ายดิสก์ ส่งคืน 0; ) หอคอยเป็นโมฆะ(int count_disk, int baza, int help_baza, int new_baza) ( ถ้า (count_disk == 1) // เงื่อนไขสำหรับการสิ้นสุดการโทรแบบเรียกซ้ำ ( cout รูปที่ 5 แสดงตัวอย่างโปรแกรมเรียกซ้ำ Tower of Hanoi ขั้นแรก เราป้อนจำนวนดิสก์เท่ากับสาม จากนั้นจึงป้อนแกนฐาน (อันแรก) และกำหนดแกนสุดท้าย (ที่สาม) ก้านที่สองกลายเป็นส่วนเสริมโดยอัตโนมัติ โปรแกรมสร้างผลลัพธ์ที่สอดคล้องกับวิธีแก้ปัญหาภาพเคลื่อนไหวสำหรับปัญหานี้อย่างสมบูรณ์ ใส่จำนวนดิสก์: 3 ใส่จำนวนแกนพื้นฐาน: 1 ใส่จำนวนแกนสุดท้าย: 3 1) 1 -> 3 2) 1 -> 2 3) 3 -> 2 4) 1 -> 3 5) 2 -> 1 6) 2 -> 3 7) 1 -> 3 รูปที่ 5 - การเรียกซ้ำใน C ++ ในการเขียนโปรแกรม การเรียกซ้ำมีความสัมพันธ์อย่างใกล้ชิดกับฟังก์ชัน ต้องขอบคุณฟังก์ชันในการเขียนโปรแกรมที่มีทั้งฟังก์ชันการเรียกซ้ำหรือฟังก์ชันเรียกซ้ำ พูดง่ายๆ ก็คือ การเรียกซ้ำคือคำจำกัดความของส่วนหนึ่งของฟังก์ชัน (วิธีการ) ผ่านตัวมันเอง นั่นคือ เป็นฟังก์ชันที่เรียกตัวเองโดยตรง (ในร่างกาย) หรือโดยอ้อม (ผ่านฟังก์ชันอื่น) มีการพูดถึงเรื่องการเรียกซ้ำมากมาย นี่คือแหล่งข้อมูลที่ดีบางส่วน: จากเครือข่าย อัลกอริธึมใดๆ ที่นำมาใช้ในรูปแบบเรียกซ้ำสามารถเขียนใหม่ได้ในรูปแบบวนซ้ำและในทางกลับกัน คำถามยังคงอยู่ว่าสิ่งนี้จำเป็นหรือไม่และจะมีประสิทธิภาพเพียงใด สามารถให้ข้อโต้แย้งต่อไปนี้เพื่อพิสูจน์สิ่งนี้ ประการแรก เราสามารถจำคำจำกัดความของการเรียกซ้ำและการวนซ้ำได้ การเรียกซ้ำเป็นวิธีการจัดการการประมวลผลข้อมูลที่โปรแกรมเรียกตัวเองโดยตรงหรือด้วยความช่วยเหลือของโปรแกรมอื่น การวนซ้ำเป็นวิธีการจัดการการประมวลผลข้อมูลซึ่งมีการกระทำบางอย่างซ้ำหลายครั้งโดยไม่ทำให้เกิดการเรียกโปรแกรมแบบเรียกซ้ำ หลังจากนั้นเราสามารถสรุปได้ว่าพวกมันใช้แทนกันได้ แต่ต้นทุนและความเร็วไม่เท่ากันเสมอไป เพื่อพิสูจน์สิ่งนี้ เราสามารถยกตัวอย่างต่อไปนี้: มีฟังก์ชันที่ในการจัดระเบียบอัลกอริธึมบางอย่าง มีการวนซ้ำที่ดำเนินการตามลำดับของการกระทำ ขึ้นอยู่กับค่าปัจจุบันของตัวนับ (อาจไม่ขึ้นอยู่กับ มัน). เนื่องจากมีวัฏจักร หมายความว่าร่างกายจะทำซ้ำลำดับของการกระทำ นั่นคือการวนซ้ำของวัฏจักร คุณสามารถย้ายการดำเนินการไปยังรูทีนย่อยที่แยกจากกัน และส่งผ่านค่าตัวนับได้ ถ้ามี เมื่อเสร็จสิ้นการดำเนินการของรูทีนย่อย เราจะตรวจสอบเงื่อนไขในการดำเนินการลูป และหากเป็นจริง เราจะดำเนินการเรียกรูทีนย่อยใหม่ หากเป็นเท็จ เราจะดำเนินการให้เสร็จสิ้น เพราะ เราวางเนื้อหาทั้งหมดของลูปไว้ในรูทีนย่อย ซึ่งหมายความว่าเงื่อนไขในการดำเนินการวนซ้ำจะถูกวางไว้ในรูทีนย่อยด้วย และสามารถรับได้ผ่านค่าที่ส่งคืนของฟังก์ชัน พารามิเตอร์ที่ส่งผ่านโดยการอ้างอิงหรือตัวชี้ไปยังรูทีนย่อย ตลอดจนตัวแปรทั่วโลก นอกจากนี้ มันเป็นเรื่องง่ายที่จะแสดงว่าการเรียกไปยังรูทีนย่อยที่กำหนดจากลูปสามารถแปลงเป็นการเรียกได้อย่างง่ายดาย หรือไม่ใช่การเรียก (ส่งคืนค่าหรือเพียงทำงานให้เสร็จสิ้น) ของรูทีนย่อยจากตัวมันเอง โดยอยู่ภายใต้เงื่อนไขบางประการ (เหล่านั้น ที่เคยอยู่ในสภาพวนซ้ำ) ทีนี้ ถ้าคุณดูโปรแกรมนามธรรมของเรา ดูเหมือนว่าการส่งค่าไปยังรูทีนย่อยคร่าวๆ แล้วใช้งาน ซึ่งรูทีนย่อยจะเปลี่ยนเมื่อเสร็จสิ้น เช่น เราแทนที่การวนซ้ำด้วยการเรียกซ้ำไปยังรูทีนย่อยเพื่อแก้ไขอัลกอริทึมที่กำหนด งานในการนำการเรียกซ้ำมาสู่แนวทางวนซ้ำนั้นมีความสมมาตร โดยสรุป เราสามารถแสดงความคิดต่อไปนี้: สำหรับแต่ละแนวทางจะมีประเภทของงานของตัวเอง ซึ่งถูกกำหนดโดยข้อกำหนดเฉพาะสำหรับงานเฉพาะ คุณสามารถหาข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้ได้ ดังนั้นฟังก์ชันแบบเรียกซ้ำจึงประกอบด้วย โซลูชันคลาสสาธารณะ ( การเรียกซ้ำ int แบบคงที่สาธารณะ (int n) ( // เงื่อนไขการออก // กรณีพื้นฐาน // เมื่อใดที่จะหยุดการเรียกซ้ำซ้ำ ถ้า (n == 1) ( ส่งคืน 1; ) // ขั้นตอนการเรียกซ้ำ / การส่งคืนเงื่อนไขการเรียกซ้ำ การเรียกซ้ำ ( n - 1) * n; ) public static void main (String args) ( System.out.println (recursion (5)); // เรียกใช้ฟังก์ชันแบบเรียกซ้ำ ) ) เงื่อนไขพื้นฐานคือเงื่อนไขเมื่อ n=1 เนื่องจากเรารู้ว่า 1!=1 และคำนวณ 1! เราไม่ต้องการอะไรเลย ในการคำนวณ 2! เราสามารถใช้ 1! เช่น 2!=1!*2. ในการคำนวณ 3! เราต้องการ 2!*3... เพื่อคำนวณ n! เราต้องการ (n-1)!*n นี่คือขั้นตอนการเรียกซ้ำ กล่าวอีกนัยหนึ่ง หากต้องการหาค่าแฟกทอเรียลของตัวเลข n ก็เพียงพอที่จะคูณค่าแฟกทอเรียลของตัวเลขก่อนหน้าด้วย n แท็ก: ใส่จำนวนดิสก์: 3 ใส่จำนวนแกนพื้นฐาน: 1 ใส่จำนวนแกนสุดท้าย: 3 1) 1 -> 3 2) 1 -> 2 3) 3 -> 2 4) 1 -> 3 5) 2 -> 1 6) 2 -> 3 7) 1 -> 3 รูปที่ 5 - การเรียกซ้ำใน C ++ ในการเขียนโปรแกรม การเรียกซ้ำมีความสัมพันธ์อย่างใกล้ชิดกับฟังก์ชัน ต้องขอบคุณฟังก์ชันในการเขียนโปรแกรมที่มีทั้งฟังก์ชันการเรียกซ้ำหรือฟังก์ชันเรียกซ้ำ พูดง่ายๆ ก็คือ การเรียกซ้ำคือคำจำกัดความของส่วนหนึ่งของฟังก์ชัน (วิธีการ) ผ่านตัวมันเอง นั่นคือ เป็นฟังก์ชันที่เรียกตัวเองโดยตรง (ในร่างกาย) หรือโดยอ้อม (ผ่านฟังก์ชันอื่น) มีการพูดถึงเรื่องการเรียกซ้ำมากมาย นี่คือแหล่งข้อมูลที่ดีบางส่วน: จากเครือข่าย อัลกอริธึมใดๆ ที่นำมาใช้ในรูปแบบเรียกซ้ำสามารถเขียนใหม่ได้ในรูปแบบวนซ้ำและในทางกลับกัน คำถามยังคงอยู่ว่าสิ่งนี้จำเป็นหรือไม่และจะมีประสิทธิภาพเพียงใด สามารถให้ข้อโต้แย้งต่อไปนี้เพื่อพิสูจน์สิ่งนี้ ประการแรก เราสามารถจำคำจำกัดความของการเรียกซ้ำและการวนซ้ำได้ การเรียกซ้ำเป็นวิธีการจัดการการประมวลผลข้อมูลที่โปรแกรมเรียกตัวเองโดยตรงหรือด้วยความช่วยเหลือของโปรแกรมอื่น การวนซ้ำเป็นวิธีการจัดการการประมวลผลข้อมูลซึ่งมีการกระทำบางอย่างซ้ำหลายครั้งโดยไม่ทำให้เกิดการเรียกโปรแกรมแบบเรียกซ้ำ หลังจากนั้นเราสามารถสรุปได้ว่าพวกมันใช้แทนกันได้ แต่ต้นทุนและความเร็วไม่เท่ากันเสมอไป เพื่อพิสูจน์สิ่งนี้ เราสามารถยกตัวอย่างต่อไปนี้: มีฟังก์ชันที่ในการจัดระเบียบอัลกอริธึมบางอย่าง มีการวนซ้ำที่ดำเนินการตามลำดับของการกระทำ ขึ้นอยู่กับค่าปัจจุบันของตัวนับ (อาจไม่ขึ้นอยู่กับ มัน). เนื่องจากมีวัฏจักร หมายความว่าร่างกายจะทำซ้ำลำดับของการกระทำ นั่นคือการวนซ้ำของวัฏจักร คุณสามารถย้ายการดำเนินการไปยังรูทีนย่อยที่แยกจากกัน และส่งผ่านค่าตัวนับได้ ถ้ามี เมื่อเสร็จสิ้นการดำเนินการของรูทีนย่อย เราจะตรวจสอบเงื่อนไขในการดำเนินการลูป และหากเป็นจริง เราจะดำเนินการเรียกรูทีนย่อยใหม่ หากเป็นเท็จ เราจะดำเนินการให้เสร็จสิ้น เพราะ เราวางเนื้อหาทั้งหมดของลูปไว้ในรูทีนย่อย ซึ่งหมายความว่าเงื่อนไขในการดำเนินการวนซ้ำจะถูกวางไว้ในรูทีนย่อยด้วย และสามารถรับได้ผ่านค่าที่ส่งคืนของฟังก์ชัน พารามิเตอร์ที่ส่งผ่านโดยการอ้างอิงหรือตัวชี้ไปยังรูทีนย่อย ตลอดจนตัวแปรทั่วโลก นอกจากนี้ มันเป็นเรื่องง่ายที่จะแสดงว่าการเรียกไปยังรูทีนย่อยที่กำหนดจากลูปสามารถแปลงเป็นการเรียกได้อย่างง่ายดาย หรือไม่ใช่การเรียก (ส่งคืนค่าหรือเพียงทำงานให้เสร็จสิ้น) ของรูทีนย่อยจากตัวมันเอง โดยอยู่ภายใต้เงื่อนไขบางประการ (เหล่านั้น ที่เคยอยู่ในสภาพวนซ้ำ) ทีนี้ ถ้าคุณดูโปรแกรมนามธรรมของเรา ดูเหมือนว่าการส่งค่าไปยังรูทีนย่อยคร่าวๆ แล้วใช้งาน ซึ่งรูทีนย่อยจะเปลี่ยนเมื่อเสร็จสิ้น เช่น เราแทนที่การวนซ้ำด้วยการเรียกซ้ำไปยังรูทีนย่อยเพื่อแก้ไขอัลกอริทึมที่กำหนด งานในการนำการเรียกซ้ำมาสู่แนวทางวนซ้ำนั้นมีความสมมาตร โดยสรุป เราสามารถแสดงความคิดต่อไปนี้: สำหรับแต่ละแนวทางจะมีประเภทของงานของตัวเอง ซึ่งถูกกำหนดโดยข้อกำหนดเฉพาะสำหรับงานเฉพาะ คุณสามารถหาข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้ได้ ดังนั้นฟังก์ชันแบบเรียกซ้ำจึงประกอบด้วย โซลูชันคลาสสาธารณะ ( การเรียกซ้ำ int แบบคงที่สาธารณะ (int n) ( // เงื่อนไขการออก // กรณีพื้นฐาน // เมื่อใดที่จะหยุดการเรียกซ้ำซ้ำ ถ้า (n == 1) ( ส่งคืน 1; ) // ขั้นตอนการเรียกซ้ำ / การส่งคืนเงื่อนไขการเรียกซ้ำ การเรียกซ้ำ ( n - 1) * n; ) public static void main (String args) ( System.out.println (recursion (5)); // เรียกใช้ฟังก์ชันแบบเรียกซ้ำ ) ) เงื่อนไขพื้นฐานคือเงื่อนไขเมื่อ n=1 เนื่องจากเรารู้ว่า 1!=1 และคำนวณ 1! เราไม่ต้องการอะไรเลย ในการคำนวณ 2! เราสามารถใช้ 1! เช่น 2!=1!*2. ในการคำนวณ 3! เราต้องการ 2!*3... เพื่อคำนวณ n! เราต้องการ (n-1)!*n นี่คือขั้นตอนการเรียกซ้ำ กล่าวอีกนัยหนึ่ง หากต้องการหาค่าแฟกทอเรียลของตัวเลข n ก็เพียงพอที่จะคูณค่าแฟกทอเรียลของตัวเลขก่อนหน้าด้วย n แท็ก: เพิ่มแท็ก วาร์ก พูดว่า: สวัสดีตอนบ่าย ฉันไม่เข้าใจจริงๆ ว่าฟังก์ชันนี้คำนวณอย่างไร
{ ตามความเข้าใจของฉัน ใน n มี 5 เงื่อนไขไม่ตรงกัน จากนั้นโค้ดนี้จะถูกดำเนินการ ผลรวม(n-1)+n นั่นคือบางสิ่งที่ได้รับในวงเล็บปีกกาด้วยการลบจะถูกบวกเข้ากับ 5 แต่อะไรคือ (5 - 1) + 5 และถ้าเป็นเช่นนั้น อะไรจะหยุดการดำเนินการทางคณิตศาสตร์นี้:?: :?: :?: ค่าก่อนหน้าคืออะไร มาจากไหน เท่ากับอะไร:?: :?: :?: ใช่เกือบทุกอย่างเป็นไปตามที่ฉันเข้าใจ (ในย่อหน้าสุดท้ายคุณแสดงการเรียกซ้ำ))) แต่คำถามยังคงอยู่: ผลรวมที่ได้จะปรากฏบนหน้าจอได้อย่างไร? : (5) //เราให้ 5 ให้กับฟังก์ชัน ตรวจสอบความเท่าเทียมกันกับ 1 ไม่เท่ากันก็เรียกฟังก์ชันอีกแล้วส่ง 5-1 เข้าไป 2-1 == 1 เรียกใช้ฟังก์ชันเสร็จแล้ว ใช่ ใช่ ใช่ ฉันไม่มีเวลาเขียนที่ฉันเข้าใจ ทุกอย่างถูกต้อง มีบางอย่างไม่ผ่านทันที ขอบคุณเว็บไซต์ที่ดี)) และไม่มีเหตุผลเลยว่าจะเกิดอะไรขึ้นในบรรทัด 8 หากคุณเปลี่ยนหมายเลขที่ส่งคืนจากส่งคืน 1 เป็น 2 จำนวนจะเปลี่ยนเป็น 16 เงื่อนไขนี้เกี่ยวข้องกับบรรทัดที่ 9 อย่างไร :
<П>
- แท่งเสริมหรือแท่งกลาง
<Ф>
— ก้านสุดท้าย – ก้านที่ต้องเคลื่อนย้ายดิสก์
n-1ย้ายไป <П>
nย้ายไป <Ф>
n-1ย้ายจาก <П>
บน <Ф>
ขณะใช้งาน <Б>
เป็นตัวช่วยสั้น ๆ เกี่ยวกับการเรียกซ้ำ
การเรียกซ้ำเป็นปรากฏการณ์ทั่วไปที่เกิดขึ้นไม่เพียงแต่ในสาขาวิทยาศาสตร์เท่านั้น แต่ยังเกิดขึ้นในชีวิตประจำวันด้วย ตัวอย่างเช่น เอฟเฟ็กต์ Droste, สามเหลี่ยม Sierpinski เป็นต้น วิธีหนึ่งในการดูการเรียกซ้ำคือการชี้กล้องเว็บไปที่หน้าจอคอมพิวเตอร์ โดยธรรมชาติแล้วจะต้องเปิดกล้องขึ้นมาก่อน ดังนั้นกล้องจะบันทึกภาพหน้าจอคอมพิวเตอร์และแสดงบนหน้าจอนี้ก็จะมีลักษณะคล้ายวงปิด ผลก็คือเราจะสังเกตเห็นบางสิ่งที่คล้ายกับอุโมงค์
สันนิษฐานว่าผู้อ่านมีความคุ้นเคยกับการเรียกซ้ำในทางทฤษฎีและรู้ว่ามันคืออะไร ในบทความนี้ เราจะให้ความสำคัญกับปัญหาการเรียกซ้ำมากขึ้น งาน
เมื่อเรียนรู้การเรียกซ้ำ วิธีที่มีประสิทธิภาพที่สุดในการทำความเข้าใจการเรียกซ้ำคือการแก้ปัญหา วิธีแก้ปัญหาการเรียกซ้ำ?
ก่อนอื่น คุณต้องเข้าใจว่าการเรียกซ้ำนั้นเป็นการกระทำที่มากเกินไป โดยทั่วไปแล้ว ทุกสิ่งที่ถูกแก้ไขแบบวนซ้ำสามารถแก้ไขได้แบบวนซ้ำ นั่นคือ การใช้ฟังก์ชันแบบวนซ้ำ
เช่นเดียวกับการแจงนับ (วงจร) การเรียกซ้ำต้องมีเงื่อนไขการหยุด - กรณีพื้นฐาน (ไม่เช่นนั้น เช่นเดียวกับวงจร การเรียกซ้ำจะทำงานตลอดไป - อนันต์) เงื่อนไขนี้เป็นกรณีที่การเรียกซ้ำดำเนินไป (ขั้นตอนการเรียกซ้ำ) ในแต่ละขั้นตอน ฟังก์ชันแบบเรียกซ้ำจะถูกเรียกจนกว่าการเรียกครั้งถัดไปจะทริกเกอร์เงื่อนไขพื้นฐานและการเรียกซ้ำจะหยุด (หรือค่อนข้างจะกลับไปสู่การเรียกฟังก์ชันครั้งล่าสุด) วิธีแก้ปัญหาทั้งหมดอยู่ที่การแก้ไขกรณีพื้นฐาน ในกรณีที่มีการเรียกใช้ฟังก์ชันแบบเรียกซ้ำเพื่อแก้ไขปัญหาที่ซับซ้อน (ไม่ใช่กรณีพื้นฐาน) จะมีการดำเนินการเรียกหรือขั้นตอนแบบเรียกซ้ำจำนวนหนึ่งเพื่อลดปัญหาให้เหลือปัญหาที่ง่ายขึ้น และต่อๆ ไปจนกว่าเราจะได้วิธีแก้ปัญหาเบื้องต้น
ลองดูตัวอย่างการหาแฟกทอเรียลกัน:
เพิ่มแท็ก สั้น ๆ เกี่ยวกับการเรียกซ้ำ
การเรียกซ้ำเป็นปรากฏการณ์ทั่วไปที่เกิดขึ้นไม่เพียงแต่ในสาขาวิทยาศาสตร์เท่านั้น แต่ยังเกิดขึ้นในชีวิตประจำวันด้วย ตัวอย่างเช่น เอฟเฟ็กต์ Droste, สามเหลี่ยม Sierpinski เป็นต้น วิธีหนึ่งในการดูการเรียกซ้ำคือการชี้กล้องเว็บไปที่หน้าจอคอมพิวเตอร์ โดยธรรมชาติแล้วจะต้องเปิดกล้องขึ้นมาก่อน ดังนั้นกล้องจะบันทึกภาพหน้าจอคอมพิวเตอร์และแสดงบนหน้าจอนี้ก็จะมีลักษณะคล้ายวงปิด ผลก็คือเราจะสังเกตเห็นบางสิ่งที่คล้ายกับอุโมงค์
สันนิษฐานว่าผู้อ่านมีความคุ้นเคยกับการเรียกซ้ำในทางทฤษฎีและรู้ว่ามันคืออะไร ในบทความนี้ เราจะให้ความสำคัญกับปัญหาการเรียกซ้ำมากขึ้น งาน
เมื่อเรียนรู้การเรียกซ้ำ วิธีที่มีประสิทธิภาพที่สุดในการทำความเข้าใจการเรียกซ้ำคือการแก้ปัญหา วิธีแก้ปัญหาการเรียกซ้ำ?
ก่อนอื่น คุณต้องเข้าใจว่าการเรียกซ้ำนั้นเป็นการกระทำที่มากเกินไป โดยทั่วไปแล้ว ทุกสิ่งที่ถูกแก้ไขแบบวนซ้ำสามารถแก้ไขได้แบบวนซ้ำ นั่นคือ การใช้ฟังก์ชันแบบวนซ้ำ
เช่นเดียวกับการแจงนับ (วงจร) การเรียกซ้ำต้องมีเงื่อนไขการหยุด - กรณีพื้นฐาน (ไม่เช่นนั้น เช่นเดียวกับวงจร การเรียกซ้ำจะทำงานตลอดไป - อนันต์) เงื่อนไขนี้เป็นกรณีที่การเรียกซ้ำดำเนินไป (ขั้นตอนการเรียกซ้ำ) ในแต่ละขั้นตอน ฟังก์ชันแบบเรียกซ้ำจะถูกเรียกจนกว่าการเรียกครั้งถัดไปจะทริกเกอร์เงื่อนไขพื้นฐานและการเรียกซ้ำจะหยุด (หรือค่อนข้างจะกลับไปสู่การเรียกฟังก์ชันครั้งล่าสุด) วิธีแก้ปัญหาทั้งหมดอยู่ที่การแก้ไขกรณีพื้นฐาน ในกรณีที่มีการเรียกใช้ฟังก์ชันแบบเรียกซ้ำเพื่อแก้ไขปัญหาที่ซับซ้อน (ไม่ใช่กรณีพื้นฐาน) จะมีการดำเนินการเรียกหรือขั้นตอนแบบเรียกซ้ำจำนวนหนึ่งเพื่อลดปัญหาให้เหลือปัญหาที่ง่ายขึ้น และต่อๆ ไปจนกว่าเราจะได้วิธีแก้ปัญหาเบื้องต้น
ลองดูตัวอย่างการหาแฟกทอเรียลกัน:
ถ้า (n==1) ส่งคืน 1; //ถ้าค่าใหม่เป็น 1 เราจะบวกมันด้วย 1 ไม่ใช่ค่าก่อนหน้า เพราะ อันก่อนหน้าคือศูนย์ และการบวก 1+0 จะไม่มีที่สิ้นสุด
มิฉะนั้นจะส่งคืนผลรวม (n-1)+n; //แต่ถ้า n>1 ให้บวกด้วยค่าก่อนหน้าเท่ากับผลรวมขององค์ประกอบทั้งหมดจนถึง n
}
ฉันทำงานกับ Dev C++ ตัวอย่างนี้แสดงจำนวน ==15 หากคุณนับตามที่เขียนไว้ในตัวอย่าง จำนวนเงินจะแตกต่างออกไป
ฉันเขียนไว้ข้างต้น เอาล่ะ (5-1)+5=4+5=9
1+2+3+4+5 = 15 ตัวอย่างผลลัพธ์ถูกต้อง
(5-1+(5)) //...
(4-1+(5-1+(5)))
(3-1+(4-1+(5-1+(5))))
(2-1+(3-1+(4-1+(5-1+(5)))))
(2-1+(3-1+(4-1+(5-1+(5))))) == 15
นี่คือผลลัพธ์
ผลลัพธ์ของฟังก์ชันนี้คือผลต่างของตัวเลขสองตัวแรก และ n คือส่วนที่เหลือทางด้านขวา
__________________________________
คุณเพียงแค่ต้องเข้าใจฟังก์ชันอย่างถูกต้องและยอมรับว่าเป็นค่าจากการคำนวณ แต่ไม่เข้าใจว่าเป็นตัวแปร มันคล้ายกับตัวแปร แต่ใกล้กับค่าคงที่ที่คำนวณได้มากกว่า แม้ว่าจะไม่ใช่ค่าคงที่ แต่ก็สะดวกกว่าที่จะรับรู้ด้วยวิธีนี้
ด้วยเหตุนี้ทุกอย่างชัดเจนเพียงแค่ส่งคืน 2 ก็บวกการกีดกันเข้ากับผลรวม
ไม่ใช่ดาวพิเศษ แต่เป็นสองดวงนี้ และถ้าคุณเขียน -3 แล้วเมื่อบวกหนึ่งครั้งก็จะลบสามดวง เป็นต้น
ตรรกะทั้งหมดก็คือฟังก์ชันแบบเรียกซ้ำจำเป็นต้องมีจุดส่งคืน
การเชื่อมต่อกับบรรทัดที่เก้าคือตัวเลขจะถูกส่งผ่านไปยังฟังก์ชันผลรวมเมื่อเรียกจากภายในหลัก ในระหว่างการเรียกซ้ำ หมายเลขนี้จะลดลงหนึ่ง (n-1) ในแต่ละครั้ง ผลลัพธ์นี้ n-1 จะถูกตรวจสอบความเท่าเทียมกันด้วย หนึ่ง และหากความเท่าเทียมกันเป็นจริง จำนวนเงินที่ได้รับทั้งหมดจะถูกรวมเข้ากับตัวเลขในการส่งคืนนั้น มิฉะนั้นผลรวมทั้งหมดจะถูกรวมเข้ากับ n-1 ใหม่นี้