ส่วนใหญ่คำตอบที่นี่มีความผิด คำตอบที่ถูกต้องคือมันขึ้นอยู่กับ ตัวอย่างเช่นนี่คือฟังก์ชัน C สองฟังก์ชันที่เดินผ่านต้นไม้ ก่อนอื่น recursive:
static
void mm_scan_black(mm_rc *m, ptr p) {
    SET_COL(p, COL_BLACK);
    P_FOR_EACH_CHILD(p, {
        INC_RC(p_child);
        if (GET_COL(p_child) != COL_BLACK) {
            mm_scan_black(m, p_child);
        }
    });
}
และนี่คือฟังก์ชั่นเดียวกับที่ใช้กับการวนซ้ำ:
static
void mm_scan_black(mm_rc *m, ptr p) {
    stack *st = m->black_stack;
    SET_COL(p, COL_BLACK);
    st_push(st, p);
    while (st->used != 0) {
        p = st_pop(st);
        P_FOR_EACH_CHILD(p, {
            INC_RC(p_child);
            if (GET_COL(p_child) != COL_BLACK) {
                SET_COL(p_child, COL_BLACK);
                st_push(st, p_child);
            }
        });
    }
}
มันไม่สำคัญที่จะเข้าใจรายละเอียดของรหัส เพียงแค่นั่นpคือโหนดและนั่นP_FOR_EACH_CHILDจะเป็นการเดิน ในรุ่นที่ซ้ำกันเราต้องการสแต็คอย่างชัดเจนstไปที่โหนดจะถูกผลักแล้วผุดและจัดการ
ฟังก์ชั่นวนซ้ำทำงานเร็วกว่าฟังก์ชั่นวนซ้ำมาก เหตุผลเป็นเพราะในระยะหลังสำหรับแต่ละรายการที่CALLจะฟังก์ชั่นที่จำเป็นและจากนั้นอีกครั้งเพื่อให้st_pushst_pop
ในอดีตคุณมีการเรียกซ้ำCALLสำหรับแต่ละโหนดเท่านั้น
นอกจากนี้การเข้าถึงตัวแปรบน callstack นั้นทำได้รวดเร็วอย่างไม่น่าเชื่อ หมายความว่าคุณกำลังอ่านจากหน่วยความจำซึ่งน่าจะอยู่ในแคชด้านในสุดเสมอ ในทางกลับกันสแต็กที่ชัดเจนต้องได้รับการสนับสนุนโดยmalloc: ed memory จาก heap ซึ่งเข้าถึงได้ช้ากว่ามาก
ด้วยการปรับให้เหมาะสมอย่างระมัดระวังเช่น inlining st_pushและst_popฉันสามารถเข้าถึงความเท่าเทียมกันอย่างคร่าวๆด้วยวิธีเรียกซ้ำ แต่อย่างน้อยในคอมพิวเตอร์ของฉันค่าใช้จ่ายในการเข้าถึงหน่วยความจำฮีปนั้นใหญ่กว่าค่าใช้จ่ายของการโทรซ้ำ
แต่การสนทนานี้ส่วนใหญ่จะเป็นที่สงสัยเพราะเดินต้นไม้ recursive เป็นที่ไม่ถูกต้อง หากคุณมีต้นไม้ขนาดใหญ่พอคุณจะหมดพื้นที่ callstack ซึ่งเป็นสาเหตุที่ต้องใช้อัลกอริทึมซ้ำ