RECURSIVE FUNCTION ติดจรวด
บทความนี้จะเป็นบทความพิเศษ จะรวดเร็วอย่างที่ไม่เคยมีมาก่อน กระพริบตาครั้งเดียวก็จบแล้ว ถ่างตาอ่านให้ดี ๆ เพราะเราไม่มีเวลาอธิบายแล้ว!
ให้เจอหน้าก็พอรู้จัก
Recursive function (ฟังก์ชันเรียกตัวเอง ) หน้าตาเป็นยังไง? อยากให้เรานึกภาพตุ๊กตาอีสาว (Matryoshka) ดู
Recursive Function มีหน้าตาจำได้ง่าย ๆ แค่เห็นก็รู้ว่าใช่ คือ ในตัวฟังก์ชันจะมีชื่อฟังก์ชันของตัวเองทำงานอยู่
แล้วมีเจ้าตัวแบบนี้ทำไม?
Recursive function เป็นเจ้าตัวที่จิ๋วแต่แจ๋วมาก ๆ สามารถแก้ปัญหาบางปัญหาได้อย่างมีประสิทธิภาพทีเดียว แต่ยังไงไปดู เราไม่มีเวลาอธิบายแล้ว!
เหตุการณ์สมมติ
สมมติว่าเราต้องการจะทำฟังก์ชันการคำนวณค่า Factorial เราก็จะเขียนออกมาประมาณนี้
factorial of 5 is 120
จาก code ด้านบนจะเห็นว่าฟังก์ชัน factorial จะรับค่า n มาแล้ววนลูปและคูณไปเรื่อยจาก n จนถึง 1 ไปเรื่อย ๆ อธิบายเป็นภาพง่ายๆจากด้านล่าง
แต่ฟังก์ชัน factorial นี้ยังไม่ใช่ Recursive function เลย แน่ล่ะ ยังไม่มีชื่อซ้ำเหมือนนายอ๊อดซะด้วยซ้ำ ดังนั้นเราจะทำให้ฟังก์ชันคำนวณ factorial ออกมาเป็น Recursive function ซะ ไปต่อกันเราต้องไวกว่านี้!
Recursive function Starter kit
การจะเขียน Recursive function ไม่ใช่ว่าเขียนแค่ชื่อซ้ำลงไปแล้วจะสามารถทำงานได้เลย เราจำเป็นต้องเข้าใจหลักการเพื่อสามารถเขียนให้ทำงานได้ตามที่ต้องการ และเพื่อให้เราเข้าใจเร็วกว่าหมา(วิ่ง) ผมจึงเตรียม Starter kit ไว้ให้ครับ
อย่าพึ่งทำหน้าเหมือนเป็นนิ่วในไตเหมือนข้างบนนะครับ เดี๋ยวเราจะมาวางโครงสร้างไปด้วยกัน
ต่อจิ๊กซอว์ความคิดลงในกล่อง
อย่างแรกที่เราต้องทำก็คือการทำเงื่อนไขของ Starter kit ของเราให้สมบูรณ์เสียก่อน ซึ่งเรามีเงื่อนไขของเรา 3 อย่าง
- Name(ชื่อ) : เราต้องเข้าใจว่าเราต้องการทำฟังก์ชันไปเพื่ออะไร
- Ending(จุดจบ) : เราต้องกำหนดจุดจบของมันว่ามันจะไปจบที่ไหน
- Next(จุดต่อไป) : ซึ่งต่อจากข้อ 2 เราต้องทำยังไงให้มันจบให้ได้
จากฟังก์ชันคำนวณ factorial จะสามารถใส่เงื่อนไขได้ดังนี้
เริ่มจากชื่อ เราก็ตั้งชื่อมันซะว่า factorial
จาก จุดจบ เราจะเห็นว่า factorial ไม่ว่าจะเป็นค่าจำนวนเต็มบวกใดๆก็จะคูณไปจนถึง 1เสมอ ดังนั้นจุดจบที่เหมาะสมกับฟังก์ชันนี้คือ 1
จุดต่อไป เราจะให้มันจบที่ 1 ดังนั้นเราจึงต้องให้มันทำฟังก์ชันนี้ตั้งแต่ n ถึง 1
นำ Starter kit ไปแปลงเป็น code
เมื่อได้เงื่อนไขครบทั้ง 3 แล้วก็นำเงื่อนไขที่ได้ไปต่อเป็น code ได้ดังข้างล่าง
การกำหนดจุดจบจะขึ้นอยู่กับ ฟังก์ชันที่เราต้องการจะทำ อาจเป็นค่าคงที่อะไรก็ได้ ซึ่งฟังก์ชัน factorial ของเราจะมีจุดจบที่ 1 เราจึงให้มัน return 1
เมื่อเรามาดูจุดที่ฟังก์ชันต้องทำต่อไป จะเห็นว่า เราสามารถทำรูปแบบการทำงานมันให้เป็น n จนถึง 1 ได้แล้ว เหลือเพียงการทำให้มันสามารถคำนวณตามจำนวนรอบที่มีซึ่งการคำนวณในแต่ละรอบก็จะแบ่งย่อย เป็นรอบละ n คูณกับรอบต่อไปเรื่อยๆ นั่นคือ n * factorial(n-1) นั่นเอง
ดังนั้นจุดสุดท้ายก็ใส่ return n * factorial(n-1) ก็เป็นอันสมบูรณ์
ผลที่ได้ก็จะเป็นเหมือนโค้ดด้านล่าง
factorial of 5 is 120
เหมือนเด๊ะ!!!
ร่ายมาทั้งหมด มันมีไว้ทำไม?
ตั้งแต่ที่เราผ่านมาด้วยกันทั้งหมด ก็คงจะเกิดคำถามว่าลูปก็มีทำไมต้องเรียนด้วย?
ถ้าเราลองเทียบโค้ดทั้ง2แบบดู จะเห็นได้ชัดเลยว่า Recursive function จะเขียนน้อยกว่าซึ่งสามารถประหยัดเวลาได้เยอะทีเดียว หากเราเข้าใจโครงสร้างเราอย่างดี
และนอกจากนี้ ยังสามารถใช้แก้ปัญหาเฉพาะบางประเภทที่มีประสิทธิภาพอีกด้วย เช่นการหาข้อมูลจากโครงสร้างต้นไม้ (Tree) ดังภาพด้านล่าง
สำหรับวันนี้ก็ขอจบเพียงแค่นี้หวังว่าหลาย ๆ คนจะเข้าใจได้เร็วกว่าหมาวิ่ง หากชอบใจก็สามารถติดตามหัวข้อต่างๆได้ที่ blog นี้ครับ