ขั้นตอนการเรียกซ้ำค. อัลกอริธึมการเรียกซ้ำและการเรียกซ้ำ

เพื่อไม่ให้เขียนบทความใหญ่ๆ สักบทความ ซึ่งจะมีตัวอย่างมากมายของการเรียกซ้ำในภาษา 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");
ศาล<//จุดเรียกของฟังก์ชันแบบเรียกซ้ำ กำลังแสดงแฟคทอเรียล 10 บนหน้าจอ
รับ();
กลับ 0 ;
}
ddd
============

ส่วนหลักในโปรแกรมเรียกซ้ำ C++
กลับไม่มี * ข้อเท็จจริง(n–1)

ฟังก์ชันของเราจะคำนวณใหม่เพื่อให้ได้ค่าก่อนหน้า ค่าจริงคือพารามิเตอร์ที่ส่งไป nจากจุดที่เรียกใช้ฟังก์ชัน จุดประสงค์ของการเรียกใช้ฟังก์ชันของเราคือการเรียกใช้จากบล็อกหลักของโปรแกรม ในกรณีของเรา เราเรียกมันจากฟังก์ชัน int หลัก()
ทำไมฉันถึงเขียนไม่ใช่อันถัดไป แต่อันก่อนหน้า? เมื่อคูณตัวเลขแล้ว 0 * 1 แรกนี่คือค่าปัจจุบันของเรา 1 และศูนย์คือค่าการคำนวณก่อนหน้า นี่คือสาระสำคัญทั้งหมดของการเรียกซ้ำ เราคำนวณมูลค่าปัจจุบันโดยใช้ค่าก่อนหน้า ในขณะที่ค่าก่อนหน้าจะได้มาจากการคำนวณเดียวกัน คอมไพเลอร์จะคำนวณค่าก่อนหน้าและเก็บค่านี้ไว้ในหน่วยความจำ สิ่งที่เราต้องทำคือให้คำแนะนำ - ด้วยคุณสมบัติของคอมไพเลอร์นี้ ฟังก์ชันที่พบกับคำสั่งให้เรียกตัวเอง (ในกรณีของเรา ข้อเท็จจริง(n–1) ) จะไม่เขียนทับพารามิเตอร์ที่ส่งไปให้ nเพื่อคำนวณฟังก์ชัน พารามิเตอร์ที่ส่งผ่านไปยัง nมันยังคงอยู่ในความทรงจำ ในกรณีนี้ จะมีการกำหนดพื้นที่หน่วยความจำอื่นเพิ่มเติม โดยที่ฟังก์ชันแบบเรียกซ้ำของเราจะทำการคำนวณแบบเรียกซ้ำเพื่อให้ได้ผลลัพธ์ก่อนหน้า

ขอให้โปรแกรมเมอร์ยกโทษให้ฉันสำหรับการตัดสินที่เคี้ยวเอื้องเช่นนี้ นี่เป็นวิธีที่ผู้เริ่มต้นรับรู้ถึงการเรียกซ้ำโดยประมาณ

ฉันหวังว่าบล็อก C++ สำหรับผู้เริ่มต้นจะมีประโยชน์กับบางคนและช่วยให้ใครบางคนเข้าใจแนวคิดพื้นฐานของฟังก์ชันแบบเรียกซ้ำใน C++

บันทึก. ในบทความนี้ เช่นเดียวกับในบทความก่อนหน้านี้ ฉันไม่ได้คำนวณจาก 1 ถึง N แต่เป็นค่าที่ป้อนภายในโปรแกรม ประเด็นก็คือฉันไม่ต้องการเขียนโค้ดเพิ่มอีกบรรทัดและสันนิษฐานว่าผู้ใช้มีความชำนาญในการป้อนข้อมูลและแสดงข้อมูลบนหน้าจออยู่แล้ว

การเรียกซ้ำเป็นปรากฏการณ์ทั่วไปที่เกิดขึ้นไม่เพียงแต่ในสาขาวิทยาศาสตร์เท่านั้น แต่ยังเกิดขึ้นในชีวิตประจำวันด้วย ตัวอย่างเช่น เอฟเฟ็กต์ Droste, สามเหลี่ยม Sierpinski ฯลฯ วิธีที่ง่ายที่สุดในการดูการเรียกซ้ำคือการชี้กล้องเว็บไปที่หน้าจอคอมพิวเตอร์ตามปกติหลังจากเปิดเครื่อง ดังนั้นกล้องจะบันทึกภาพหน้าจอคอมพิวเตอร์และแสดงบนหน้าจอนี้ก็จะมีลักษณะคล้ายวงปิด ผลก็คือเราจะสังเกตเห็นบางสิ่งที่คล้ายกับอุโมงค์

