數據結構(八):優先隊列-最大最小優先


 

一、 優先隊列的概述

  在前面的數據結構(三):線性表-棧,隊列中記錄到,隊列是先進先出的結構,元素在隊列末端添加,在隊列前頭刪除,若使用該隊列的數據結構,則當要找出隊列中的最大最小值時,需要遍歷隊列

  對每個元素做比較后得出,這樣在實際的生產應用中效率是很低的,這時就需要有一種隊列,能快捷的獲取隊列中的最大或最小值,叫做優先隊列。

  使用優先隊列保存數據元素,能快速的獲取隊列的最大或最小值,比如計算機中有多個排隊的任務,但是需要按照優先級一一執行,此時優先隊列的優勢便得到了體現,在前一章對堆的記錄中

  我們發現堆能快速的找到最大或最小值並刪除,符合優先隊列的應用場景,因此本章我們使用堆來實現最大,最小優先隊列和索引優先隊列

   

二、 最小優先隊列

  1、最小優先隊列實際就是一個小頂堆,即每次插入堆中的元素,都存儲至堆末端,通過上浮操作比較,小於父節點則和父節點交換元素,直到根結點為止,這樣就形成了一個小頂堆。

  2、在獲取最小值時,由於堆是數組的結構,只需獲取根結點的值,即數組下標為1的值即可。

  3、獲取最小值並刪除,則可以交換根結點和尾結點,之后刪除尾結點,並對根結點進行下沉操作,保證每個父節點都小於兩個左右子樹即可

   

public class MinPriorityQueue<T extends Comparable<T>> {

 

// 初始化堆

private T[] items;

 

// 初始化個數

private int N;

 

/**

 * 返回優先隊列大小

 *

 * @return

 */

public int size() {

       return N;

}

 

/**

 * 隊列是否為空

 *

 * @return

 */

public boolean isEmpty() {

       return N==0;

}

 

/**

 * 構造方法,傳入堆的初始大小

 *

 * @param size

 */

public MinPriorityQueue(int size) {

       items = (T[]) new Comparable[size + 1];

       N = 0;

}

 

/**

 * 判斷堆中索引i處的值是否小於j處的值

 *

 * @param i

 * @param j

 * @return

 */

private boolean bigger(int i, int j) {

       return items[i].compareTo(items[j]) > 0;

}

 

/**

 * 元素位置的交換

 *

 * @param col

 * @param i

 * @param j

 */

private void switchPos(int i, int j) {

       T temp = items[i];

       items[i] = items[j];

       items[j] = temp;

}

 

/**

 * 刪除堆中最大的元素,並且返回這個元素

 *

 * @return

 */

public T delMin() {

       // 獲取根結點最大值

       T minValue = items[1];

 

       // 交換根結點和尾結點

       switchPos(1, N);

 

       // 尾結點置空

       items[N] = null;

 

       // 堆數量減1

       N--;

 

       // 根結點下沉

       sink(1);

 

       return minValue;

}

 

/**

 * 往堆中插入一個元素t

 *

 * @param t

 */

public void insert(T t) {

       items[++N] = t;

       swim(N);

}

 

/**

 * 使用上浮算法,使堆中索引k處的值能夠處於一個正確的位置

 *

 * @param k

 */

private void swim(int k) {

       while (k > 1) {

              if (bigger(k / 2, k)) {

                     switchPos(k, k /2);

              }

 

              k = k / 2;

       }

}

 

/**

 * 使用下沉算法,使堆中索引k處的值能夠處於一個正確的位置

 *

 * @param k

 */

private void sink(int k) {

       while (2 * k <= N) {

              int min;

              // 存在右子結點的情況

              if (2 * k + 1 <= N) {

                     if (bigger(2 * k, 2 * k + 1)) {

                            min = 2 * k + 1;

                     } else {

                            min = 2 * k;

                     }

              } else {

                     min = 2 * k;

              }

 

              // 當前結點不比左右子樹結點的最小值小,則退出

              if (bigger(min, k)) {

                     break;

              }

 

              switchPos(k, min);

              k = min;

       }

}

 

public static void main(String[] args) {

       String[] arr = { "S", "O", "R", "T", "E", "X", "A", "M", "P", "L", "E" };

       MinPriorityQueue<String> minpq = new MinPriorityQueue<>(20);

       for (String s : arr) {

              minpq.insert(s);

       }

       String del;

       while (!minpq.isEmpty()) {

              del = minpq.delMin();

              System.out.print(minpq.size());

              System.out.println(del + ",");

       }

 

}

}


三、
最大優先隊列

  1、最大優先隊列實際就是一個大頂堆,即每次插入堆中的元素,都存儲至堆末端,通過上浮操作比較,大於父節點則和父節點交換元素,直到根結點為止,這樣就形成了一個大頂堆。

  2、在獲取最大值時,由於堆是數組的結構,只需獲取根結點的值,即數組下標為1的值即可。

  3、獲取最大值並刪除,則可以交換根結點和尾結點,之后刪除尾結點,並對根結點進行下沉操作,保證每個父節點都大於兩個左右子樹即可

   

public class MaxPriorityQueue<T extends Comparable<T>> {

// 初始化堆

private T[] items;

 

// 初始化個數

private int N;

 

/**

 * 返回優先隊列大小

 *

 * @return

 */

public int size() {

       return N;

}

 

/**

 * 隊列是否為空

 *

 * @return

 */

public boolean isEmpty() {

       return N == 0;

}

 

/**

 * 構造方法,傳入堆的初始大小

 *

 * @param size

 */

public MaxPriorityQueue(int size) {

       items = (T[]) new Comparable[size + 1];

       N = 0;

}

 

/**

 * 判斷堆中索引i處的值是否小於j處的值

 *

 * @param i

 * @param j

 * @return

 */

private boolean bigger(int i, int j) {

       return items[i].compareTo(items[j]) > 0;

}

 

/**

 * 元素位置的交換

 *

 * @param col

 * @param i

 * @param j

 */

private void switchPos(int i, int j) {

       T temp = items[i];

       items[i] = items[j];

       items[j] = temp;

}

 

/**

 * 刪除堆中最大的元素,並且返回這個元素

 *

 * @return

 */

public T delMax() {

       // 獲取根結點最大值

       T maxValue = items[1];

 

       // 交換根結點和尾結點

       switchPos(1, N);

 

       // 尾結點置空

       items[N] = null;

 

       // 堆數量減1

       N--;

 

       // 根結點下沉

       sink(1);

 

       return maxValue;

}

 

/**

 * 往堆中插入一個元素t

 *

 * @param t

 */

public void insert(T t) {

       items[++N] = t;

       swim(N);

}

 

/**

 * 使用上浮算法,使堆中索引k處的值能夠處於一個正確的位置

 *

 * @param k

 */

private void swim(int k) {

       while (k > 1) {

              if (bigger(k, k / 2)) {

                     switchPos(k, k / 2);

              }

 

              k = k / 2;

       }

}

 

/**

 * 使用下沉算法,使堆中索引k處的值能夠處於一個正確的位置

 *

 * @param k

 */

private void sink(int k) {

       while (2 * k <= N) {

              int max;

              // 存在右子結點的情況

              if (2 * k + 1 <= N) {

                     if (bigger(2 * k, 2 * k + 1)) {

                            max = 2 * k;

                     } else {

                            max = 2 * k + 1;

                     }

              } else {

                     max = 2 * k;

              }

 

              // 當前結點比左右子樹的最大值大,則退出

              if (bigger(k, max)) {

                     break;

              }

 

              switchPos(k, max);

              k = max;

       }

}

 

public static void main(String[] args) {

       String[] arr = { "S", "O", "R", "T", "E", "X", "A", "M", "P", "L", "E" };

       MaxPriorityQueue<String> maxpq = new MaxPriorityQueue<>(20);

       for (String s : arr) {

              maxpq.insert(s);

       }

       System.out.println(maxpq.size());

       String del;

       while (!maxpq.isEmpty()) {

              del = maxpq.delMax();

              System.out.print(del + ",");

       }

 

}

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM