C++实现Prim与Kruskal最小生成树算法

C++实现Prim与Kruskal最小生成树算法

Edge.h

#ifndef EDGE_H
#define EDGE_H

#include <iostream>

using namespace std;

class Edge
{
public:
    Edge(int nodeIndexA = 0, int nodeIndexB = 0, int weightValue = 0);
    ~Edge();
    int m_iNodeIndexA;
    int m_iNodeIndexB;
    int m_iWeightValue;
    bool m_bSelected;


};

Edge::Edge(int nodeIndexA, int nodeIndexB, int weightValue)
{
    m_iNodeIndexA = nodeIndexA;
    m_iNodeIndexB = nodeIndexB;
    m_iWeightValue = weightValue;
    m_bSelected = false;
}

Edge::~Edge()
{
}



#endif // !EDGE_H

Node.h

#ifndef NODE_H
#define NODE_H

class Node
{
public:
    Node(char data = 0);
    char m_cData;
    bool m_bIsVisited;

};

Node::Node(char data)
{
    m_cData = data;
    m_bIsVisited = false;
}



#endif // !NODE_H

CMap.h

#ifndef CMAP_H
#define CMAP_H
#include <iostream>
#include <vector>
#include <cstring>
#include "Node.h"
#include "Edge.h"

using namespace std;

class CMap
{
public:
    CMap(int capacity);
    ~CMap();
    bool addNode(Node *pNode);                      //向图中加入顶点(结点)
    void resetNode();                               //重置顶点
    bool setValueToMatrixForDirectedGraph(int row, int col, int val = 1);       //为有向图设置邻接矩阵
    bool setValueToMatrixforUndirectedGraph(int row, int col, int val = 1);     //为无向图设置邻接矩阵

    void printMatrix();                             //打印邻接矩阵

    void depthFirstTraverse(int nodeIndex);         //深度优先遍历
    void breadthFirstTraverse(int nodeIndex);       //广度优先遍历

    void primTree(int nodeIndex);                   //普里姆生成树
    void kruskalTree();                             //

private:
    bool getValueFromMatrix(int row, int col, int &val);        //从矩阵中获取权值
    void breadthFristTraverseImpl(vector<int> preVec);          //广度优先遍历实现函数

    int getMinEdge(vector<Edge> edgeVec);                       //获取最小边
    bool isInSet(vector<int> &nodeSet, int target);             //判断顶点是否在点集合中
    void mergeNodeSet(vector<int> &nodeSetA, vector<int> nodeSetB);     //合并两个顶点集合


private:
    int m_iCapacity;                //图中最多可以容纳的顶点数
    int m_iNodeCount;               //已经添加的顶点(结点)的个数 (索引)
    Node *m_pNodeArray;             //用来存放顶点数组
    int *m_pMatrix;                 //用来存放邻接矩阵

    Edge *m_pEdge;
};

CMap::CMap(int capacity)
{
    m_iCapacity = capacity;
    m_iNodeCount = 0;
    m_pNodeArray = new Node[m_iCapacity];
    m_pMatrix = new int[m_iCapacity*m_iCapacity];
    memset(m_pMatrix, 0, m_iCapacity*m_iCapacity*sizeof(int) );

    m_pEdge = new Edge[m_iCapacity - 1];
}

CMap::~CMap()
{
    delete[]m_pNodeArray;
    delete[]m_pMatrix;
    delete[]m_pEdge;
}

bool CMap::addNode(Node *pNode)
{
    if (pNode == NULL)
    {
        return false;
    }
    m_pNodeArray[m_iNodeCount].m_cData = pNode->m_cData;
    m_iNodeCount++;
    return true;
}

void CMap::resetNode()
{
    for (int i = 0; i < m_iNodeCount; i++)
    {
        m_pNodeArray[i].m_bIsVisited = false;
    }
}

bool CMap::setValueToMatrixForDirectedGraph(int row, int col, int val)
{
    if (row < 0 || row >= m_iCapacity)
    {
        return false;
    }
    if (col < 0 || col >= m_iCapacity)
    {
        return false;
    }
    m_pMatrix[row * m_iCapacity + col] = val;
    return true;
}

bool CMap::setValueToMatrixforUndirectedGraph(int row, int col, int val)
{
    if (row < 0 || row >= m_iCapacity)
    {
        return false;
    }
    if (col < 0 || col >= m_iCapacity)
    {
        return false;
    }
    m_pMatrix[row * m_iCapacity + col] = val;
    m_pMatrix[col * m_iCapacity + row] = val;
    return true;
}

void CMap::printMatrix()
{
    for (int i = 0; i < m_iCapacity; i++)
    {
        for (int j = 0; j < m_iCapacity; j++)
        {
            cout << m_pMatrix[i * m_iCapacity + j] << " ";
        }
        cout << endl;
    }
}

void CMap::depthFirstTraverse(int nodeIndex)
{
    int value = 0;
    cout << m_pNodeArray[nodeIndex].m_cData << " ";
    m_pNodeArray[nodeIndex].m_bIsVisited = true;

    for (int i = 0; i < m_iCapacity; i++)
    {
        getValueFromMatrix(nodeIndex, i, value);
        if (value != 0)
        {
            if (m_pNodeArray[i].m_bIsVisited)
            {
                continue;
            }
            else
            {
                depthFirstTraverse(i);
            }
        }
        else
        {
            continue; 
        }
    }
}

void CMap::breadthFirstTraverse(int nodeIndex)
{
    cout << m_pNodeArray[nodeIndex].m_cData << " ";
    m_pNodeArray[nodeIndex].m_bIsVisited = true;

    vector<int> curVec;
    curVec.push_back(nodeIndex);

    breadthFristTraverseImpl(curVec);
}

void CMap::breadthFristTraverseImpl(vector<int> preVec)
{
    int value = 0;
    vector<int> curVec;
    for (int i = 0; i < (int)preVec.size(); i++)
    {
        for (int j = 0; j < m_iCapacity; j++)
        {
            getValueFromMatrix(preVec[i], j, value);
            if (value != 0)
            {
                if (m_pNodeArray[j].m_bIsVisited)
                {
                    continue;
                }
                else
                {
                    cout << m_pNodeArray[j].m_cData << " ";
                    m_pNodeArray[j].m_bIsVisited = true;

                    curVec.push_back(j);
                }
            }
            else
            {
                continue;
            }
        }
    }

    if (curVec.size() == 0)
    {
        return;
    }
    else
    {
        breadthFristTraverseImpl(curVec);
    }
}

bool CMap::getValueFromMatrix(int row, int col, int &val)
{
    if (row < 0 || row >= m_iCapacity)
    {
        return false;
    }
    if (col < 0 || col >= m_iCapacity)
    {
        return false;
    }
    val = m_pMatrix[row*m_iCapacity + col];
    return true;
}


void CMap::primTree(int nodeIndex)
{
    int value = 0;
    int edgeCount = 0;
    vector<int> nodeVec;
    vector<Edge> edgeVec;

    cout << endl;
    cout << m_pNodeArray[nodeIndex].m_cData << endl;

    nodeVec.push_back(nodeIndex); 
    m_pNodeArray[nodeIndex].m_bIsVisited = true;

    while (edgeCount < m_iCapacity - 1)
    {
        int temp = nodeVec.back();
        for (int i = 0; i < m_iCapacity; i++)
        {
            getValueFromMatrix(temp, i, value);
            if (value != 0)
            {
                if (m_pNodeArray[i].m_bIsVisited)
                {
                    continue;
                }
                else
                {
                    Edge edge(temp, i, value);
                    edgeVec.push_back(edge);
                }
            }
        }

        //从可选便集合(edgeVec)中找出最小的边
        int edgeIndex = getMinEdge(edgeVec);
        edgeVec[edgeIndex].m_bSelected = true;

        cout << edgeVec[edgeIndex].m_iNodeIndexA << "--" << edgeVec[edgeIndex].m_iNodeIndexB << " " << edgeVec[edgeIndex].m_iWeightValue << endl;


        m_pEdge[edgeCount] = edgeVec[edgeIndex];
        edgeCount++;

        int nextNodeIndex = edgeVec[edgeIndex].m_iNodeIndexB;
        //nodeIndex = nextNodeIndex;
        nodeVec.push_back(nextNodeIndex);
        m_pNodeArray[nextNodeIndex].m_bIsVisited = true;
        cout << m_pNodeArray[nextNodeIndex].m_cData << endl;

    }
}

int CMap::getMinEdge(vector<Edge> edgeVec)
{
    int minWeight = 0;
    int edgeIndex = 0;
    int i = 0;
    for (; i < (int)edgeVec.size(); i++)
    {
        if (!edgeVec[i].m_bSelected)
        {
            minWeight = edgeVec[i].m_iWeightValue;
            edgeIndex = i;
            break;
        }
    }
    if (minWeight == 0)
        {
            return -1;
        }
    for (; i < (int)edgeVec.size(); i++)
    {
        if (edgeVec[i].m_bSelected)
        {
            continue; 
        }
        if (minWeight > edgeVec[i].m_iWeightValue)
        {
            minWeight = edgeVec[i].m_iWeightValue;
            edgeIndex = i;
        }
    }

    return edgeIndex;
}

