صف اولویت‌دار

صف اولویت‌دار (به انگلیسی: Priority Queue) از جمله ساختمان‌های داده بسیار پرکاربرد است.
در صف عادی از روش خروج به ترتیب ورود (FIFO) استفاده می‌شود. در این تکنیک مثل یک صف نانوایی داده‌ها به ترتیب ورود پشت سر هم در صف قرار می‌گیرند؛ بنابراین اولین داده ورودی اولین داده خروجی نیز خواهد بود.
اما در صف اولویت‌دار برای هر داده اولویتی - نه لزوماً منحصربه‌فرد - مشخص می‌شود. صف اولویت را می‌توان به اورژانس یک بیمارستان تشبیه کرد که هر بیمار با شدت بیماری بیشتر اولویت بیشتری برای رسیدگی دارد. سیستم‌عامل کامپیوتر هم برای مدیریت پردازش‌ها از صف‌های اولویت استفاده می‌کند.

شباهت با صف معمولی (بدون اولویت)

صف اولویت دار همانند صف معمولی است با این تفاوت که در هنگام خروج، عنصری که بالاترین اولویت را دارد، از لیستمان خارج می‌گردد.
صف معمولی حالت خاصی از صف اولویت‌دار است که در آن اولویت عناصر به‌ترتیب اضافه شدنشان کاهش پیدا می‌کند پس عنصری که در اول لیست است، بالاترین اولویت را داراست.

ساختن درخت Heap

ساختن یک درخت heap در واقع وارد کردن متوالی گره‌ها در آن است. برای وارد کردن یک گره به درخت heap، طی دو مرحله به صورت زیر عمل می‌کنیم:
۱- گره مفروض را در محلی از درخت که شرط کامل بودن آن به هم نخورد (بدون در نظر گرفتن شرط max-heap یا min-heap بودن) درج می‌کنیم.
۲- اگر گره مذکور بر اساس موقعیت خود در درخت، شرط max-heap یا min-heap بودن را نقض نکند، نیاز به انجام کاری نیست و عملیات درج تمام شده‌است. در غیر اینصورت، با جابجا کردن گره با والد خود، درخت جدیدی حاصل می‌شود که باید مرحله ۲ در مورد آن تکرار شود.

پیاده‌سازی صف اولویت‌دار

برای پیاده‌سازی صف اولویت‌دار عموماً از آرایه استفاده می‌شود. ما در اینجا سه روش مختلف را شرح می‌دهیم.

پیاده‌سازی با استفاده از آرایه نامرتب

در این روش زمانی که داده‌ای وارد صف می‌شود همچون صف عادی در انتهای آن قرار می‌گیرد. به عنوان نمونه داده‌های مثال زمانبندی CPU به صورت زیر در آرایه قرار می‌گیرند:
شماره پردازش: ۱ ۲ ۳ ۴ ۵ ۶
الویت: ۴ ۲ ۱ ۳ ۵ ۴
درج و حذف یک عنصر در این روش، از نظر زمانی به ترتیب (۱)O و (O(n است.
توجه داشته باشید که هر عنصر آرایه ساختمانی مرکب از دو عنصر شماره پردازش و اولویت آن است. هر پردازش جدید به انتهای صف اضافه می‌شود، که از مرتبه (O (۱ است.
اما زمانی که قرار است پردازشی از آن خارج شود باید تک تک عناصر بررسی شوند، تا پردازشی با بیشترین اولویت انتخاب شود. این فرایند از مرتبه (O (n است.

پیاده‌سازی با استفاده از آرایه مرتب

در این روش بر خلاف روش قبلی آرایه بر اساس اولویت‌ها مرتب شده‌است.
شماره پردازش:۵ ۶ ۱ ۷ ۴ ۲ ۳
الویت:۵ ۴ ۴ ۳ ۳ ۲ ۱
شماره پردازش: ۱ ۲ ۳ ۴ ۵ ۶ ۷
الویت:۴ ۲ ۱ ۳ ۵ ۴ ۳
زمانی که داده‌ای وارد صف می‌شود، بر اساس اولویت خود در محل مناسب قرار می‌گیرد.
در این حالت پردازش با بیشترین اولویت همواره در انتهای صف قرار دارد و هزینه استخراج آن (O (۱ است. این مسئله در مقایسه با آرایه نامرتب یک برتری است. اما در این روش هزینه درج (O(n است که در مقایسه با روش قبلی اصلاً بهینه نیست.
در کل می‌توان گفت روش آرایه مرتب و نامرتب هم ارز یکدیگر بوده و از لحاظ عملکرد تفاوت چندانی با هم ندارند.
درج و حذف یک عنصر در این روش، از نظر زمانی به ترتیب (O(n و (۱)O است.

پیاده‌سازی با استفاده از آرایه نیمه مرتب (درخت heap)

در این درخت heap، داده‌ها را بر اساس اولویت آن‌ها در یک درخت مکس-هیپ همانند شکل وارد می‌کنیم.
اعداد داخل گره‌ها اولویت و اعداد خارجی شماره پردازش هستند. درخت فوق در نمایش آرایه‌ای به صورت شکل نشان داده شده، خواهد شد.
در یک درخت min-heap عنصری با کوچکترین کلید همواره در ریشه قرار دارد (چرا!؟). در نتیجه عمل حذف گره ریشه از درخت min-heap کوچکترین عنصر آن را به ما می‌دهد. این عمل از مرتبه (O (logn است. عمل درج در min-heap هم همان‌طور که می‌دانید از همین مرتبه‌است.

مقایسه ۳ روش پیاده‌سازی صف اولویت‌دار

عملیات درج و حذف روی یک صف اولویتی که با استفاده از آرایه مرتب یا نامرتب ساخته شده باشد روی هم رفته از مرتبه (O (n است. اما در روش آرایه نیمه مرتب این مرتبه به (O (logn کاهش می‌یابد. پس می‌توان گفت که روش درخت هیپ برای پیاده‌سازی صف اولویتی کارایی بسیار بهتری دارد.