許多應用都需要處理有序的元素,但有時,我們不要求所有元素都有序,或是一定要一次就將它們排序,許多情況下,我們會收集這些元素裡的最大值或最小值。
優先佇列與棧和佇列類似,但它有自己的奇妙之處。
在本文中,會講解基於二叉堆的一種優先佇列的經典實現方法(**沒有任何難度,主要是理解思想)。
資料結構二叉堆能很好地實現優先佇列的操作。在二叉堆中,每個元素都要保證大於等於另外兩個位置的元素,相應的,這些位置的元素又至少要大於等於陣列中的另外兩個元素。
將所有元素畫成一顆二叉樹,就能很容易看出這種結構。
(圖示1)
在堆有序的過程中我們會遇到兩種情況:
某個節點的優先順序上公升,我們需要由下至上恢復堆的順序。
當某個節點的優先順序下降,我們需要由上至下恢復堆的順序。
在排序演算法中,我們只通過私有輔助函式來訪問元素:
1private
void exch(int i, int
j) 6
7private
boolean less(int i, int
j)
1k/2即為k節點的父節點,當k大於k/2時交換兩者,並繼續與其父節點比較,直到找到合適的位置。private
void swim(int k)
6 }
1對於二叉樹,2*k即為k的左子節點,將左右子節點進行比較,再將父節點與較大的子節點比較,如果子節點大於父節點,就將他們交換,並繼續向下比較,直到找到合適的位置。private
void sink(int k)
7if (!less(k, j))
10exch(k, j);
11 k =j;12}
13 }
如果不知道元素的個數,任意在初始化時造成空間的浪費。我們需要創造乙個函式,用來調整陣列的大小。
在插入方法中,如果空間已滿,就將陣列大小擴充套件為原來的兩倍。在刪除方法中,如果元素的個數小於陣列長度的1/4,就將陣列的長度減小一半。
1有了上面的方法,我們只需在插入和刪除方法中加入判斷語句即可。private
void resize(int
n) 6 pq =temp;
7 l =n;
8 }
④、多叉堆(了解即可)
在掌握了二叉堆的原理之後,將其改進為多叉堆只需要做幾個改動。下面直接放**,有興趣的朋友可以自己動手。
(示意圖2)
堆排序的sink()方法經過修改sink(a,b)中a是被排序的元素,b為排序的最大範圍(修改之前排序的最大範圍為元素總個數)。
1可以看到在for迴圈中,我們只掃瞄了陣列一半元素,因為我們跳過了大小為1的子堆,每次對乙個節點排序時,以該節點為根節點的子堆就是有序的,所以我們最後會得到乙個堆有序的二叉堆。public
void sort(comparable a)
6while(n>1)
10 }
下沉排序每次選出最大的元素放入陣列空出的位置,這有點像選擇排序,但所需的比較要小得多,因為堆提供了一種從未排序部分找到最大元素的有效方法。
1public
class maxpqextends comparable>
1011
public
boolean
isempty()
1415
public
intsize()
1819
public
void insert(key v)
24 pq[++n] =v;
25swim(n);26}
2728
public
void insert(key v, int d)
33 pq[++n] =v;
34swim(n, d);35}
3637
public
key delmax()
46return
max;47}
4849
public key delmax(int
d) 53 key max = pq[1];
54 exch(1, n--);
55 pq[n + 1] = null
;56 sinkm(1, d);
57if (n > 0 && n == l / 4)
61return
max;62}
6364
private
void swim(int k) 69}
7071
private
void swim(int k, int d) 76}
7778
private
void sink(int k)
84if (!less(k, j))
87exch(k, j);
88 k =j;89}
90}9192
private
void sinkm(int k, int d)
100 j++;
101}
102if (flag == k)
105exch(k, flag);
106 k =flag;
107}
108}
109110
private
void resize(int
n) 115 pq =temp;
116 l =n;
117}
118119
private
void exch(int i, int
j) 124
125private
boolean less(int i, int
j) 128
129public
void sort(comparable a)
134while(n>1)
138}
139140
private
void sink(int k, int n)
146if (!less(k, j))
149exch(k, j);
150 k =j;
151}
152}
153154
public
static
void
main(string args)
171/*
for (int i = 1; i <= 13; i++)
*/174
}175
176 }
演算法導論 優先佇列(基於堆排序)
include includeusing namespace std define length 10 void maxheapify int num,int i,int len 堆調整 void buildheap int num,int len 建立初始最大隊 int heapsort int ...
演算法之優先佇列
1 概念 優先順序佇列,顧名思義,就是一種根據一定優先順序儲存和取出資料的佇列。它可以說是佇列和排序的完美結合體,不僅可以儲存資料,還可以將這些資料按照我們設定的規則進行排序。優先順序佇列是堆的一種常見應用。有最大優先順序佇列 最大堆 和最小優先順序佇列 最小堆 優先順序佇列是一種維護有一組元素構成...
演算法 基於堆的優先佇列
1.具體演算法 public class maxpqimplements iterable 返回佇列是否為空 public boolean isempty 返回優先佇列中的元素個數 public int size 返回最大元素 public key max 向優先佇列中插入乙個元素 public v...