圖之kruskal演算法

來源:互聯網
上載者:User

kruskal演算法是一種最小產生樹演算法。基本思想如下:

設有一個有n個頂點的連通網N={V,E},最初先構造一個只有n個頂點,沒有邊的非連通圖T={V, E},圖中每個頂點自成一個連通分量。當在E中選到一條具有最小權值的邊時,若該邊的兩個頂點落在不同的連通分量上,則將此邊加入到T中;否則將此邊捨去,重新選擇一條權值最小的邊。如此重複下去,直到所有頂點在同一個連通分量上為止。

下面舉例說明kruskal演算法:


c語言實現如下:(使用鄰接矩陣儲存)

#include <stdio.h>#include <malloc.h>#define VERTEXNUM 6#define TRUE 1#define FALSE 0void createGraph(int (*edge)[VERTEXNUM], int start, int end, int value);void displayGraph(int (*edge)[VERTEXNUM]);void kruskal(int (*edge)[VERTEXNUM], int (**tree)[VERTEXNUM]);void selectEdge(int (*edge)[VERTEXNUM], int (*tree)[VERTEXNUM], int* start, int* end, int* value);int isInSeparate(int (*tree)[VERTEXNUM], int start, int end);void isInSeparateCore(int (*tree)[VERTEXNUM], int vertex, int end, int* vertexStatusArr, int* result);int isNotInTree(int (*tree)[VERTEXNUM], int start, int end);int isTree(int (*tree)[VERTEXNUM]);void isTreeCore(int (*tree)[VERTEXNUM], int vertex, int* vertexStatusArr, int* vertexNum);int main(void){//動態建立存放邊的二維數組         int (*edge)[VERTEXNUM] = (int (*)[VERTEXNUM])malloc(sizeof(int)*VERTEXNUM*VERTEXNUM);        int i,j;        for(i=0;i<VERTEXNUM;i++){                for(j=0;j<VERTEXNUM;j++){                        edge[i][j] = 0;                }        }//列印圖        printf("after init:\n");        displayGraph(edge);//建立圖(從頂點0到1有一條權值為6的邊,從頂點1到0有一條權值為6的邊,依次類推)        createGraph(edge,0,1,6);        createGraph(edge,0,3,5);        createGraph(edge,0,2,1);        createGraph(edge,1,2,5);        createGraph(edge,1,4,3);        createGraph(edge,2,4,6);        createGraph(edge,2,3,5);        createGraph(edge,2,5,4);        createGraph(edge,3,5,2);        createGraph(edge,4,5,6);//列印圖        printf("after create:\n");        displayGraph(edge);//最小產生樹         int (*tree)[VERTEXNUM] = NULL;        kruskal(edge, &tree);        printf("after generate tree:\n");        displayGraph(tree);//釋放佔用的資源         free(edge);        free(tree);        return 0;}//建立圖,從start頂點到end頂點,權值為value;從end頂點到start頂點,權值為value;void createGraph(int (*edge)[VERTEXNUM], int start, int end, int value){        edge[start][end] = value;        edge[end][start] = value;}//列印圖void displayGraph(int (*edge)[VERTEXNUM]){        int i,j;        for(i=0;i<VERTEXNUM;i++){                for(j=0;j<VERTEXNUM;j++){                        printf("%d ",edge[i][j]);                }                printf("\n");        }}//最小產生樹 void kruskal(int (*edge)[VERTEXNUM], int (**tree)[VERTEXNUM]){//申請最小產生樹佔用的資源         *tree = (int (*)[VERTEXNUM])malloc(sizeof(int)*VERTEXNUM*VERTEXNUM);        int i,j;        for(i=0;i<VERTEXNUM;i++){                for(j=0; j<VERTEXNUM; j++){                        (*tree)[i][j] = 0;                }        }        int start,end,value;//如果目前為止產生的還不是樹        while(!isTree(*tree)){                start = end = -1;                value = 999;//選擇合適的邊                selectEdge(edge, *tree, &start, &end, &value);                if(start != -1 && end != -1 && value != 999){//將邊儲存到tree中                        createGraph(*tree, start, end, value);                }        }}//選擇合適的邊void selectEdge(int (*edge)[VERTEXNUM], int (*tree)[VERTEXNUM], int* start, int* end, int* value){        if(edge == NULL || tree == NULL || start == NULL || end == NULL || value == NULL){                printf("parameter error.\n");                return;        }        int i,j;//訪問所有的邊,只需要訪問一部分就可以了,另外一部分是相同的        for(i=0; i<VERTEXNUM-1; i++){                for(j=i+1; j<VERTEXNUM; j++){//如果權值最小,並且不在產生的tree中,並且在不同的連通分量中,則選擇該邊                          if(edge[i][j] != 0 && edge[i][j] < *value && isNotInTree(tree, i, j) && isInSeparate(tree, i, j)){                                *start = i;                                *end = j;                                *value = edge[i][j];                        }                }        }}//判斷start和end頂點是否在不同的連通分量中 int isInSeparate(int (*tree)[VERTEXNUM], int start, int end){        if(tree == NULL){                printf("parameter error.\n");                return FALSE;        }        int i,j;        int result = 0;        int* vertexStatusArr = (int*)malloc(sizeof(int)*VERTEXNUM);        for(i=0;i<VERTEXNUM;i++){                vertexStatusArr[i] = 0;        }        isInSeparateCore(tree, start, end, vertexStatusArr, &result);        free(vertexStatusArr);        if(result == 1){                return FALSE;        }else{                return TRUE;        }}void isInSeparateCore(int (*tree)[VERTEXNUM], int vertex, int end, int* vertexStatusArr, int* result){        if(*result == 1){                return;        }        int i;        for(i=0; i<VERTEXNUM; i++){                if(tree[vertex][i] != 0 && vertexStatusArr[i] == 0){                        vertexStatusArr[i] = 1;                        if(i == end){                                *result = 1;                                return;                        }                        isInSeparateCore(tree, i, end, vertexStatusArr, result);                }        }}//判斷start和end是否已經在tree中  int isNotInTree(int (*tree)[VERTEXNUM], int start, int end){        if(tree == NULL){                printf("parameter error.\n");                return FALSE;        }        if(tree[start][end] == 0 && tree[end][start] == 0){                return TRUE;        }        return FALSE;}//判斷tree是否是樹(從一個頂點從發,是否能夠遍曆到所有的點)  int isTree(int (*tree)[VERTEXNUM]){        if(tree == NULL){                printf("tree is not exist.\n");                return FALSE;        }        int i;        int vertexNum = 0;        int* vertexStatusArr = (int*)malloc(sizeof(int)*VERTEXNUM);        for(i=0;i<VERTEXNUM;i++){                vertexStatusArr[i] = 0;        }        isTreeCore(tree, 0, vertexStatusArr, &vertexNum);        free(vertexStatusArr);        if(vertexNum != VERTEXNUM){                return FALSE;        }else{                return TRUE;        }}void isTreeCore(int (*tree)[VERTEXNUM], int vertex, int* vertexStatusArr, int* vertexNum){        int i;        for(i=0; i<VERTEXNUM; i++){                if(tree[vertex][i] != 0 && vertexStatusArr[i] == 0){                        vertexStatusArr[i] = 1;                        (*vertexNum)++;                        isTreeCore(tree, i, vertexStatusArr, vertexNum);                }        }}