ในการเขียนโปรแกรม การเรียกซ้ำมีความสัมพันธ์อย่างใกล้ชิดกับฟังก์ชัน ต้องขอบคุณฟังก์ชันในการเขียนโปรแกรมที่มีทั้งฟังก์ชันการเรียกซ้ำหรือฟังก์ชันเรียกซ้ำ พูดง่ายๆ ก็คือ การเรียกซ้ำคือคำจำกัดความของส่วนหนึ่งของฟังก์ชัน (วิธีการ) ผ่านตัวมันเอง นั่นคือ เป็นฟังก์ชันที่เรียกตัวเองโดยตรง (ในร่างกาย) หรือโดยอ้อม (ผ่านฟังก์ชันอื่น) ปัญหาการเรียกซ้ำโดยทั่วไปคือ: การหา n!, ตัวเลขฟีโบนัชชี เราได้แก้ไขปัญหาดังกล่าวแล้ว แต่การใช้ลูปนั่นคือวนซ้ำ โดยทั่วไปแล้ว ทุกสิ่งที่ถูกแก้ไขแบบวนซ้ำสามารถแก้ไขได้แบบวนซ้ำ นั่นคือ การใช้ฟังก์ชันแบบวนซ้ำ วิธีแก้ปัญหาทั้งหมดอยู่ที่การแก้ปัญหาหลักหรือที่เรียกกันว่ากรณีฐาน มีสิ่งเช่นขั้นตอนการเรียกซ้ำหรือการเรียกซ้ำ ในกรณีที่มีการเรียกใช้ฟังก์ชันแบบเรียกซ้ำเพื่อแก้ไขปัญหาที่ซับซ้อน (ไม่ใช่กรณีพื้นฐาน) จะมีการดำเนินการเรียกหรือขั้นตอนแบบเรียกซ้ำจำนวนหนึ่งเพื่อลดปัญหาให้เหลือปัญหาที่ง่ายขึ้น และต่อๆ ไปจนกว่าเราจะได้วิธีแก้ปัญหาเบื้องต้น มาพัฒนาโปรแกรมที่ประกาศฟังก์ชันแบบเรียกซ้ำที่คำนวณ n!

"stdafx.h" #รวม << "Enter n!: "; cin >>น;<< n << "!" << "=" << factorial(n) << endl; // вызов рекурсивной функции system("pause"); return 0; } unsigned long int factorial(unsigned long int f) // рекурсивная функция для нахождения n! { if (f == 1 || f == 0) // базовое или частное решение return 1; // все мы знаем, что 1!=1 и 0!=1 cout << "Step\t" << i << endl; i++; // операция инкремента шага рекурсивных вызовов cout << "Result= " << result << endl; result = f * factorial(f - 1); // функция вызывает саму себя, причём её аргумент уже на 1 меньше return result; }

ศาล

// รหัส รหัส::บล็อก

// รหัส Dev-C++ // factorial.cpp: กำหนดจุดเริ่มต้นสำหรับแอปพลิเคชันคอนโซล #รวม<< "Enter n!: "; cin >>น;<< n << "!" << "=" << factorial(n) << endl; // вызов рекурсивной функции return 0; } unsigned long int factorial(unsigned long int f) // рекурсивная функция для нахождения n! { if (f == 1 || f == 0) // базовое или частное решение return 1; // все мы знаем, что 1!=1 и 0!=1 cout << "Step\t" << i << endl; i++; // операция инкремента шага рекурсивных вызовов cout << "Result= " << result << endl; result = f * factorial(f - 1); // функция вызывает саму себя, причём её аргумент уже на 1 меньше return result; }

ใช้เนมสเปซมาตรฐาน; 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 ซึ่งเราจะเรียกใช้ฟังก์ชันแบบเรียกซ้ำ

// factorial.cpp: กำหนดจุดเริ่มต้นสำหรับแอปพลิเคชันคอนโซล #รวม<< "Enter n!: "; cin >>น;<= n; k++) { cout << k << "!" << "=" << factorial(k) << endl; // вызов рекурсивной функции } system("pause"); return 0; } unsigned long int factorial(unsigned long int f) // рекурсивная функция для нахождения n! { if (f == 1 || f == 0) // базовое или частное решение return 1; // все мы знаем, что 1!=1 и 0!=1 //cout << "Step\t"<< i <>น;<= n; k++) { cout << k << "!" << "=" << factorial(k) << endl; // вызов рекурсивной функции } return 0; } unsigned long int factorial(unsigned long int f) // рекурсивная функция для нахождения n! { if (f == 1 || f == 0) // базовое или частное решение return 1; // все мы знаем, что 1!=1 и 0!=1 //cout << "Step\t"<< i < << "Enter number from the Fibonacci series: "; cin >> <= entered_number; counter++) cout << setw(2) <

ศาล

// รหัส รหัส::บล็อก

