【數據結構和演算法:簡單方法】談一談優先隊列的實現

【系列文章推薦閱讀】

首先回憶一下隊列(詳細內容移步至隊列詳解),只要記住八個字即可:先進先出(FIFO),後進後出(LILO)。

就像去醫院門診看病排隊時一樣:先來的先看,看完先走。

而優先隊列的特性正是「優先」二字,「優先」二字意味著打破了「常規」「規則」。

優先隊列不再遵守普通隊列的先進先出的原則了,如何不遵守呢?

  • 最大優先隊列:不管入隊順序如何,誰的值最大誰先出隊
  • 最小優先隊列:不管入隊順序如何,誰的值最小誰先出隊

比如,對於最大優先隊列,入隊順序為:14352,出隊順序則為:54321;對於最小優先隊列,入隊順序為:14352,出隊順序則為:12345.

舉個例子:醫院的急診病例,即便來的晚,也是可以優先看病的,因為生命至上。遇到災難危險時,群眾中會先疏散小孩子。

如果在諸如此類需要講「優先」的情況下,再去講什麼「先進先出」的排隊規則,那就不太好了。

那麼該如何實現優先隊列呢?

首先,在優先隊列中,想要出隊元素,肯定要先找到最大值,或者最小值;

其次,優先隊列「不講常規」,所以進隊順序已經不重要了,重要的是找到當前隊列中的最大值或最小值。

那麼,有沒有一個能直接找到最大值或最小值,並不在意其它順序的方法呢?

有!這個方法就是二叉堆!(詳細內容請移步至二叉堆詳解

  1. 二叉堆的堆頂是該堆中的最大值或最小值
  2. 插入一個結點,即插入到二叉堆的最末尾,然後會再次調整構成二叉堆
  3. 刪除一個結點,即刪除堆頂,然後會再次調整構成二叉堆

所以可以藉助二叉堆來實現優先隊列,最大堆實現最大優先隊列,最小堆實現最小優先隊列

  1. 出隊即把堆頂出隊
  2. 入隊即向二叉堆中插入一個結點
  3. 出隊即刪除堆頂

天作之合!完美~

下面是最大優先隊列的程式碼實現。

優先隊列的結構體即是二叉堆的結構體:

typedef struct {
    int array[MAXSIZE];
    int length;
} BinaryHeap, PriorityQueue;

入隊操作:

/**
 * @description: 最大優先隊列入隊
 * @param {PriorityQueue} *queue 隊列指針
 * @param {int} elem 入隊元素
 * @return {*} 無
 */
void en_max_queue(PriorityQueue *queue, int elem)
{
    insert_into_max_heap(queue, elem);
}

出隊操作:

/**
 * @description: 最大優先隊列出隊
 * @param {PriorityQueue} *queue 隊列指針
 * @param {int} *elem 保存變數指針
 * @return {*} 無
 */
void de_max_queue(PriorityQueue *queue, int *elem)
{
    delete_from_max_heap(queue, elem);
}

函數 insert_into_max_heapdelete_from_max_heap 的實現在文章【二叉堆的原理及操作】中已經實現了,這裡不再贅述。

以上就是優先隊列的內容。

完整程式碼請移步至 GitHub | Gitee 獲取。

如有錯誤,還請指正。

如果覺得寫的不錯,可以點個贊和關注。後續會有更多數據結構和演算法相關文章。