מיון מנייה

במדעי המחשב, מיון מנייה או מיון ספירה (counting sort) הוא אלגוריתם מיון עבור מספרים שלמים חיוביים (כלומר מספרים טבעיים), המתבסס על העובדה שהמספרים נמצאים בטווח חסום, כדי לבצע את המיון בזמן מהיר יותר מזה שמסוגלים לו אלגוריתמי המיון ההשוואתיים. בצורה אינטואיטיבית, די למיון לסרוק פעם אחת את קבוצת האיברים שצריך למיין, ולמנות את מספר המופעים של כל אחד מהאיברים בטווח החסום, ומכאן שמו של האלגוריתם. שדה האיברים שיש למיין כולל ערכים שהם מספרים טבעיים בטווח   1 , … , k {\displaystyle \ 1,\dots ,k} . מערך המקור, אותו יש למיין, ייקרא   A {\displaystyle \ A} , ומערך המטרה, לתוכו תישמר תוצאת המיון, ייקרא   B {\displaystyle \ B} . יוצרים מערך   C {\displaystyle \ C} בעל   k {\displaystyle \ k} תאים מאופסים. עוברים על מערך   A {\displaystyle \ A} ומונים את מספר המופעים של כל איבר בו. כלומר, כאשר מגיעים לאיבר   A [ i ] = j {\displaystyle \ A[i]=j} , אזי מבצעים את הפעולה   C [ j ] = C [ j ] + 1 {\displaystyle \ C[j]=C[j]+1} . לאחר שהסתיים המעבר על מערך המקור, התא   C [ i ] {\displaystyle \ C[i]} מכיל את מספר ההופעות של איבר   i {\displaystyle \ i} במערך   A {\displaystyle \ A} . לאחר מכן, סוכמים את מספר המופעים - מוסיפים לכל   C [ i ] {\displaystyle \ C[i]} את קודמו -   C [ i ] = C [ i ] + C [ i − 1 ] {\displaystyle \ C[i]=C[i]+C[i-1]} . באופן זה, בתא   C [ i ] {\displaystyle \ C[i]} שמור מספר האיברים אשר קטנים או שווים ל-   i {\displaystyle \ i} במערך   A {\displaystyle \ A} . בשלב הבא עוברים על מערך   A {\displaystyle \ A} מהסוף להתחלה, ועל כל איבר   A [ i ] {\displaystyle \ A[i]} מבצעים:   B [ C [ A [ i ] ] − 1 ] = A [ i ] {\displaystyle \ B[C[A[i]]-1]=A[i]}   C [ A [ i ] ] = C [ A [ i ] ] − 1 {\displaystyle \ C[A[i]]=C[A[i]]-1} המערך   B {\displaystyle \ B} יהיה ממוין, והסדר בין איברים שווים נשמר, מה שגורם לכך שמיון זה יהיה מיון יציב. זאת משום שבתא   C [ i ] {\displaystyle \ C[i]} נשמר המופע האחרון המיועד של האיבר   i {\displaystyle \ i} במערך   B {\displaystyle \ B} , ומשום שהמעבר על מערך   A {\displaystyle \ A} היה מהסוף להתחלה. סיבוכיות הזמן של המיון תלויה לא רק במספר האיברים בקלט, אלא גם בטווח האפשרי שלהם, מכיוון שעוברים הן על כל הקלט, והן על כל המערך, שאורכו הוא כאורך הטווח האפשרי של איברי הקלט. אם   n {\displaystyle \ n} הוא מספר האיברים ו-   k {\displaystyle \ k} הוא הטווח, אז סיבוכיות הזמן היא   O ( n + k ) {\displaystyle \ O(n+k)} . על כן, אם   k = O ( n ) {\displaystyle \ k=O(n)} , כלומר הטווח הוא ליניארי בגודל הקלט או פחות מכך, אזי תהיה סיבוכיות הזמן של המיון   O ( n ) {\displaystyle \ O(n)} . זו תוצאה העדיפה אסימפטוטית על זו של מיונים מבוססי השוואות, שסיבוכיות הזמן המינימלית שלהם היא   O ( n log ⁡ n ) {\displaystyle \ O(n\log n)} . אפשר ליישם את האלגוריתם בסיבוכיות   O ( n ) {\displaystyle \ O(n)} גם כאשר טווח הערכים הוא   1 , … , n 2 {\displaystyle \ 1,\dots ,n^{2}} , כלומר לא ליניארי לגודל הקלט. למשל, עבור קלט בגודל   n {\displaystyle \ n} ותחום של   n 2 {\displaystyle \ n^{2}} , ממירים את המספרים לבסיס   n {\displaystyle \ n} , כך שמספר הספרות המקסימלי הוא 2, ומספר התאים במערך   C {\displaystyle \ C} הוא בסך הכל   n {\displaystyle \ n} , ולכן   k {\displaystyle \ k} אינו   n 2 {\displaystyle \ n^{2}} אלא   n {\displaystyle \ n} , ואז מיישמים מיון בסיס. תכונה נוספת של מיון מנייה היא שהוא מיון יציב, כלומר לא משנה את הסדר היחסי בין איברים זהים במיון. עבור כל קבוצה של איברים שקיים ביניהם יחס סדר מלא ניתן ליצור התאמה חד-חד ערכית ועל, כך שהאלגוריתם יכול באופן כללי לעבוד על קבוצות איברים שאינן בהכרח של מספרים טבעיים, כל עוד הן תחומות לטווח מסוים. מיון מנייה הוא חלק אינטגרלי ממיון בסיס, שמאפשר למיין גם מספרים שהטווח שלהם גדול מדי בשביל מיון מנייה רגיל. ניתן לממש מיון מניה בעזרת אלגוריתם מקבילי. האלגוריתם משתמש במערך מנייה בגודל n ⋅ d {\displaystyle n\cdot d} , כאשר n {\displaystyle n} הוא מספר הערכים שיש למיין ו- d {\displaystyle d} הוא רוחבו של טווח הערכים במערך. קיימת גרסה שמשתמשת במערך מניה בגודל n ⋅ n {\displaystyle n\cdot n} , ו- n 2 {\displaystyle n^{2}} מעבדים (כאשר n הוא מספר הערכים שיש למיין). זמן הריצה הוא log ⁡ ( n ) {\displaystyle \log(n)} . הדגמה של מיון מנייה מיון מניה בQueue