最小生成树(两种算法)

#ifndef MIN_TREE_H
#define MIN_TREE_H

#include
#include
#include
#include

#include"../data_struct/data_struct.h"
#include"../tool/tool_disjoint_set.h"

/// 最小生成树
/// 假设图中的顶点有n个,则生成树的边有n-1条,多一条会存在回路,少一路则不能把所有顶点联通起来,
/// 如果非要在图中加上权重,则生成树中权重最小的叫做最小生成树
class graph_min_tree
{
public:
    /// 普里姆 时间是复杂度O(n2),适合稠密图。
    static bool prim(const std::shared_ptr graph,
                     std::vector& out_weight, std::vector& out_parent)
    {
        out_weight.resize(graph->vertex.size());
        //保存父节点
        out_parent.resize(graph->vertex.size());

        //取出邻接矩阵的第一行数据,也就是取出第一个顶点并将权和边信息保存于临时数据中
        for (uint32_t i = 1; i < graph->vertex.size(); i++)
        {
            out_weight[i] = graph->matrix[0][i];
            out_parent[i] = 0;
        }

        std::vector is_visited(graph->vertex.size(), false);
        is_visited[0]=true;
        for (uint32_t i = 1; i < graph->vertex.size(); i++)
        {
            uint32_t index = i;
            int min = INT_MAX;

            for (uint32_t j = 1; j < graph->vertex.size(); j++)
            {
                //用于找出当前节点的邻接点中权值最小的未访问点
                if (out_weight[j] < min && is_visited[j] != true)
                {
                    min = out_weight[j];
                    index = j;
                }
            }

            is_visited[index] = true;

            //从最新的节点出发,将此节点的weight比较赋值
            for (uint32_t j = 0; j < graph->vertex.size(); j++)
            {
                //已当前节点为出发点,重新选择最小边
                if (is_visited[j] != true && graph->matrix[index][j] < out_weight[j])
                {
                    out_weight[j] = graph->matrix[index][j];
                    out_parent[j] = index;
                }
            }
        }

        //是否能够生成树
        for (uint32_t i = 1; i < graph->vertex.size(); i++)
        {
            if (out_weight[i] == INT_MAX)
            {
                return false;
            }
        }
        return true;
    }

    /// 克鲁斯卡尔:这篇我们看看第二种生成树的Kruskal算法
    /// 我们知道Prim算法构建生成树是从”顶点”这个角度来思考的,然后采用“贪心思想”
    /// 来一步步扩大化,最后形成整体最优解,而Kruskal算法有点意思,它是站在”边“这个角度在思考的
    /// 时间复杂度O(elog2e),适合简单图。
    static std::vector kruskal(const std::shared_ptr graph)
    {
        //优先队列,存放树中的边
        std::priority_queue smallPriorityQueue;

        //并查集
        tool_disjoint_set disjointSet(graph->vertex);

        //将对角线读入到优先队列
        for (uint32_t i = 0; i < graph->vertex.size(); i++)
        {
            for (uint32_t j = 0; j < graph->vertex.size(); j++)
            {
                //说明该边有权重
                if (i != j && graph->matrix[i][j] != INT_MAX)
                {
                    edge tmp(i, j, graph->matrix[i][j]);
                    smallPriorityQueue.emplace(tmp);
                }
            }
        }

        //最后收集到的最小生成树的边
        std::vector arr;

        //循环队列
        while (smallPriorityQueue.size() > 0)
        {
            auto edge = smallPriorityQueue.top();
            smallPriorityQueue.pop();

            std::cout<vertex.size() - 1)
            {
                break;
            }
        }

        return arr;
    }
};

#endif // MIN_TREE_H

 

你可能感兴趣的:(算法)