使用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_HEdge.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
- 使用C++邻接矩阵实现图的存储、Prim、Kruskal算法
- 图邻接矩阵存储 最小生成树 prim普里姆算法 C语言实现
- 基于邻接矩阵的Prim算法(C语言实现)
- Prim算法的C语言实现(邻接矩阵)
- 用有向图的邻接矩阵存储结构实现prim算法
- 邻接矩阵实现prim算法
- 图的邻接矩阵实现(包括PRIM和DIJKSTRA算法)
- (c++)数据结构与算法之图:邻接矩阵、深度广度遍历、构造最小生成树(prim、kruskal算法)
- Kruskal算法之邻接矩阵实现
- 图论--Prim算法---邻接矩阵实现
- Prim算法之邻接矩阵实现
- 最小生成树问题中Kruskal算法和Prim算法的C语言实现
- 图的算法DFS、BFS、Prim、Kruskal
- Prim算法和Kruskal算法的基本思想和实现
- 图的邻接矩阵存储实现
- 最小生成树 prim算法实现(利用图的邻接矩阵来存放图)
- 图的邻接矩阵存储(C语言实现)
- c语言实现图的基本操作--邻接矩阵存储
- [ 备战NOIP2016 ] 字符串匹配 - 哈希
- 1.jdbc相较于mybatis,hibernate的一些缺点
- extern "c"用法解析
- android 控件动画效果实现
- 学习笔记_多线程
- 使用C++邻接矩阵实现图的存储、Prim、Kruskal算法
- 学习笔记_ThreadLocal
- mybatis问题org.apache.ibatis.binding.BindingException: Parameter 'loginId' not found.
- uva10288(数学期望)
- 利用社交关系提升个性化排序效果
- 学习笔记_进程 vs. 线程
- 对于python setup.py install安装的包如何卸载
- 年轻人如何做科研
- 学习笔记_分布式进程