void CMap::kruskalTree()
{
    int value = 0;
    int edgeCount = 0;

    //定义存放结点集合的数组
    vector< vector<int> > nodeSets;

    //第一步:取出所有的边
    vector<Edge> edgeVec;
    for (int i = 0; i < m_iCapacity; i++)
    {
        for (int j = i + 1; j < m_iCapacity ; j++)
        {
            getValueFromMatrix(i, j, value);
            if (value != 0)
            {
                Edge edge(i, j, value);
                edgeVec.push_back(edge);
            }
        }
    }

    //第二步:从所有边中取出组成最小生成树的边
    //1.找到算法结束条件
    while (edgeCount < m_iCapacity - 1)
    {
        //2.从边集合中找到最小边
        int minEdgeIndex = getMinEdge(edgeVec);
        edgeVec[minEdgeIndex].m_bSelected = true;

        //3.找出最小边连接的点
        int nodeAIndex = edgeVec[minEdgeIndex].m_iNodeIndexA;
        int nodeBIndex = edgeVec[minEdgeIndex].m_iNodeIndexB;

        //4.找出点所在的点的集合
        bool nodeAIsInSet = false;
        bool nodeBIsInSet = false;

        int nodeAInSetLabel = -1;
        int nodeBInSetLabel = -1;
        for (int i = 0; i < (int)nodeSets.size(); i++)
        {
            nodeAIsInSet = isInSet(nodeSets[i], nodeAIndex);
            if (nodeAIsInSet)
            {
                nodeAInSetLabel = i;
            }
        }
        for (int i = 0; i < (int)nodeSets.size(); i++)
        {
            nodeBIsInSet = isInSet(nodeSets[i], nodeBIndex);
            if (nodeBIsInSet)
            {
                nodeBInSetLabel = i;
            }
        }
        //5.根据点所在集合的不同做出不同的处理
        if (nodeAInSetLabel == -1 && nodeBInSetLabel == -1)
        {
            vector<int> vec;
            vec.push_back(nodeAIndex);
            vec.push_back(nodeBIndex);

            nodeSets.push_back(vec);
        }
        else if (nodeAInSetLabel == -1 && nodeBInSetLabel != -1)
        {
            nodeSets[nodeBInSetLabel].push_back(nodeAIndex);
        }
        else if (nodeAInSetLabel != -1 && nodeBInSetLabel == -1)
        {
            nodeSets[nodeAInSetLabel].push_back(nodeBIndex);
        }
        else if (nodeAInSetLabel != -1 && nodeBInSetLabel != -1 && nodeAInSetLabel != nodeBInSetLabel)
        {
            mergeNodeSet(nodeSets[nodeAInSetLabel], nodeSets[nodeBInSetLabel]);
            for (int i = nodeBInSetLabel; i < (int)nodeSets.size() - 1; i++)
            {
                nodeSets[i] = nodeSets[i + 1];
            }
        }
        else if (nodeAInSetLabel != -1 && nodeBInSetLabel != -1 && nodeAInSetLabel == nodeBInSetLabel)
        {
            continue;
        }

        m_pEdge[edgeCount] = edgeVec[minEdgeIndex];
        edgeCount++;

        cout << edgeVec[minEdgeIndex].m_iNodeIndexA << "---" << edgeVec[minEdgeIndex].m_iNodeIndexB << " " << edgeVec[minEdgeIndex].m_iWeightValue << endl;

    }
}

bool CMap::isInSet(vector<int> &nodeSet, int target)
{
    for (int i = 0; i < (int)nodeSet.size(); i++)
    {
        if (nodeSet[i] == target)
        {
            return true;
        }
    }
    return false;

}
void CMap::mergeNodeSet(vector<int> &nodeSetA, vector<int> nodeSetB)
{
    for (int i = 0; i < (int)nodeSetB.size(); i++)
    {
        nodeSetA.push_back(nodeSetB[i]);
    }
}



#endif // !CMAP_H

main.cpp

#include "CMap.h"
#include "Node.h"
#include <stdlib.h>


int main()
{
    CMap *pMap = new CMap(6);

    Node *e1 = new Node('A');
    Node *e2 = new Node('B');
    Node *e3 = new Node('C');
    Node *e4 = new Node('D');
    Node *e5 = new Node('E');
    Node *e6 = new Node('F');

    pMap->addNode(e1);
    pMap->addNode(e2);
    pMap->addNode(e3);
    pMap->addNode(e4);
    pMap->addNode(e5);
    pMap->addNode(e6);


    pMap->setValueToMatrixforUndirectedGraph(0, 1, 6);
    pMap->setValueToMatrixforUndirectedGraph(0, 4, 5);
    pMap->setValueToMatrixforUndirectedGraph(0, 5, 1);
    pMap->setValueToMatrixforUndirectedGraph(1, 2, 3);
    pMap->setValueToMatrixforUndirectedGraph(1, 5, 2);
    pMap->setValueToMatrixforUndirectedGraph(2, 5, 8);
    pMap->setValueToMatrixforUndirectedGraph(2, 3, 7);
    pMap->setValueToMatrixforUndirectedGraph(3, 5, 4);
    pMap->setValueToMatrixforUndirectedGraph(3, 4, 2);
    pMap->setValueToMatrixforUndirectedGraph(4, 5, 9);



    pMap->printMatrix();

    cout << endl;

    pMap->depthFirstTraverse(0);

    cout << endl;
    pMap->resetNode();
    pMap->breadthFirstTraverse(0);

    cout << endl;

    pMap->resetNode();

    pMap->primTree(0);

    cout << endl;

    pMap->kruskalTree();

    system("pause");
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值