// fibonacci.cpp: กำหนดจุดเริ่มต้นสำหรับแอปพลิเคชันคอนโซล #รวม // ไลบรารีสำหรับจัดรูปแบบข้อมูลที่แสดงบนหน้าจอ #include ใช้เนมสเปซมาตรฐาน; ฟีโบนัชชีแบบยาวที่ไม่ได้ลงนาม(แบบยาวที่ไม่ได้ลงนาม); // ต้นแบบของฟังก์ชันแบบเรียกซ้ำสำหรับการค้นหาตัวเลขจากชุดฟีโบนักชี int main(int argc, char* argv) ( enter_number แบบยาวที่ไม่ได้ลงนาม;<< "Enter number from the Fibonacci series: "; cin >> ป้อน_หมายเลข;<= entered_number; counter++) cout << setw(2) <

สมมติว่าคุณต้องย้ายดิสก์สามแผ่นจากก้านแรกไปยังก้านที่สาม ซึ่งหมายความว่าก้านที่สองเป็นส่วนเสริม วิธีแก้ปัญหาด้วยภาพสำหรับปัญหานี้ถูกนำไปใช้ใน Flash คลิกที่ปุ่มเริ่มต้นเพื่อเริ่มภาพเคลื่อนไหว ปุ่มหยุดเพื่อหยุด

ต้องเขียนโปรแกรมสำหรับดิสก์จำนวนที่ n เนื่องจากเราแก้ไขปัญหานี้แบบวนซ้ำ เราจึงต้องค้นหากรณีพิเศษของวิธีแก้ปัญหาก่อน ในปัญหานี้มีกรณีพิเศษเพียงกรณีเดียว - นี่คือเมื่อจำเป็นต้องย้ายดิสก์เพียงแผ่นเดียวและในกรณีนี้ไม่จำเป็นต้องใช้แกนเสริม แต่เราก็ไม่สนใจเรื่องนี้ ตอนนี้จำเป็นต้องจัดระเบียบโซลูชันแบบเรียกซ้ำหากจำนวนดิสก์มีมากกว่าหนึ่งดิสก์ ให้เราแนะนำสัญกรณ์บางอย่างเพื่อไม่ให้เขียนมากเกินไป:

<Б> - แกนซึ่งดิสก์อยู่ในตอนแรก (แกนฐาน)
<П> - แท่งเสริมหรือแท่งกลาง
<Ф> — ก้านสุดท้าย – ก้านที่ต้องเคลื่อนย้ายดิสก์

นอกจากนี้ เมื่ออธิบายอัลกอริทึมในการแก้ปัญหา เราจะใช้สัญลักษณ์เหล่านี้ เพื่อย้ายสามดิสก์จาก <Б> บน <Ф> เราต้องย้ายดิสก์ทั้งสองออกก่อน <Б> บน <П> จากนั้นย้ายดิสก์แผ่นที่สาม (ใหญ่ที่สุด) ไปที่ <Ф> , เพราะ <Ф> ฟรี

เพื่อเคลื่อนย้าย nดิสก์ด้วย <Б> บน <Ф> เราต้องย้ายก่อน n-1ดิสก์ด้วย <Б> บน <П> จากนั้นย้ายดิสก์ที่ n (ใหญ่ที่สุด) ไปที่ <Ф> , เพราะ <Ф> ฟรี หลังจากนี้คุณจะต้องย้าย n-1ดิสก์ด้วย <П> บน <Ф> ขณะใช้ไม้เท้า <Б> เป็นตัวช่วย การกระทำทั้งสามนี้เป็นอัลกอริธึมแบบเรียกซ้ำทั้งหมด อัลกอริทึมเดียวกันในรหัสเทียม:
n-1ย้ายไป <П>
nย้ายไป <Ф>
n-1ย้ายจาก <П> บน <Ф> ขณะใช้งาน <Б> เป็นตัวช่วย

// hanoi_tower.cpp: กำหนดจุดเริ่มต้นสำหรับแอปพลิเคชันคอนโซล // โปรแกรมที่แก้ปัญหาหอคอยฮานอยแบบวนซ้ำ #include "stdafx.h" #include #รวม ใช้เนมสเปซมาตรฐาน; หอคอยโมฆะ (int, int, int, int); // ประกาศต้นแบบของฟังก์ชันแบบเรียกซ้ำ int count = 1; // ตัวแปรโกลบอลสำหรับการนับจำนวนขั้นตอน int _tmain(int argc, _TCHAR* argv) ( cout<< "Enter of numbers of disks: ";// введите количество дисков, которые надо переместить int number; cin >>หมายเลข;<< "Enter the number of basic rod: "; // введите номер стержня, на котором диски будут находится изначально int basic_rod; cin >ศาล<< "Enter the number of final rod: "; // введите номер стержня, на который необходимо переместить диски int final_rod; cin >> basic_rod;<< setw(2) << count << ") "<< baza << " " << "->" << " " << new_baza << endl; count++; } else { tower(count_disk -1, baza, new_baza, help_baza); // перемещаем все диски кроме самого последнего на вспомогательный стержень tower(1, baza, help_baza, new_baza); // перемещаем последний диск с начального стержня на финальный стержень tower(count_disk -1, help_baza, baza, new_baza); // перемещаем все диски со вспомогательного стержня на финальный } }

ศาล

