簡體   English   中英

Kruskal算法(集合除法)

[英]Kruskal Algorithm (set division)

我有一個了解Kruskal算法的問題。 這是代碼

#include <stdio.h>
#define MAX_VERTICLES 100
#define INF 1000

int parent[MAX_VERTICLES];
int num[MAX_VERTICLES];

void setInit(int n) {
    int i;
    for (i = 0; i < n; i++) {
        parent[i] = -1;
        num[i] = 1;
    }
}

int setFind(int vertex) {
    int p, s, i = -1;
    for (i = vertex;(p = parent[i]) >= 0; i = p)
        ;
    s = i;
    for (i = vertex;(p = parent[i]) >= 0; i=p)
        parent[i]=s;
    return s;
}

void setUnion(int s1, int s2) {
    if (num[s1] < num[s2]) {
        parent[s1]=s2;
        num[s2]+=num[s1];
    }
    else {
        parent[s2] = s1;
        num[s1] += num[s2];
    }
}

typedef struct {
    int key;
    int u;
    int v;
}element;

#define MAX_ELEMENT 100
typedef struct {
    element heap[MAX_ELEMENT];
    int heap_size;
}HeapType;

void init(HeapType *h) {
    h->heap_size = 0;
}

void printHeap(HeapType *h) {
    int i;
    int level = 1;
    printf("\n==========");
    for (i = 1; i <= h->heap_size;i++) {
        if (i = level) {
            printf("\n");
            level *= 2;
        }
        printf("\t%d", h->heap[i].key);
    }
    printf("\n==========");
}

void insertMinHeap(HeapType *h, element item) {
    int i;
    i = ++(h->heap_size);
    while ((i != 1) && (item.key < h->heap[i / 2].key)){
        h->heap[i] = h->heap[i / 2];
        i /= 2;
    }
    h->heap[i] = item;
}

element deleteMinHeap(HeapType *h) {
    int parent, child;
    element item, temp;
    item = h->heap[1];
    temp = h->heap[(h->heap_size)--];
    parent = 1;
    child = 2;
    while (child <= h->heap_size) {
        if ((child < h->heap_size) && (h->heap[child].key > h->heap[child + 1].key))
            child++;
        if (temp.key <= h->heap[child].key) break;
        h->heap[parent] = h->heap[child];
        parent = child;
        child *=2;
    }
    h->heap[parent] = temp;
    return item;
}

void insertHeapEdge(HeapType *h, int u, int v, int weight) {
    element e;
    e.u = u;
    e.v = v;
    e.key = weight;
    insertMinHeap(h, e);
}

void insertAllEdges(HeapType *h){
    insertHeapEdge(h, 0, 1, 13);
    insertHeapEdge(h, 1, 2, 36);
    insertHeapEdge(h, 2, 3, 12);
    insertHeapEdge(h, 2, 4, 28);
    insertHeapEdge(h, 3, 5, 32);
    insertHeapEdge(h, 4, 5, 14);
    insertHeapEdge(h, 0, 5, 19);
    insertHeapEdge(h, 0, 6, 23);
    insertHeapEdge(h, 1, 6, 15);
    insertHeapEdge(h, 5, 6, 20);
}

void kruskal(int n) {
    int edge_accepted = 0;
    HeapType h;
    int uset, vset;
    element e;

    init(&h);
    insertAllEdges(&h);
    setInit(n);
    while (edge_accepted<(n-1)){
        e = deleteMinHeap(&h);
        uset = setFind(e.u);
        vset = setFind(e.v);
        if (uset != vset) {
            printf("(%d,%d) %d \n", e.u, e.v, e.key);
            edge_accepted++;
            setUnion(uset, vset);
        }7
    }
}

void main(){
    kruskal(7);

    getchar();
}

我不明白setFind和setUnion函數是如何工作的(其他情況都很好)

有人可以明確地解釋算法嗎?

Kruskal的算法(旨在生成最小生成樹)需要子例程,用於找到給定頂點的連接組件以及合並連接組件的可能性。

顯然, parent[i]存儲一個頂點,可以遵循該頂點直到沒有父節點為止。 以這種方式到達的節點是所連接組件的根-可以通過setFind找到該節點; num[i]表示此關系定義的子代數。 因此,連接的組件被隱式表示。

setUnion函數旨在通過將一個連接的組件的根附加到另一個組件並更新子setUnion ,將較小的連接的組件合並為較大的組件。

您在此處發布的內容是聯合查找算法的實現。

它是一種用於以下操作的時間恆定的算法(實際上,如果實現良好):

- unite 2 equivalence classes into a single one
- find equivalence class of an element

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM