使用C++邻接矩阵实现图的存储、Prim、Kruskal算法

1、创建Node.h 定义图的顶点

#ifndef NODE_H
#define NODE_H
class Node{
public:
    Node(char data=0);
    char m_cData;
    bool m_bIsVisited;
};
#endif // NODE_H

2、创建Node.cpp 实现顶点的定义

#include "Node.h"
Node::Node(char data){
    m_cData = data;
    m_bIsVisited = false;
}
3、创建CMap.h 实现图的数据结构的定义

#ifndef CMAP_H
#define CMAP_H
#include <vector>
#include "Node.h"
#include "Edge.h"
using namespace std;
class CMap{
public:
    CMap(int campacity);
    ~CMap();
    bool addNode(Node *pNode);
    void resetNode();   //将所有顶点的访问标示设置为false
    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 breadFirstTraverse(int nodeindex);
    void primTree(int nodeindex);
    void kluskalTree();

private:
    bool getValueFromMatrix(int row,int col,int &val);
    void breadFirstTraverseImp(vector<int> preVec); //广度优先遍历实现函数
    int getMinEdge(vector<Edge> edgeVec);
    bool isInSet(vector<int> nodeSet,int target);
    void mergeNodeSet(vector<int> &nodeSetA,vector<int> nodeSetB);
    int m_iCampacity;  //图中最多可容纳的顶点的个数
    int m_iNodeCount;    //已经添加的顶点的个数
    Node *m_pNodeArray; //用来存放顶点数组
    int *m_pMatrix;     //用来存放邻接矩阵
    Edge *m_pEdgeArray;  //最小生成树选中边的集合

};
#endif // CMAP_H

4、创建CMap.cpp 实现图的定义