// รหัส รหัส::บล็อก

ศาล #รวม > สุดท้าย_ร็อด;<< "Enter of numbers of disks: ";// введите количество дисков, которые надо переместить int number; cin >>หมายเลข;<< "Enter the number of basic rod: "; // введите номер стержня, на котором диски будут находится изначально int basic_rod; cin >ศาล<< "Enter the number of final rod: "; // введите номер стержня, на который необходимо переместить диски int final_rod; cin >> สุดท้าย_ร็อด;<< setw(2) << count << ") "<< baza << " " << "->" << " " << new_baza << endl; count++; } else { tower(count_disk -1, baza, new_baza, help_baza); // перемещаем все диски кроме самого последнего на вспомогательный стержень tower(1, baza, help_baza, new_baza); // перемещаем последний диск с начального стержня на финальный стержень tower(count_disk -1, help_baza, baza, new_baza); // перемещаем все диски со вспомогательного стержня на финальный } }

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 ++

สั้น ๆ เกี่ยวกับการเรียกซ้ำ

การเรียกซ้ำเป็นปรากฏการณ์ทั่วไปที่เกิดขึ้นไม่เพียงแต่ในสาขาวิทยาศาสตร์เท่านั้น แต่ยังเกิดขึ้นในชีวิตประจำวันด้วย ตัวอย่างเช่น เอฟเฟ็กต์ Droste, สามเหลี่ยม Sierpinski เป็นต้น วิธีหนึ่งในการดูการเรียกซ้ำคือการชี้กล้องเว็บไปที่หน้าจอคอมพิวเตอร์ โดยธรรมชาติแล้วจะต้องเปิดกล้องขึ้นมาก่อน ดังนั้นกล้องจะบันทึกภาพหน้าจอคอมพิวเตอร์และแสดงบนหน้าจอนี้ก็จะมีลักษณะคล้ายวงปิด ผลก็คือเราจะสังเกตเห็นบางสิ่งที่คล้ายกับอุโมงค์

ในการเขียนโปรแกรม การเรียกซ้ำมีความสัมพันธ์อย่างใกล้ชิดกับฟังก์ชัน ต้องขอบคุณฟังก์ชันในการเขียนโปรแกรมที่มีทั้งฟังก์ชันการเรียกซ้ำหรือฟังก์ชันเรียกซ้ำ พูดง่ายๆ ก็คือ การเรียกซ้ำคือคำจำกัดความของส่วนหนึ่งของฟังก์ชัน (วิธีการ) ผ่านตัวมันเอง นั่นคือ เป็นฟังก์ชันที่เรียกตัวเองโดยตรง (ในร่างกาย) หรือโดยอ้อม (ผ่านฟังก์ชันอื่น)

มีการพูดถึงเรื่องการเรียกซ้ำมากมาย นี่คือแหล่งข้อมูลที่ดีบางส่วน:

  • ปัญหาการเรียกซ้ำและการเรียกซ้ำ พื้นที่การประยุกต์ใช้การเรียกซ้ำ
สันนิษฐานว่าผู้อ่านมีความคุ้นเคยกับการเรียกซ้ำในทางทฤษฎีและรู้ว่ามันคืออะไร ในบทความนี้ เราจะให้ความสำคัญกับปัญหาการเรียกซ้ำมากขึ้น

งาน

เมื่อเรียนรู้การเรียกซ้ำ วิธีที่มีประสิทธิภาพที่สุดในการทำความเข้าใจการเรียกซ้ำคือการแก้ปัญหา
วิธีแก้ปัญหาการเรียกซ้ำ?
ก่อนอื่น คุณต้องเข้าใจว่าการเรียกซ้ำนั้นเป็นการกระทำที่มากเกินไป โดยทั่วไปแล้ว ทุกสิ่งที่ถูกแก้ไขแบบวนซ้ำสามารถแก้ไขได้แบบวนซ้ำ นั่นคือ การใช้ฟังก์ชันแบบวนซ้ำ

จากเครือข่าย

อัลกอริธึมใดๆ ที่นำมาใช้ในรูปแบบเรียกซ้ำสามารถเขียนใหม่ได้ในรูปแบบวนซ้ำและในทางกลับกัน คำถามยังคงอยู่ว่าสิ่งนี้จำเป็นหรือไม่และจะมีประสิทธิภาพเพียงใด

สามารถให้ข้อโต้แย้งต่อไปนี้เพื่อพิสูจน์สิ่งนี้

ประการแรก เราสามารถจำคำจำกัดความของการเรียกซ้ำและการวนซ้ำได้ การเรียกซ้ำเป็นวิธีการจัดการการประมวลผลข้อมูลที่โปรแกรมเรียกตัวเองโดยตรงหรือด้วยความช่วยเหลือของโปรแกรมอื่น การวนซ้ำเป็นวิธีการจัดการการประมวลผลข้อมูลซึ่งมีการกระทำบางอย่างซ้ำหลายครั้งโดยไม่ทำให้เกิดการเรียกโปรแกรมแบบเรียกซ้ำ

