ฟังก์ชั่นวนซ้ำทั้งหมดสามารถใช้รหัสซ้ำได้หรือไม่ [ปิด]


10

ข้อดีของการเรียกซ้ำคืออะไร

ภาษาการเขียนโปรแกรมบางอย่างสามารถปรับการเรียกซ้ำหางให้เหมาะสม แต่ในแง่ทั่วไปการเรียกซ้ำใช้ทรัพยากรมากกว่าลูปปกติ

เป็นไปได้ไหมที่จะมีฟังก์ชั่นวนซ้ำซ้ำ ๆ ?



คำตอบ:


10

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

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

ฉันขอแนะนำให้คุณศึกษาหนังสือคอมไพเลอร์เพื่อดูว่าจะนำไปใช้ในรหัสเครื่องได้อย่างไร


ฉันเข้าใจแล้ว ดังนั้นการเรียกซ้ำมีประโยชน์อย่างไร ความเรียบง่าย?
OscarRyz

2
@OscarRyz: ใช่และมันก็ดูดีกว่า
Michael K

@OscarRyz วิธีที่ฉันอธิบายคือเรียกซ้ำ มันไม่ได้ทำโดยใช้คำสั่ง CPU ดั้งเดิม การทำมันด้วยตนเองช่วยให้คุณทำสิ่งต่าง ๆ เช่นการขนานซึ่งแมปคำสั่งดั้งเดิมไม่ถูกต้อง

15

การเรียกซ้ำเป็นวิธีที่เป็นธรรมชาติมากกว่าในการมองสิ่งต่าง ๆ มากกว่าการทำซ้ำ ตัวอย่างเช่นพิจารณาการข้ามผ่านของต้นไม้ไบนารี: inorder(left); process(); inorder(right);ง่ายกว่าการดูแลสแต็กอย่างชัดเจน

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

อัลกอริทึมแบบเรียกซ้ำใด ๆ สามารถแสดงเป็นอัลกอริทึมแบบวนซ้ำได้ แต่คุณอาจต้องเก็บสแต็คอย่างชัดเจน (ตรงกับสแต็กการโทรที่จัดการโดยปริยาย) ท้ายที่สุดถ้าคุณรวบรวมฟังก์ชั่นวนซ้ำคุณจะได้รับบางสิ่งบางอย่างที่อาศัยการจัดการกองซ้อนและวนรอบฟังก์ชันและนั่นเป็นการวนซ้ำ

ฟังก์ชั่น tail-recursive สามารถแปลเป็นลูปได้ง่ายและไม่ต้องการสแต็ก แต่เป็นกรณีพิเศษ


8
ฉันจะบอกว่าถูกต้องดีกว่าเร็วกว่าเสมอ รหัสที่ทำสิ่งผิดอย่างรวดเร็วนั้นไม่ดีสำหรับทุกคน
Mason Wheeler

1
แต่ถ้าคุณสามารถทำสิ่งผิดอย่างรวดเร็วจริง ๆ !
RationalGeek

1
@jkohlhepp - ฉันสามารถแก้ปัญหาได้ทันที คำตอบคือ 0
หมายเหตุตนเอง - คิดชื่อ

2
การใช้การเรียกซ้ำมากกว่าการกองซ้อนอย่างชัดเจนอาจมีประสิทธิภาพมากกว่า - หลีกเลี่ยงความจำเป็นในการจัดสรรฮีปการกระจายตัวของหน่วยความจำที่เป็นไปได้และปัญหาท้องถิ่นที่เป็นไปได้ อย่างไรก็ตามที่ "ปกติดีกว่าเร็ว" ในกรณีที่ซอฟต์แวร์ของคุณต้องจัดการหมายความว่ารหัสของคุณเสีย โดยปกติแล้วกรณีปัญหาค่อนข้างง่ายที่จะมองเห็น - การเรียกซ้ำบนต้นไม้ที่สมดุล (อย่างสมเหตุสมผล) นั้นดี แต่การเรียกซ้ำบนต้นไม้ที่อาจไม่สมดุลมากหรือในรายการที่เชื่อมโยงอาจเป็นจุดบกพร่องที่ร้ายแรงในภาษาเช่น C. Worse มันอาจอยู่รอดได้จากการทดสอบอย่างง่ายและมีปัญหาเมื่อใช้งานจริงเท่านั้น
Steve314

1
ฉันคิดว่าคุณทุกคนเข้าใจในสิ่งที่เมสันหมายถึงและกำลังทำเรื่องตลกเพื่อความสนุกของมัน แน่นอนโปรแกรมที่ถูกต้องช้ามีประโยชน์มากกว่าโปรแกรมที่ไม่ถูกต้องเร็ว
Giorgio

4

ข้อดีของการเรียกซ้ำคืออะไร

ลองแก้ปัญหาหอคอยแห่งฮานอยซ้ำ ๆ เมื่อคุณยอมแพ้ให้ดูที่วิธีแก้ปัญหาซ้ำแล้วเปรียบเทียบกับโซลูชันแบบเรียกซ้ำ อันไหนง่ายกว่ากัน?

เป็นไปได้ไหมที่จะมีฟังก์ชั่นวนซ้ำซ้ำ ๆ ?

ใช่ในหลักการ อย่างไรก็ตามสำหรับปัญหามากมายรวมถึงงานทั่วไปเช่นการสำรวจเส้นทางต้นไม้การแก้ปัญหาแบบเรียกซ้ำนั้นง่ายกว่าและสวยงามกว่าแบบวนซ้ำ


3

ข้อดีของการเรียกซ้ำคืออะไร

ความง่าย แน่นอนว่าการใช้ tail-call optimization นั้นจะใช้ทรัพยากรมากขึ้น (stack) แต่คุณจะใช้งานอย่างไรdeltreeใน Java โดยไม่มีการเรียกซ้ำ การบิดคือการที่delete()สามารถลบไดเร็กตอรี่ต่อเมื่อมันว่างเปล่า; ที่นี่ด้วยการสอบถามซ้ำ:

deltree(File fileOrDirectory) {
    if (fileOrDirectory.isDirectory()) {
        for (File subFileOrDirectory : fileOrDirectory.listFiles()) {
            deltree(subFileOrDirectory);
        }
    }
    fileOrDirectory.delete();
}

1
ด้วยสแต็คดังกล่าวโดยคำตอบอื่น ๆ
นิโคล

ใช่ แต่มันง่ายแค่ไหน -)
Joonas Pulakka

โอ้การเรียกซ้ำดีกว่าแน่นอน ฉันคิดว่าคุณกำลังพูดว่ามันเป็นไปไม่ได้
นิโคล

0

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

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

มีสิ่งเหล่านั้นในใจเรียนรู้การเรียกซ้ำ มันตลกซับซ้อนและมันจะทำให้สมองคุณแตก แต่คุณจะพบว่าตัวเองรักมัน

ขอให้โชคดี!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.