Kruskal最小生成树算法

15 篇文章 0 订阅
4 篇文章 0 订阅

=============

版权声明:本文为博主原创文章,未经博主允许不得转载。

Kruskal是一种简单贪心路径算法,解决连通图中最短路径问题

#include <iostream>
#include <stdio.h>
#include <windows.h>
#include <cmath>
#include <algorithm>
#include <string>
using namespace std;
/**
 **保存数据
 **查找最小边
 **判断是否产生回路
 **保存数据
 **/
int vertex_num;
int edge_num;
struct Edge
{
    int edge_from;  
    int edge_to;    
    int value;      
};

struct Graph
{
    Edge *vertex;  
    int *root;     
    int **matrix;  

} graph;

// sort
bool cmp(const Edge &a, const Edge &b)
{
    return a.value < b.value;
}

void all(int index,const int num, int max_index, bool flag[])
{
    int temp1, temp2;
    for(int i=0; i<max_index; i++)
    {
        temp1 = graph.vertex[i].edge_from;
        temp2 = graph.vertex[i].edge_to;
        if(flag[temp1] == true && flag[temp2] == true)
            continue;
        if(temp1 == index)
        {
            flag[temp1] = 1;
            graph.root[temp1] = graph.root[temp2] = num;
            all(temp2, num, max_index, flag);
        }
        else if(temp2 == index)
        {
            flag[temp2] = 1;
            graph.root[temp2] = graph.root[temp1] = num;
            all(temp1, num, max_index, flag);
        }
    }
}

// Kruskal
void Kruskal(Edge G[])
{
    int index = 0;
    for(int i=0; i<edge_num && index < vertex_num - 1; i++)
    {
        int from =  G[i].edge_from;
        int to = G[i].edge_to;
        if(graph.root[from] == -1 || graph.root[to] == -1 || graph.root[from] != graph.root[to])
        {
            bool flag[500]= {0};
            graph.vertex[index++] = G[i];
            if(graph.root[from] == -1 && graph.root[to] == -1)
                graph.root[from] = graph.root[to] = from;
            else if(graph.root[from] != -1)
                all(to, graph.root[from], index, flag);
            else if(graph.root[to] != -1)
                all(from,graph.root[to], index, flag);
        }
    }
}

int find_array(string s[],string str,int index)
{
    for(int i=0; i<index; i++)
        if(s[i] == str)
            return i;
    return -1;
}

int main()
{
    printf("案例:\n7 12\nA B 12\nB C 10\nC D 3\nD E 4\nE F 2\nF G 9\nG A 14\nA F 16\nB F 7\nC F 6\nE G 8\nC E 5\n");
    printf("请输入顶点的个数:\n");
    scanf("%d", &vertex_num);
    int k = 0, temp;
    string *str = new string[vertex_num];
    graph.vertex = new Edge[vertex_num - 1];
    graph.root = new int [vertex_num];
    graph.matrix = new int *[vertex_num];
    for(int i=0; i<vertex_num; i++)
    {
        graph.matrix[i] = new int [vertex_num];
        for(int j=0; j<vertex_num; j++)
            graph.matrix[i][j] = -1;
        graph.root[i] = -1;
    }

    Edge *edge;
    printf("请输入边的个数:\n");
    scanf("%d", &edge_num);
    edge = new Edge[edge_num];

    printf("请以\"结点A 结点B 权值\"的格式输入\n其中结点,权值为正整数\n");
    for(int i=0; i<edge_num; i++)
    {
        string a,b;
        cin >> a >> b;
        temp = find_array(str, a, k);
        if(temp != -1)
            edge[i].edge_from = temp;
        else
        {
            str[k] = a;
            edge[i].edge_from = k++;
        }

        temp = find_array(str, b, k);
        if(temp != -1)
            edge[i].edge_to = temp;
        else
        {
            str[k] = b;
            edge[i].edge_to = k++;
        }

        cin >> edge[i].value;
        graph.matrix[edge[i].edge_from][edge[i].edge_to] = edge[i].value;
        graph.matrix[edge[i].edge_to][edge[i].edge_from] = edge[i].value;
    }
    sort(edge, edge + edge_num, cmp);

    Kruskal(edge);

    printf("邻接矩阵:\n");
    for(int i=0; i<vertex_num; i++)
    {
        for(int j=0; j<vertex_num; j++)
            printf("%5d", graph.matrix[i][j]);
        cout << endl;
    }

    printf("\n最小生成树:\n");
    for(int i=0; i<vertex_num-1; i++)
    {
        cout << "<" << str[graph.vertex[i].edge_from] << "," << str[graph.vertex[i].edge_to] << ">" << endl;
    }
    delete[] str;
    delete[] graph.matrix;
    for(int i=0; i<vertex_num; i++)
        delete[] graph.matrix[i];
    delete[] edge;
    system("pause");
    return 0;
}

=============

版权声明:本文为博主原创文章,未经博主允许不得转载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值