หลังจากนั้นเราสามารถสรุปได้ว่าพวกมันใช้แทนกันได้ แต่ต้นทุนและความเร็วไม่เท่ากันเสมอไป เพื่อพิสูจน์สิ่งนี้ เราสามารถยกตัวอย่างต่อไปนี้: มีฟังก์ชันที่ในการจัดระเบียบอัลกอริธึมบางอย่าง มีการวนซ้ำที่ดำเนินการตามลำดับของการกระทำ ขึ้นอยู่กับค่าปัจจุบันของตัวนับ (อาจไม่ขึ้นอยู่กับ มัน). เนื่องจากมีวัฏจักร หมายความว่าร่างกายจะทำซ้ำลำดับของการกระทำ นั่นคือการวนซ้ำของวัฏจักร คุณสามารถย้ายการดำเนินการไปยังรูทีนย่อยที่แยกจากกัน และส่งผ่านค่าตัวนับได้ ถ้ามี เมื่อเสร็จสิ้นการดำเนินการของรูทีนย่อย เราจะตรวจสอบเงื่อนไขในการดำเนินการลูป และหากเป็นจริง เราจะดำเนินการเรียกรูทีนย่อยใหม่ หากเป็นเท็จ เราจะดำเนินการให้เสร็จสิ้น เพราะ เราวางเนื้อหาทั้งหมดของลูปไว้ในรูทีนย่อย ซึ่งหมายความว่าเงื่อนไขในการดำเนินการวนซ้ำจะถูกวางไว้ในรูทีนย่อยด้วย และสามารถรับได้ผ่านค่าที่ส่งคืนของฟังก์ชัน พารามิเตอร์ที่ส่งผ่านโดยการอ้างอิงหรือตัวชี้ไปยังรูทีนย่อย ตลอดจนตัวแปรทั่วโลก นอกจากนี้ มันเป็นเรื่องง่ายที่จะแสดงว่าการเรียกไปยังรูทีนย่อยที่กำหนดจากลูปสามารถแปลงเป็นการเรียกได้อย่างง่ายดาย หรือไม่ใช่การเรียก (ส่งคืนค่าหรือเพียงทำงานให้เสร็จสิ้น) ของรูทีนย่อยจากตัวมันเอง โดยอยู่ภายใต้เงื่อนไขบางประการ (เหล่านั้น ที่เคยอยู่ในสภาพวนซ้ำ) ทีนี้ ถ้าคุณดูโปรแกรมนามธรรมของเรา ดูเหมือนว่าการส่งค่าไปยังรูทีนย่อยคร่าวๆ แล้วใช้งาน ซึ่งรูทีนย่อยจะเปลี่ยนเมื่อเสร็จสิ้น เช่น เราแทนที่การวนซ้ำด้วยการเรียกซ้ำไปยังรูทีนย่อยเพื่อแก้ไขอัลกอริทึมที่กำหนด

งานในการนำการเรียกซ้ำมาสู่แนวทางวนซ้ำนั้นมีความสมมาตร

โดยสรุป เราสามารถแสดงความคิดต่อไปนี้: สำหรับแต่ละแนวทางจะมีประเภทของงานของตัวเอง ซึ่งถูกกำหนดโดยข้อกำหนดเฉพาะสำหรับงานเฉพาะ

คุณสามารถหาข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้ได้


เช่นเดียวกับการแจงนับ (วงจร) การเรียกซ้ำต้องมีเงื่อนไขการหยุด - กรณีพื้นฐาน (ไม่เช่นนั้น เช่นเดียวกับวงจร การเรียกซ้ำจะทำงานตลอดไป - อนันต์) เงื่อนไขนี้เป็นกรณีที่การเรียกซ้ำดำเนินไป (ขั้นตอนการเรียกซ้ำ) ในแต่ละขั้นตอน ฟังก์ชันแบบเรียกซ้ำจะถูกเรียกจนกว่าการเรียกครั้งถัดไปจะทริกเกอร์เงื่อนไขพื้นฐานและการเรียกซ้ำจะหยุด (หรือค่อนข้างจะกลับไปสู่การเรียกฟังก์ชันครั้งล่าสุด) วิธีแก้ปัญหาทั้งหมดอยู่ที่การแก้ไขกรณีพื้นฐาน ในกรณีที่มีการเรียกใช้ฟังก์ชันแบบเรียกซ้ำเพื่อแก้ไขปัญหาที่ซับซ้อน (ไม่ใช่กรณีพื้นฐาน) จะมีการดำเนินการเรียกหรือขั้นตอนแบบเรียกซ้ำจำนวนหนึ่งเพื่อลดปัญหาให้เหลือปัญหาที่ง่ายขึ้น และต่อๆ ไปจนกว่าเราจะได้วิธีแก้ปัญหาเบื้องต้น

