演算法導論小結 10 最小生成樹

2021-05-01 10:50:20 字數 3549 閱讀 6270

by:

潘雲登

對於商業目的下對本文的任何行為需經作者同意。

寫在前面

1.本文內容對應《演算法導論》(第

2版)》第

23章。 2.

主要介紹了兩種構建最小生成樹的方法:

kruskal

演算法和prim

演算法。 3.

kruskal

演算法和prim

演算法,可以以鄰接表表示的圖為基礎(可參考《

圖的表示與搜尋

》),並且都利用了

貪心演算法

的思想。假設最小生成樹(

mst,

minimum spanning tree

)問題針對的是無向連通加權圖

g=(v, e)

,那麼mst

中邊的個數為

|v|-1

kruskal

演算法

首先定義幾個概念。無向圖

g=(v, e)

的乙個割

(s, v-s)是對v

的乙個劃分。當一條邊

(u, v)∈e

的乙個端點屬於

s,而另乙個端點屬於

v-s時,稱邊

(u, v)

通過割(s, v-s)

。如果乙個邊的集合

a中沒有邊通過某一割,則說該割不妨礙邊集

a。如果某條邊的權值是通過乙個割的所有邊中最小的,則稱該邊為通過這個割的一條輕邊。

kruskal

演算法首先選擇權值最小的一條邊,並將它的兩個端點劃入

s,表示最小生成樹的乙個子集。然後,選擇通過割

(s, v-s)

的一條輕邊,將屬於

v-s的端點劃入

s。重複上述過程,直到集合

v-s為空。所有被選擇的邊即為最小生成樹的邊。

void mst_kruskal(adjlist *graphic)

}graphic->mst_size = j;

}其中,

make_set

執行時間為

o(1)

,對各條邊按權值進行的快速排序需要

o(e lg e)

,執行o(e)

次find_set

和union_set

操作所需的總時間為

o(e lg e)

。因此,

kruskal

演算法的總執行時間為

o(e lg e)。

這裡,用到了不相交集合上的操作(第

21章)。其中,

make_set(x)

建立乙個新的集合,其唯一成員為x。

union_set(x, y)

將包含x和y

的動態集合合併為乙個新的集合。

find_set(x)

返回乙個指標,指向包含

x的集合的代表。在不相交集合的一種實現中,用有根樹表示集合。每個結點僅指向其父結點。每棵樹的根作為集合的代表,並且是它自己的父結點。為改進執行時間,可採用兩種啟發式策略:一是按秩合併,其思想是把包含較少結點的樹的根指向包含較多結點的樹的根;二是路徑壓縮,使查詢路徑上的每個結點都直接指向根結點,但不改變結點的秩。為執行路徑壓縮,

find_set

是一種兩趟方法:一趟是沿查詢路徑上公升,直到找到根;一趟是沿查詢路徑下降,以便更新每個結點,使之直接指向根。

void make_set(dobj *obj)

void union_set(dobj *x, dobj *y)

void link_set(dobj *x, dobj *y)

else

}dobj * find_set(dobj *x)

prim

演算法

prim

演算法的特點是最小生成樹子集

a中的邊總是形成單棵樹。樹從任意根頂點開始形成,並逐漸生成,直至該樹覆蓋了

v中的所有頂點。在每一步,總是在以

a中頂點為乙個端點的所有邊中,選擇一條輕邊加入到樹中。在演算法的執行過程中,不在樹中的所有頂點都放在乙個基於邊權重的最小優先佇列中(可參考《

堆的使用

》)。

void mst_prim(adjlist *graphic, int start)

h.array[start].key = 0;

build_min_heap(&h);

graphic->mst_size = 0;

while(h.heap_size>0)

temp_lnode = graphic->vlist[temp_vhnode->index].link;

while(temp_lnode != null)

temp_lnode = temp_lnode->next;}}

free_heap(&h);

}這裡,暫且用

color

域標識頂點是否在優先佇列中。

prim

演算法的效能取決於優先佇列如何實現。如果用最小堆來實現,那麼

while

迴圈中,執行

|v|次的

heap_extract_min

操作需要

o(v lg v)

時間。另外,需要檢查

o(e)

條邊,而對邊進行

heap_decrease_key

操作需要

o(lg v)

時間。因此,

prim

演算法的整個執行時間為

o(v lg v+ e lg v)=o(e lg v)。

附最小堆實現的最小優先佇列。

typedef struct vertex_heap_node

vhnode;

typedef struct heap_array

heap;

int parent(int i)

; int left(int i)

; int right(int i)

; void exchange(vhnode *a, vhnode *b);

void init_heap(heap *h, int vertex_number);

void free_heap(heap *h);

void min_heapify(heap *h, int i)

}void build_min_heap(heap *h)

vhnode * heap_extract_min(heap *h)

void heap_decrease_key(heap *h, int i, int key)

}

演算法導論 最小生成樹

華電北風吹 日期 2016 1 16 常用的最小生成樹演算法有prime演算法和kruskal演算法。prime演算法基於節點,kruskal基於邊。1 prime演算法 prime演算法屬於貪心演算法,與廣度優先搜尋類似。保持乙個屬於已發現的最小生成樹節點的集合。每一次從未在樹中的節點中選擇乙個與...

演算法導論 最小生成樹擴充套件

一,次最小生成樹 定義 設t是圖g的最小生成樹,如果t1滿足 t1 min,則t1是g的次小生成樹。解釋 除了最小生成樹外,另外乙個生成樹的權值和最小的生成樹,定義為次最小生成樹。經典題目 poj1679 the unique mst,對於一張圖,判斷最小生成樹是否惟一。惟一的定義是 不存在第二棵生...

演算法導論 最小生成樹(prim演算法)

一,定義 沒有權值時 乙個有n個節點的聯通圖,生成樹是,極小聯通子圖。包含圖中所有節點,且有保持圖聯通的最少的邊。邊有權值時 無向聯通圖g v,e 權值函式,w e r。找到g的一棵最小生成樹,使得 w t 最小。w t 為最小生成樹所有邊權值和。二,prime演算法 1 初始化 u te 節點集u...