Menu
Coddy logo textTech

Quick Sort (מיון מהיר)

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

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

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

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

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

צעד אחר צעד

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

דוגמה מפורטת

מיון של [5, 2, 4, 1] בשיטת Lomuto (האיבר האחרון כציר):

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

מתי להשתמש ב-quicksort

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

קוד Quick Sort

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

קוד Quick Sort ב-Python

Python
1def quick_sort(a, low=0, high=None):2    if high is None:3        high = len(a) - 14    if low < high:5        p = partition(a, low, high)6        quick_sort(a, low, p - 1)7        quick_sort(a, p + 1, high)8    return a9
10
11def partition(a, low, high):12    # Lomuto partition: everything < pivot moves left of it13    pivot = a[high]14    i = low15    for j in range(low, high):16        if a[j] < pivot:17            a[i], a[j] = a[j], a[i]18            i += 119    a[i], a[high] = a[high], a[i]20    return i21
22
23nums = [10, 7, 8, 9, 1, 5]24print("Before:", nums)25quick_sort(nums)26print("After: ", nums)
להריץ את הקוד הזה בעורך ה-Python אונליין

שאלות נפוצות על quick sort

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

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

להתחיל