ดังนั้นฟังก์ชันแบบเรียกซ้ำจึงประกอบด้วย

  • การหยุดสภาพหรือกรณีฐาน
  • เงื่อนไขการต่อเนื่องหรือขั้นตอนการเรียกซ้ำเป็นวิธีหนึ่งในการลดปัญหาให้เกิดปัญหาที่ง่ายขึ้น
ลองดูตัวอย่างการหาแฟกทอเรียลกัน:

โซลูชันคลาสสาธารณะ ( การเรียกซ้ำ 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 ++

สั้น ๆ เกี่ยวกับการเรียกซ้ำ

การเรียกซ้ำเป็นปรากฏการณ์ทั่วไปที่เกิดขึ้นไม่เพียงแต่ในสาขาวิทยาศาสตร์เท่านั้น แต่ยังเกิดขึ้นในชีวิตประจำวันด้วย ตัวอย่างเช่น เอฟเฟ็กต์ Droste, สามเหลี่ยม Sierpinski เป็นต้น วิธีหนึ่งในการดูการเรียกซ้ำคือการชี้กล้องเว็บไปที่หน้าจอคอมพิวเตอร์ โดยธรรมชาติแล้วจะต้องเปิดกล้องขึ้นมาก่อน ดังนั้นกล้องจะบันทึกภาพหน้าจอคอมพิวเตอร์และแสดงบนหน้าจอนี้ก็จะมีลักษณะคล้ายวงปิด ผลก็คือเราจะสังเกตเห็นบางสิ่งที่คล้ายกับอุโมงค์

ในการเขียนโปรแกรม การเรียกซ้ำมีความสัมพันธ์อย่างใกล้ชิดกับฟังก์ชัน ต้องขอบคุณฟังก์ชันในการเขียนโปรแกรมที่มีทั้งฟังก์ชันการเรียกซ้ำหรือฟังก์ชันเรียกซ้ำ พูดง่ายๆ ก็คือ การเรียกซ้ำคือคำจำกัดความของส่วนหนึ่งของฟังก์ชัน (วิธีการ) ผ่านตัวมันเอง นั่นคือ เป็นฟังก์ชันที่เรียกตัวเองโดยตรง (ในร่างกาย) หรือโดยอ้อม (ผ่านฟังก์ชันอื่น)

มีการพูดถึงเรื่องการเรียกซ้ำมากมาย นี่คือแหล่งข้อมูลที่ดีบางส่วน:

  • ปัญหาการเรียกซ้ำและการเรียกซ้ำ พื้นที่การประยุกต์ใช้การเรียกซ้ำ
สันนิษฐานว่าผู้อ่านมีความคุ้นเคยกับการเรียกซ้ำในทางทฤษฎีและรู้ว่ามันคืออะไร ในบทความนี้ เราจะให้ความสำคัญกับปัญหาการเรียกซ้ำมากขึ้น

งาน

เมื่อเรียนรู้การเรียกซ้ำ วิธีที่มีประสิทธิภาพที่สุดในการทำความเข้าใจการเรียกซ้ำคือการแก้ปัญหา
วิธีแก้ปัญหาการเรียกซ้ำ?
ก่อนอื่น คุณต้องเข้าใจว่าการเรียกซ้ำนั้นเป็นการกระทำที่มากเกินไป โดยทั่วไปแล้ว ทุกสิ่งที่ถูกแก้ไขแบบวนซ้ำสามารถแก้ไขได้แบบวนซ้ำ นั่นคือ การใช้ฟังก์ชันแบบวนซ้ำ

จากเครือข่าย

อัลกอริธึมใดๆ ที่นำมาใช้ในรูปแบบเรียกซ้ำสามารถเขียนใหม่ได้ในรูปแบบวนซ้ำและในทางกลับกัน คำถามยังคงอยู่ว่าสิ่งนี้จำเป็นหรือไม่และจะมีประสิทธิภาพเพียงใด

สามารถให้ข้อโต้แย้งต่อไปนี้เพื่อพิสูจน์สิ่งนี้

ประการแรก เราสามารถจำคำจำกัดความของการเรียกซ้ำและการวนซ้ำได้ การเรียกซ้ำเป็นวิธีการจัดการการประมวลผลข้อมูลที่โปรแกรมเรียกตัวเองโดยตรงหรือด้วยความช่วยเหลือของโปรแกรมอื่น การวนซ้ำเป็นวิธีการจัดการการประมวลผลข้อมูลซึ่งมีการกระทำบางอย่างซ้ำหลายครั้งโดยไม่ทำให้เกิดการเรียกโปรแกรมแบบเรียกซ้ำ

หลังจากนั้นเราสามารถสรุปได้ว่าพวกมันใช้แทนกันได้ แต่ต้นทุนและความเร็วไม่เท่ากันเสมอไป เพื่อพิสูจน์สิ่งนี้ เราสามารถยกตัวอย่างต่อไปนี้: มีฟังก์ชันที่ในการจัดระเบียบอัลกอริธึมบางอย่าง มีการวนซ้ำที่ดำเนินการตามลำดับของการกระทำ ขึ้นอยู่กับค่าปัจจุบันของตัวนับ (อาจไม่ขึ้นอยู่กับ มัน). เนื่องจากมีวัฏจักร หมายความว่าร่างกายจะทำซ้ำลำดับของการกระทำ นั่นคือการวนซ้ำของวัฏจักร คุณสามารถย้ายการดำเนินการไปยังรูทีนย่อยที่แยกจากกัน และส่งผ่านค่าตัวนับได้ ถ้ามี เมื่อเสร็จสิ้นการดำเนินการของรูทีนย่อย เราจะตรวจสอบเงื่อนไขในการดำเนินการลูป และหากเป็นจริง เราจะดำเนินการเรียกรูทีนย่อยใหม่ หากเป็นเท็จ เราจะดำเนินการให้เสร็จสิ้น เพราะ เราวางเนื้อหาทั้งหมดของลูปไว้ในรูทีนย่อย ซึ่งหมายความว่าเงื่อนไขในการดำเนินการวนซ้ำจะถูกวางไว้ในรูทีนย่อยด้วย และสามารถรับได้ผ่านค่าที่ส่งคืนของฟังก์ชัน พารามิเตอร์ที่ส่งผ่านโดยการอ้างอิงหรือตัวชี้ไปยังรูทีนย่อย ตลอดจนตัวแปรทั่วโลก นอกจากนี้ มันเป็นเรื่องง่ายที่จะแสดงว่าการเรียกไปยังรูทีนย่อยที่กำหนดจากลูปสามารถแปลงเป็นการเรียกได้อย่างง่ายดาย หรือไม่ใช่การเรียก (ส่งคืนค่าหรือเพียงทำงานให้เสร็จสิ้น) ของรูทีนย่อยจากตัวมันเอง โดยอยู่ภายใต้เงื่อนไขบางประการ (เหล่านั้น ที่เคยอยู่ในสภาพวนซ้ำ) ทีนี้ ถ้าคุณดูโปรแกรมนามธรรมของเรา ดูเหมือนว่าการส่งค่าไปยังรูทีนย่อยคร่าวๆ แล้วใช้งาน ซึ่งรูทีนย่อยจะเปลี่ยนเมื่อเสร็จสิ้น เช่น เราแทนที่การวนซ้ำด้วยการเรียกซ้ำไปยังรูทีนย่อยเพื่อแก้ไขอัลกอริทึมที่กำหนด

งานในการนำการเรียกซ้ำมาสู่แนวทางวนซ้ำนั้นมีความสมมาตร

โดยสรุป เราสามารถแสดงความคิดต่อไปนี้: สำหรับแต่ละแนวทางจะมีประเภทของงานของตัวเอง ซึ่งถูกกำหนดโดยข้อกำหนดเฉพาะสำหรับงานเฉพาะ

คุณสามารถหาข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้ได้


เช่นเดียวกับการแจงนับ (วงจร) การเรียกซ้ำต้องมีเงื่อนไขการหยุด - กรณีพื้นฐาน (ไม่เช่นนั้น เช่นเดียวกับวงจร การเรียกซ้ำจะทำงานตลอดไป - อนันต์) เงื่อนไขนี้เป็นกรณีที่การเรียกซ้ำดำเนินไป (ขั้นตอนการเรียกซ้ำ) ในแต่ละขั้นตอน ฟังก์ชันแบบเรียกซ้ำจะถูกเรียกจนกว่าการเรียกครั้งถัดไปจะทริกเกอร์เงื่อนไขพื้นฐานและการเรียกซ้ำจะหยุด (หรือค่อนข้างจะกลับไปสู่การเรียกฟังก์ชันครั้งล่าสุด) วิธีแก้ปัญหาทั้งหมดอยู่ที่การแก้ไขกรณีพื้นฐาน ในกรณีที่มีการเรียกใช้ฟังก์ชันแบบเรียกซ้ำเพื่อแก้ไขปัญหาที่ซับซ้อน (ไม่ใช่กรณีพื้นฐาน) จะมีการดำเนินการเรียกหรือขั้นตอนแบบเรียกซ้ำจำนวนหนึ่งเพื่อลดปัญหาให้เหลือปัญหาที่ง่ายขึ้น และต่อๆ ไปจนกว่าเราจะได้วิธีแก้ปัญหาเบื้องต้น

ดังนั้นฟังก์ชันแบบเรียกซ้ำจึงประกอบด้วย

  • การหยุดสภาพหรือกรณีฐาน
  • เงื่อนไขการต่อเนื่องหรือขั้นตอนการเรียกซ้ำเป็นวิธีหนึ่งในการลดปัญหาให้เกิดปัญหาที่ง่ายขึ้น
ลองดูตัวอย่างการหาแฟกทอเรียลกัน:

โซลูชันคลาสสาธารณะ ( การเรียกซ้ำ 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==1) ส่งคืน 1; //ถ้าค่าใหม่เป็น 1 เราจะบวกมันด้วย 1 ไม่ใช่ค่าก่อนหน้า เพราะ อันก่อนหน้าคือศูนย์ และการบวก 1+0 จะไม่มีที่สิ้นสุด
มิฉะนั้นจะส่งคืนผลรวม (n-1)+n; //แต่ถ้า n>1 ให้บวกด้วยค่าก่อนหน้าเท่ากับผลรวมขององค์ประกอบทั้งหมดจนถึง n
}