#include "CMap.h"
#include "Node.h"
#include "Edge.h"
#include <cstring>
#include <iostream>
using namespace std;
CMap::CMap(int campacity){
    m_iCampacity = campacity;
    m_iNodeCount = 0;
    m_pNodeArray = new Node[campacity];
    m_pMatrix = new int[m_iCampacity * m_iCampacity];
    memset(m_pMatrix,0,m_iCampacity * m_iCampacity * sizeof(int));
    m_pEdgeArray = new Edge[m_iCampacity - 1];
}
CMap::~CMap(){
    delete[] m_pNodeArray;
    delete[] m_pMatrix;
    delete[] m_pEdgeArray;
}
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_iCampacity;i++){
        m_pNodeArray[i].m_bIsVisited = false;

    }
}
/**
带有默认参数的构造函数只需在声明时指定默认参数值,定义则不必指明默认参数的值
**/
bool CMap::setValueToMatrixForDirectedGraph(int row,int col,int val){
    if(row < 0 || row >= m_iCampacity || col < 0 || col >= m_iCampacity)
        return false;
    m_pMatrix[row * m_iCampacity + col] = val;
    return true;
}
bool CMap::setValueToMatrixForUndirectedGraph(int row,int col,int val){
    if(row < 0 || row >= m_iCampacity || col < 0 || col >= m_iCampacity)
        return false;
    m_pMatrix[row * m_iCampacity + col] = val;
    m_pMatrix[col * m_iCampacity + row] = val;
    return true;
}
void CMap::printMatrix(){
    for(int i = 0; i < m_iCampacity;i++){
        for(int j = 0; j < m_iCampacity;j++){
            cout<<m_pMatrix[i * m_iCampacity + j]<<"\t";
        }
        cout<<endl;
    }
}
bool CMap::getValueFromMatrix(int row,int col,int &val){
    if(row < 0 || row >= m_iCampacity || col < 0 || col >= m_iCampacity)
        return false;
    val = m_pMatrix[row * m_iCampacity + col];
    return true;
}
void CMap::depthFirstTraverse(int nodeindex){
    cout<<m_pNodeArray[nodeindex].m_cData<<" ";
    m_pNodeArray[nodeindex].m_bIsVisited = true;
    int value = 0;
    for(int i = 0;i < m_iCampacity;i++){
        //value = m_pNodeArray[nodeindex + 1].c_Data;
        getValueFromMatrix(nodeindex,i,value);
        if(value == 1){
            if(m_pNodeArray[i].m_bIsVisited){
                continue;
            }else{
                depthFirstTraverse(i);
            }
        }else{
            continue;
        }
    }
}
void CMap::breadFirstTraverse(int nodeindex){
    if(nodeindex < 0 || nodeindex >= m_iCampacity)
        return;
    cout<<m_pNodeArray[nodeindex].m_cData<<" ";
    m_pNodeArray[nodeindex].m_bIsVisited = true;
    vector<int> curVec;
    curVec.push_back(nodeindex);
    breadFirstTraverseImp(curVec);  //传递容器参数直接传递即可
}
void CMap::breadFirstTraverseImp(vector<int> preVec){
    int value;
    vector<int> curVec;
    for(int i = 0;i < (int)preVec.size();i++){
        for(int j = 0;j < m_iCampacity;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){
        breadFirstTraverseImp(curVec);
    }
}
/**最小生成树 Prim算法相关函数**/
void CMap::primTree(int nodeindex){
    int value;
    vector<int> nodeVec;   //选中点的集合
    vector<Edge> edgeVec;  //备选边的集合
    int edgeCount = 0;
    nodeVec.push_back(nodeindex);
    m_pNodeArray[nodeindex].m_bIsVisited = true;
    cout<<m_pNodeArray[nodeindex].m_cData<<endl;
    while(edgeCount < m_iCampacity - 1){
        int temp = nodeVec.back();
        for(int i = 0;i < m_iCampacity;i++){
            getValueFromMatrix(temp,i,value);
            if(value != 0){
                if(m_pNodeArray[i].m_bIsVisited){
                    continue;
                }else{
                    Edge edge(temp,i,value); //什么时候用new,什么时候不用new,这里为什么不用
                    edgeVec.push_back(edge);
                }
            }else{
                continue;
            }
        }
        //int len = edgeVec.size();
        //从可选边集合中选出最小边
        int edgeIndex = getMinEdge(edgeVec);
        edgeVec[edgeIndex].m_bSelected = true;
        cout<<edgeVec[edgeIndex].m_iNodeA<<"----"<<edgeVec[edgeIndex].m_iNodeB;
        cout<<" weight:"<<edgeVec[edgeIndex].m_iWeightValue<<endl;
        //cout<<edgeVec[edgeIndex].m_iWeightValue<<endl;
        m_pEdgeArray[edgeCount] = edgeVec[edgeIndex];
        edgeCount++;
        int nextNodeIndex = edgeVec[edgeIndex].m_iNodeB;
        nodeVec.push_back(nextNodeIndex);
        m_pNodeArray[nextNodeIndex].m_bIsVisited = true;
        cout<<m_pNodeArray[nextNodeIndex].m_cData<<endl;

    }
}
int CMap::getMinEdge(vector<Edge> edgeVec){
    int edgeIndex = 0;
    int minWeight = 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;
        }else{
            if(edgeVec[i].m_iWeightValue < minWeight){
                minWeight = edgeVec[i].m_iWeightValue;
                edgeIndex = i;
            }
        }
    }
    return edgeIndex;
}
//最小生成树 kluskal算法
void CMap::kluskalTree(){
    int value = 0;
    int edgeCount = 0;
    //定义存放节点集合的数组
    vector< vector<int> > nodeSets;//点集合的集合
    vector<Edge> edgeVec;
    //第一步:取出所有边
    for(int i = 0;i < m_iCampacity;i++){  //轮训矩阵上三角
        for(int j = i+1;j < m_iCampacity;j++){
            getValueFromMatrix(i,j,value);
            if(value != 0){
                Edge edge(i,j,value);
                edgeVec.push_back(edge);
            }
        }
    }
    //第二步:从所有边中取出组成最小生成树的边
    //1、找到算法的结束条件
    while(edgeCount < m_iCampacity - 1){
        //2、从边集合中找到最小边
        int minEdgeIndex = getMinEdge(edgeVec);
        edgeVec[minEdgeIndex].m_bSelected = true;
        //3、找出最小边连接的点
        int nodeAIndex = edgeVec[minEdgeIndex].m_iNodeA;
        int nodeBIndex = edgeVec[minEdgeIndex].m_iNodeB;
        //4、找出点所在的集合
        bool isAInSet = false;
        bool isBInSet = false;
        int nodeAInSetLabel = -1;
        int nodeBInSetLabel = -1;
        for(int i = 0;i < (int)nodeSets.size();i++){
            isAInSet = isInSet(nodeSets[i],nodeAIndex);
            if(isAInSet){
                nodeAInSetLabel = i;
            }
        }
        for(int i = 0;i < (int)nodeSets.size();i++){
            isBInSet = isInSet(nodeSets[i],nodeBIndex);
            if(isBInSet){
                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 == nodeBInSetLabel){
            continue;
        }
        m_pEdgeArray[edgeCount] = edgeVec[minEdgeIndex];
        edgeCount++;
        cout<<edgeVec[minEdgeIndex].m_iNodeA<<"---"<<edgeVec[minEdgeIndex].m_iNodeB;
        cout<<" weight:"<<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]);
    }
}

