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

来源:互联网 发布:unity3d人物点击行走 编辑:程序博客网 时间:2024/06/06 03:23

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

#ifndef NODE_H#define NODE_Hclass 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_Hclass 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;/**ABCDEFGH01234567             A           /   \          B     D         / \   / \        C   F  G-H         \ /          E           A        /  |  \       B---F---E        \  /\ /          C--DABCDEF012345A-B 6   A-E 5   A-F 1B-C 3   B-F 2C-F 8   C-D 7D-F 4   D-E 2E-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;}

0 0
原创粉丝点击