ตามความเข้าใจของฉัน ใน n มี 5 เงื่อนไขไม่ตรงกัน จากนั้นโค้ดนี้จะถูกดำเนินการ ผลรวม(n-1)+n นั่นคือบางสิ่งที่ได้รับในวงเล็บปีกกาด้วยการลบจะถูกบวกเข้ากับ 5 แต่อะไรคือ (5 - 1) + 5 และถ้าเป็นเช่นนั้น อะไรจะหยุดการดำเนินการทางคณิตศาสตร์นี้:?: :?: :?: ค่าก่อนหน้าคืออะไร มาจากไหน เท่ากับอะไร:?: :?: :?:

ใช่เกือบทุกอย่างเป็นไปตามที่ฉันเข้าใจ (ในย่อหน้าสุดท้ายคุณแสดงการเรียกซ้ำ))) แต่คำถามยังคงอยู่: ผลรวมที่ได้จะปรากฏบนหน้าจอได้อย่างไร?
ฉันทำงานกับ Dev C++ ตัวอย่างนี้แสดงจำนวน ==15 หากคุณนับตามที่เขียนไว้ในตัวอย่าง จำนวนเงินจะแตกต่างออกไป
ฉันเขียนไว้ข้างต้น เอาล่ะ (5-1)+5=4+5=9