5、如果要使用Prim和Kruskal算法构造最小生成树还要创建Edge.h 和Edge.cpp

Edge.h

#ifndef EDGE_H
#define EDGE_H
class Edge{
public:
    int m_iNodeA;
    int m_iNodeB;
    bool m_bSelected;
    Edge(int nodeA=0,int nodeB=0,int weightValue=0);
    int m_iWeightValue;


};
#endif // EDGE_H
Edge.cpp

#include "Edge.h"
Edge::Edge(int nodeA,int nodeB,int weightValue){
    m_iNodeA = nodeA;
    m_iNodeB = nodeB;
    m_iWeightValue = weightValue;
    m_bSelected = false;
}

6、创建main.cpp 检验定义的正确性

#include <iostream>
#include "CMap.h"
using namespace std;
/**
ABCDEFGH
01234567
             A
           /   \
          B     D
         / \   / \
        C   F  G-H
         \ /
          E

           A
        /  |  \
       B---F---E
        \  /\ /
          C--D
ABCDEF
012345
A-B 6   A-E 5   A-F 1
B-C 3   B-F 2
C-F 8   C-D 7
D-F 4   D-E 2
E-F 2

**/
int main()
{
    /**
    //树的基本操作检验
    CMap *cmap = new CMap(8);
    Node *node1 = new Node('A');
    Node *node2 = new Node('B');
    Node *node3 = new Node('C');
    Node *node4 = new Node('D');
    Node *node5 = new Node('E');
    Node *node6 = new Node('F');
    Node *node7 = new Node('G');
    Node *node8 = new Node('H');

    cmap->addNode(node1);
    cmap->addNode(node2);
    cmap->addNode(node3);
    cmap->addNode(node4);
    cmap->addNode(node5);
    cmap->addNode(node6);
    cmap->addNode(node7);
    cmap->addNode(node8);

    cmap->setValueToMatrixForUndirectedGraph(0,1);
    cmap->setValueToMatrixForUndirectedGraph(0,3);
    cmap->setValueToMatrixForUndirectedGraph(1,2);
    cmap->setValueToMatrixForUndirectedGraph(1,5);
    cmap->setValueToMatrixForUndirectedGraph(3,6);
    cmap->setValueToMatrixForUndirectedGraph(3,7);
    cmap->setValueToMatrixForUndirectedGraph(6,7);
    cmap->setValueToMatrixForUndirectedGraph(2,4);
    cmap->setValueToMatrixForUndirectedGraph(4,5);

    cmap->printMatrix();
    cmap->depthFirstTraverse(0);
    cout<<endl;
    cmap->resetNode();
    cout<<endl;
    cmap->breadFirstTraverse(0);**/


    //prim 算法检验
    CMap *pMap = new CMap(6);
    Node *pNodeA = new Node('A');
    Node *pNodeB = new Node('B');
    Node *pNodeC = new Node('C');
    Node *pNodeD = new Node('D');
    Node *pNodeE = new Node('E');
    Node *pNodeF = new Node('F');

    pMap->addNode(pNodeA);
    pMap->addNode(pNodeB);
    pMap->addNode(pNodeC);
    pMap->addNode(pNodeD);
    pMap->addNode(pNodeE);
    pMap->addNode(pNodeF);

    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->primTree(0);
    cout<<"------------------------------"<<endl;
    pMap->kluskalTree();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值