c語言實現如下:(使用鄰接表格儲存體)

#include <stdio.h>#include <malloc.h>#define VERTEXNUM 6#define TRUE 1#define FALSE 0//存放頂點的鄰接表元素typedef struct edge{        int vertex;        int value;        struct edge* next;}st_edge;void createGraph(st_edge** edge, int start, int end, int value);void displayGraph(st_edge** edge);void delGraph(st_edge** edge);void kruskal(st_edge** edge, st_edge*** tree);void selectEdge(st_edge** edge, st_edge** tree, int* start, int* end, int* value);void saveEdge(st_edge** tree, int start, int end, int value);int isInSeparate(st_edge** tree, int start, int end);void isInSeparateCore(st_edge** tree, st_edge* node, int end, int* vertexStatusArr, int* result);int isNotInTree(st_edge** tree, int start, int end);int isTree(st_edge** tree);void isTreeCore(st_edge** tree, st_edge* node, int* vertexStatusArr, int* vertexNum);int main(void){//動態建立存放邊的指標數組        st_edge** edge = (st_edge**)malloc(sizeof(st_edge*)*VERTEXNUM);        int i;        for(i=0;i<VERTEXNUM;i++){                edge[i] = NULL;        }//列印圖        printf("after init:\n");        displayGraph(edge);//建立圖        createGraph(edge,0,1,6);        createGraph(edge,0,3,5);        createGraph(edge,0,2,1);        createGraph(edge,1,2,5);        createGraph(edge,1,4,3);        createGraph(edge,2,4,6);        createGraph(edge,2,3,5);        createGraph(edge,2,5,4);        createGraph(edge,3,5,2);        createGraph(edge,4,5,6);//列印圖        printf("after create:\n");        displayGraph(edge);        st_edge** tree = NULL;//最小產生樹        kruskal(edge, &tree);//列印圖        printf("after generate tree:\n");        displayGraph(tree);//釋放佔用的資源        if(edge != NULL){                delGraph(edge);                edge = NULL;        }        if(tree != NULL){                delGraph(tree);                tree = NULL;        }        return 0;}//建立圖,從start頂點到end頂點,權值為value;從end頂點到start頂點,權值為value;void createGraph(st_edge** edge, int start, int end, int value){        if(edge == NULL){                printf("no space for graph.\n");                return;        }        st_edge* newedge1 = (st_edge*)malloc(sizeof(st_edge));        newedge1->vertex = end;        newedge1->value = value;        newedge1->next = NULL;        st_edge** edge1 = edge + start;        while(*edge1 != NULL){                edge1 = &((*edge1)->next);        }        *edge1 = newedge1;        st_edge* newedge2 = (st_edge*)malloc(sizeof(st_edge));        newedge2->vertex = start;        newedge2->value = value;        newedge2->next = NULL;        st_edge** edge2 = edge + end;        while(*edge2 != NULL){                edge2 = &((*edge2)->next);        }        *edge2 = newedge2;}//列印圖void displayGraph(st_edge** edge){        if(edge == NULL){                printf("graph is not exist.\n");                return;        }        int i;        st_edge* p;        for(i=0;i<VERTEXNUM;i++){                printf("%d:",i);                p = *(edge+i);                while(p != NULL){                        printf("%d(%d) ",p->vertex,p->value);                        p = p->next;                }                printf("\n");        }}//刪除圖void delGraph(st_edge** edge){        if(edge == NULL){                printf("graph is not exist.\n");                return;        }        int i;        st_edge* p;        st_edge* del;        for(i=0;i<VERTEXNUM;i++){                p = *(edge+i);                while(p != NULL){                        del = p;                        p = p->next;                        free(del);                }                edge[i] = NULL;        }        free(edge);}//最小產生樹void kruskal(st_edge** edge, st_edge*** tree){//申請最小產生樹佔用的資源        *tree = (st_edge**)malloc(sizeof(st_edge*)*VERTEXNUM);        int i;        for(i=0;i<VERTEXNUM;i++){                (*tree)[i] = NULL;        }        int start,end,value;//如果目前為止產生的還不是樹        while(!isTree(*tree)){                start = end = -1;                value = 999;//選擇合適的邊                selectEdge(edge, *tree, &start, &end, &value);                if(start != -1 && end != -1 && value != 999){//將邊儲存到tree中                        createGraph(*tree, start, end, value);                }        }}//選擇合適的邊void selectEdge(st_edge** edge, st_edge** tree, int* start, int* end, int* value){        if(edge == NULL || tree == NULL || start == NULL || end == NULL || value == NULL){                printf("parameter error.\n");                return;        }        int i;        st_edge* p = NULL;//遍曆所有的邊        for(i=0; i<VERTEXNUM; i++){                p = edge[i];                while(p != NULL){//如果權值最小,並且不在產生的tree中,並且在不同的連通分量中,則選擇該邊                        if(p->value < *value && isNotInTree(tree, i, p->vertex) && isInSeparate(tree, i, p->vertex)){                                *start = i;                                *end = p->vertex;                                *value = p->value;                        }                        p = p->next;                }        }}//判斷start和end頂點是否在不同的連通分量中int isInSeparate(st_edge** tree, int start, int end){        if(tree == NULL){                printf("parameter error.\n");                return FALSE;        }        int i;        st_edge* startNode = tree[start];        int result = 0;        int* vertexStatusArr = (int*)malloc(sizeof(int)*VERTEXNUM);        for(i=0;i<VERTEXNUM;i++){                vertexStatusArr[i] = 0;        }        isInSeparateCore(tree, startNode, end, vertexStatusArr, &result);free(vertexStatusArr);        if(result == 1){                return FALSE;        }else{                return TRUE;        }}void isInSeparateCore(st_edge** tree, st_edge* node, int end, int* vertexStatusArr, int* result){        if(*result == 1){                return;        }        while(node !=  NULL){                if(vertexStatusArr[node->vertex] == 0){                        vertexStatusArr[node->vertex] = 1;                        if(node->vertex == end){                                *result = 1;                                return;                        }                        isInSeparateCore(tree, tree[node->vertex], end, vertexStatusArr, result);                }                node = node->next;        }}//判斷start和end是否已經在tree中int isNotInTree(st_edge** tree, int start, int end){        if(tree == NULL){                printf("parameter error.\n");                return FALSE;        }        int i;        st_edge* p;        p = tree[start];        while(p != NULL){                if(p->vertex == end){                        return FALSE;                }                p = p->next;        }        return TRUE;}//判斷tree是否是樹(從一個頂點從發,是否能夠遍曆到所有的點)int isTree(st_edge** tree){        if(tree == NULL){                printf("tree is not exist.\n");                return FALSE;        }        int i;        int vertexNum = 0;        st_edge* startNode = tree[0];        int* vertexStatusArr = (int*)malloc(sizeof(int)*VERTEXNUM);        for(i=0;i<VERTEXNUM;i++){                vertexStatusArr[i] = 0;        }        isTreeCore(tree, startNode, vertexStatusArr, &vertexNum);        free(vertexStatusArr);        if(vertexNum != VERTEXNUM){                return FALSE;        }else{                return TRUE;        }}void isTreeCore(st_edge** tree, st_edge* node, int* vertexStatusArr, int* vertexNum){        if(tree == NULL || vertexStatusArr == NULL || vertexNum == NULL){                printf("parameter error!\n");                return;        }        while(node != NULL){                if(vertexStatusArr[node->vertex] == 0){                        vertexStatusArr[node->vertex] = 1;                        (*vertexNum)++;                        isTreeCore(tree, tree[node->vertex], vertexStatusArr, vertexNum);                }                node = node->next;        }}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.