:
1+2+3+4+5 = 15 ตัวอย่างผลลัพธ์ถูกต้อง

(5) //เราให้ 5 ให้กับฟังก์ชัน ตรวจสอบความเท่าเทียมกันกับ 1 ไม่เท่ากันก็เรียกฟังก์ชันอีกแล้วส่ง 5-1 เข้าไป
(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 == 1 เรียกใช้ฟังก์ชันเสร็จแล้ว
(2-1+(3-1+(4-1+(5-1+(5))))) == 15
นี่คือผลลัพธ์
ผลลัพธ์ของฟังก์ชันนี้คือผลต่างของตัวเลขสองตัวแรก และ n คือส่วนที่เหลือทางด้านขวา
__________________________________
คุณเพียงแค่ต้องเข้าใจฟังก์ชันอย่างถูกต้องและยอมรับว่าเป็นค่าจากการคำนวณ แต่ไม่เข้าใจว่าเป็นตัวแปร มันคล้ายกับตัวแปร แต่ใกล้กับค่าคงที่ที่คำนวณได้มากกว่า แม้ว่าจะไม่ใช่ค่าคงที่ แต่ก็สะดวกกว่าที่จะรับรู้ด้วยวิธีนี้

ใช่ ใช่ ใช่ ฉันไม่มีเวลาเขียนที่ฉันเข้าใจ ทุกอย่างถูกต้อง มีบางอย่างไม่ผ่านทันที ขอบคุณเว็บไซต์ที่ดี))

และไม่มีเหตุผลเลยว่าจะเกิดอะไรขึ้นในบรรทัด 8 หากคุณเปลี่ยนหมายเลขที่ส่งคืนจากส่งคืน 1 เป็น 2 จำนวนจะเปลี่ยนเป็น 16 เงื่อนไขนี้เกี่ยวข้องกับบรรทัดที่ 9 อย่างไร
ด้วยเหตุนี้ทุกอย่างชัดเจนเพียงแค่ส่งคืน 2 ก็บวกการกีดกันเข้ากับผลรวม

:
ไม่ใช่ดาวพิเศษ แต่เป็นสองดวงนี้ และถ้าคุณเขียน -3 แล้วเมื่อบวกหนึ่งครั้งก็จะลบสามดวง เป็นต้น
ตรรกะทั้งหมดก็คือฟังก์ชันแบบเรียกซ้ำจำเป็นต้องมีจุดส่งคืน
การเชื่อมต่อกับบรรทัดที่เก้าคือตัวเลขจะถูกส่งผ่านไปยังฟังก์ชันผลรวมเมื่อเรียกจากภายในหลัก ในระหว่างการเรียกซ้ำ หมายเลขนี้จะลดลงหนึ่ง (n-1) ในแต่ละครั้ง ผลลัพธ์นี้ n-1 จะถูกตรวจสอบความเท่าเทียมกันด้วย หนึ่ง และหากความเท่าเทียมกันเป็นจริง จำนวนเงินที่ได้รับทั้งหมดจะถูกรวมเข้ากับตัวเลขในการส่งคืนนั้น มิฉะนั้นผลรวมทั้งหมดจะถูกรวมเข้ากับ n-1 ใหม่นี้