Menu
Coddy logo textTech

Heap Sort (מיון ערימה)

עודכן לאחרונה

מיון ערימה מתייחס למערך כאל ערימה בינארית. קודם הוא בונה ערימת מקסימום, כך שהאיבר הגדול ביותר יושב בשורש (אינדקס 0). אחר כך הוא מחליף שוב ושוב את השורש עם האיבר הלא ממוין האחרון, וכך נועל את המקסימום במקומו, ומוריד את השורש החדש כדי להחזיר את תכונת הערימה. לחצו על הפעלה למעלה כדי לראות את בניית הערימה ואת השליפות.

מיון ערימה מבטיח זמן של O(n log n) כמו מיון מיזוג, אבל ממיין במקום עם O(1) זיכרון נוסף בלבד. הוא לא יציב ובדרך כלל ההתנהגות שלו מול המטמון גרועה יותר משל quicksort, ולכן בוחרים בו לעתים קרובות כשגם חסם מובטח וגם זיכרון קבוע חשובים.

סיבוכיות זמן וזיכרון

מקרהסיבוכיותהערות
המקרה הטובO(n log n)בנייה ועוד n שליפות
המקרה הממוצעO(n log n)סדר אקראי
המקרה הגרועO(n log n)מובטח
זיכרוןO(1)במקום
יציבלאההורדה משנה את הסדר של איברים שווים

צעד אחר צעד

צעדמה קורה
1בונים ערימת מקסימום מהמערך (הורדה החל מההורה האחרון).
2מחליפים את השורש (המקסימום) עם האיבר האחרון בערימה.
3מקטינים את הערימה באחד: התא האחרון הזה ממוין עכשיו.
4מורידים את השורש החדש כדי להחזיר את תכונת ערימת המקסימום.
5חוזרים על כך עד שנשאר בערימה איבר אחד.

דוגמה מפורטת

מיון של [3, 1, 6, 5, 2, 4]. הקו | מסמן את הגבול בין הערימה המצטמקת לזנב הממוין:

מעברמערךפעולה
בניית ערימה[6, 5, 4, 1, 2, 3]מורידים החל מההורה האחרון כדי לבנות את ערימת המקסימום; 6 נמצא עכשיו בשורש.
1[5, 3, 4, 1, 2 | 6]מחליפים את השורש 6 עם התא האחרון, מקטינים את הערימה ומורידים את 3.
2[4, 3, 2, 1 | 5, 6]מוציאים את השורש 5, ואז מורידים את 2 כך ש-4 עולה לשורש.
3[3, 1, 2 | 4, 5, 6]מוציאים את השורש 4, ואז מורידים את 1 כך ש-3 עולה לשורש.
4[2, 1 | 3, 4, 5, 6]מוציאים את השורש 3; 2 כבר מקיים את תכונת הערימה.
5[1 | 2, 3, 4, 5, 6]מוציאים את השורש 2; נשאר איבר אחד, ולכן המערך ממוין.

מתי להשתמש במיון ערימה

השתמשו בו כאשרהימנעו ממנו כאשר
אתם צריכים מקרה גרוע מובטח של O(n log n) בלי סיכון ל-O(n²).אתם צריכים מיון יציב ששומר על הסדר של מפתחות שווים.
הזיכרון מוגבל: הוא ממיין במקום עם O(1) זיכרון נוסף בלבד.ביצועי המטמון חשובים והנתונים נכנסים לזיכרון: quicksort בדרך כלל מהיר יותר.
אתם כבר מתחזקים ערימה (למשל תור עדיפויות) על הנתונים.אתם רוצים הכי מעט השוואות: מיון מיזוג ו-quicksort מבצעים לעתים קרובות פחות בפועל.
קלט לא מהימן עלול להפעיל את המקרה הגרוע של quicksort ואי אפשר להכניס אקראיות.הנתונים כמעט ממוינים: מיון הכנסה רץ עליהם בזמן כמעט ליניארי.

קוד Heap Sort

מימוש נקי של Heap Sort שאפשר להריץ, ב-Python, JavaScript, Java, C++, C. בחרו שפה, העתיקו את הקוד, או פתחו אותו טעון מראש בעורך האונליין של Coddy.

קוד Heap Sort ב-Python

Python
1def heap_sort(a):2    n = len(a)3    # Build a max-heap, deepest parent first4    for i in range(n // 2 - 1, -1, -1):5        sift_down(a, i, n)6    # Repeatedly move the max to the end and shrink the heap7    for end in range(n - 1, 0, -1):8        a[0], a[end] = a[end], a[0]9        sift_down(a, 0, end)10    return a11
12
13def sift_down(a, i, size):14    while True:15        largest = i16        left, right = 2 * i + 1, 2 * i + 217        if left < size and a[left] > a[largest]:18            largest = left19        if right < size and a[right] > a[largest]:20            largest = right21        if largest == i:22            return23        a[i], a[largest] = a[largest], a[i]24        i = largest25
26
27nums = [12, 11, 13, 5, 6, 7]28print("Before:", nums)29heap_sort(nums)30print("After: ", nums)
להריץ את הקוד הזה בעורך ה-Python אונליין

שאלות נפוצות על מיון ערימה

מהי סיבוכיות הזמן של מיון ערימה?
מיון ערימה הוא O(n log n) במקרה הטוב, הממוצע והגרוע. בניית הערימה היא O(n) וכל אחת מ-n השליפות עולה O(log n). הוא משתמש ב-O(1) זיכרון נוסף.
האם מיון ערימה יציב?
לא. פעולת ההורדה יכולה להזיז איברים שווים זה מעבר לזה, ולכן מיון ערימה לא שומר על הסדר היחסי של מפתחות שווים.
מתי כדאי להשתמש במיון ערימה?
השתמשו במיון ערימה כשאתם צריכים מקרה גרוע מובטח של O(n log n) עם O(1) זיכרון נוסף בלבד. הוא נמנע מהסיכון של O(n²) ב-quicksort בלי החוצץ של O(n) במיון מיזוג, במחיר של יציבות וביצועי מטמון.
מה ההבדל בין מיון ערימה ל-quicksort?
שניהם ממיינים במקום, אבל ל-quicksort יש מקרה גרוע של O(n²), ואילו מיון ערימה מבטיח O(n log n). בפועל quicksort בדרך כלל מהיר יותר בזכות מקומיות מטמון טובה יותר ופחות החלפות, ולכן מעדיפים את מיון הערימה בעיקר כשחייבים להבטיח את החסם של המקרה הגרוע.
איך מיון ערימה קשור לתור עדיפויות?
ערימה בינארית היא המימוש הסטנדרטי של תור עדיפויות, ומיון ערימה הוא בעצם שליפה חוזרת של המקסימום מהתור הזה. אם אתם כבר שומרים את הנתונים בערימה, שליפת האיברים אחד אחד נותנת לכם סדר ממוין בלי עלות נוספת.
האם מיון ערימה צריך ערימת מקסימום או ערימת מינימום?
כדי למיין בסדר עולה במקום, השתמשו בערימת מקסימום: האיבר הגדול ביותר מוחלף לסוף בכל מעבר, והזנב הממוין גדל מימין. ערימת מינימום הייתה מייצרת סדר יורד במקום, או סדר עולה אם שולפים למערך נפרד.
איור של שפות התכנות ב-Coddy

לשלוט באלגוריתמים עם Coddy

להתחיל