排序演算法之 優先佇列經典實現(基於二叉堆)

2022-02-28 12:08:35 字數 3911 閱讀 7032

許多應用都需要處理有序的元素,但有時,我們不要求所有元素都有序,或是一定要一次就將它們排序,許多情況下,我們會收集這些元素裡的最大值或最小值。

優先佇列與棧和佇列類似,但它有自己的奇妙之處。

在本文中,會講解基於二叉堆的一種優先佇列的經典實現方法(**沒有任何難度,主要是理解思想)。

資料結構二叉堆能很好地實現優先佇列的操作。在二叉堆中,每個元素都要保證大於等於另外兩個位置的元素,相應的,這些位置的元素又至少要大於等於陣列中的另外兩個元素。

將所有元素畫成一顆二叉樹,就能很容易看出這種結構。

(圖示1)

在堆有序的過程中我們會遇到兩種情況:

某個節點的優先順序上公升,我們需要由下至上恢復堆的順序。

當某個節點的優先順序下降,我們需要由上至下恢復堆的順序。

在排序演算法中,我們只通過私有輔助函式來訪問元素:

1

private

void exch(int i, int

j) 6

7private

boolean less(int i, int

j)

1

private

void swim(int k)

6 }

k/2即為k節點的父節點,當k大於k/2時交換兩者,並繼續與其父節點比較,直到找到合適的位置。

1

private

void sink(int k)

7if (!less(k, j))

10exch(k, j);

11 k =j;12}

13 }

對於二叉樹,2*k即為k的左子節點,將左右子節點進行比較,再將父節點與較大的子節點比較,如果子節點大於父節點,就將他們交換,並繼續向下比較,直到找到合適的位置。

如果不知道元素的個數,任意在初始化時造成空間的浪費。我們需要創造乙個函式,用來調整陣列的大小。

在插入方法中,如果空間已滿,就將陣列大小擴充套件為原來的兩倍。在刪除方法中,如果元素的個數小於陣列長度的1/4,就將陣列的長度減小一半。

1

private

void resize(int

n) 6 pq =temp;

7 l =n;

8 }

有了上面的方法,我們只需在插入和刪除方法中加入判斷語句即可。

④、多叉堆(了解即可)

在掌握了二叉堆的原理之後,將其改進為多叉堆只需要做幾個改動。下面直接放**,有興趣的朋友可以自己動手。

(示意圖2)

堆排序的sink()方法經過修改sink(a,b)中a是被排序的元素,b為排序的最大範圍(修改之前排序的最大範圍為元素總個數)。

1

public

void sort(comparable a)

6while(n>1)

10 }

可以看到在for迴圈中,我們只掃瞄了陣列一半元素,因為我們跳過了大小為1的子堆,每次對乙個節點排序時,以該節點為根節點的子堆就是有序的,所以我們最後會得到乙個堆有序的二叉堆。

下沉排序每次選出最大的元素放入陣列空出的位置,這有點像選擇排序,但所需的比較要小得多,因為堆提供了一種從未排序部分找到最大元素的有效方法。

1

public

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...