C++图的操作
来源:互联网 发布:还珠之我是知画 编辑:程序博客网 时间:2024/06/05 17:05
经过漫长的学习,终于对图的结构、表示和遍历及其最小生成树等一系列图相关的操作有了一些理解,因此现在写这篇博客,希望会对大家有用,我们的图是通过邻接矩阵实现的。
Node.h
#ifndef NODE_H#define NODE_Hclass Node{public: Node(char data = 0); char m_data; bool m_isVisited;};#endif
Edge.h
#ifndef EDGE_H#define EDGE_Hclass Edge{public: Edge(int nodeIndexA = 0, int nodexIndexB = 0, int weightValue = 0); int m_nodeIndexA; int m_nodeIndexB; int m_weightValue; bool m_selected;};#endif
CMap.h
#ifndef CMAP_H#define CMAP_H#include <vector>#include "Node.h"#include "Edge.h"using namespace std;class CMap{public: CMap(int capacity); ~CMap(); bool addNode(Node* node); void resetNode(); bool setValueToMatrixForDirectedGraph(int row, int col, int value = 1);//为有向图设置邻接矩阵 bool setValueToMatrixForUndirectedGraph(int row, int col, int value = 1);//为无向图设置邻接矩阵 void printMatrix();//打印邻接矩阵 //遍历 void depthFirstTraverse(int nodeIndex); void breadthFirstTraverse(int nodeIndex); void depthFirstTraverse_self(int nodeIndex); void primTree(int nodeIndex);//最小生成树 void kruskalTree();private: int m_capacity;//图中最多容纳的顶点数 int m_iNodeCount;//已经添加的顶点的数目 Node* m_pNodeArray;//存放顶点数组 int* m_pMatrix;//存放二维数组矩阵,用来表示顶点之间的边的关系 bool getValueFromMatrix(int row, int col, int& val);//从矩阵中获取权值 int getMinEdge(vector<Edge> edgeVec); void mergeNodeSet(vector<int> &nodeSetA,vector<int> nodeSetB); bool isInset(vector<int> nodeSet,int target); //申明一个边的集合用来保存最小生成树的边 Edge* m_edge;};#endif
Node.cpp
#include <iostream>#include "Node.h"using namespace std;Node::Node(char data){ m_data = data; m_isVisited = false;}
Edge.cpp
#include "Edge.h"Edge::Edge(int nodeIndexA, int nodeIndexB, int weightValue){ m_nodeIndexA = nodeIndexA; m_nodeIndexB = nodeIndexB; m_weightValue = weightValue; m_selected = false;}
CMap.cpp
#include <iostream>#include "CMap.h"#include <queue>using namespace std;CMap::CMap(int capacity){ m_capacity = capacity; m_iNodeCount = 0; m_pNodeArray = new Node[m_capacity]; m_pMatrix = new int[m_capacity*m_capacity]; memset(m_pMatrix, 0, m_capacity*m_capacity*sizeof(int)); //生成最小生成树的边 m_edge = new Edge[m_capacity - 1];}CMap::~CMap(){ delete[] m_pNodeArray; delete[] m_pMatrix; delete[] m_edge;}bool CMap::addNode(Node* node){ m_pNodeArray[m_iNodeCount].m_data = node->m_data; m_iNodeCount++; return true;}void CMap::resetNode(){ for (int i = 0; i < m_iNodeCount; i++){ m_pNodeArray[i].m_isVisited = false; }}bool CMap::setValueToMatrixForDirectedGraph(int row, int col, int value){ if (row < 0 && row >= m_capacity) return false; if (col < 0 && col >= m_capacity) return false; m_pMatrix[row*m_capacity + col] = value; return true;}bool CMap::setValueToMatrixForUndirectedGraph(int row, int col, int value){ if (row < 0 && row >= m_capacity) return false; if (col < 0 && col >= m_capacity) return false; m_pMatrix[row*m_capacity + col] = value; m_pMatrix[col*m_capacity + row] = value; return true;}void CMap::printMatrix(){ for (int i = 0; i < m_capacity; i++){ for (int j = 0; j < m_capacity; j++){ cout<<m_pMatrix[i*m_capacity + j]<<" "; } cout << endl; }}//遍历void CMap::depthFirstTraverse(int nodeIndex){ int value = 0; cout << m_pNodeArray[nodeIndex].m_data << " "; m_pNodeArray[nodeIndex].m_isVisited = true; for (int i = 0; i < m_capacity; i++){ //判断从当前节点到其他顶点c是否存在边或者弧 getValueFromMatrix(nodeIndex, i, value); if (value == 1){ if (m_pNodeArray[i].m_isVisited){ continue; } else{ depthFirstTraverse(i); } } else{ continue; } }}void CMap::depthFirstTraverse_self(int nodeIndex){ int value = 0; cout << m_pNodeArray[nodeIndex].m_data << " "; m_pNodeArray[nodeIndex].m_isVisited = true; for (int i = 0; i < m_capacity; i++){ getValueFromMatrix(nodeIndex, i, value); if (value !=0){ if (m_pNodeArray[i].m_isVisited == false){ depthFirstTraverse_self(i); } } }}void CMap::breadthFirstTraverse(int nodeIndex){ int value = 0; int temp = NULL; queue<int> queue; Node firstNode = NULL; queue.push(nodeIndex); m_pNodeArray[nodeIndex].m_isVisited = true; while (!queue.empty()){ temp = queue.front(); firstNode = m_pNodeArray[temp]; cout << firstNode.m_data << " "; queue.pop(); for (int i = 0; i < m_capacity; i++){ getValueFromMatrix(temp, i, value); if (value != 0){ if (m_pNodeArray[i].m_isVisited == false){ queue.push(i); m_pNodeArray[i].m_isVisited = true; } } } }}bool CMap::getValueFromMatrix(int row, int col, int& val){ if (row < 0 || row >= m_capacity){ return false; } if (col < 0 || col >= m_capacity){ return false; } val = m_pMatrix[row*m_capacity + col];}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_selected != true){ minWeight = edgeVec[i].m_weightValue; break; } } if (minWeight == 0){ return -1; } //从剩余的边中继续找,看看有没有比第一条边的值更小的边 for (; i < (int)edgeVec.size(); i++){ if (edgeVec[i].m_selected != true){ if (edgeVec[i].m_weightValue < minWeight){ minWeight = edgeVec[i].m_weightValue; edgeIndex = i; } } } return edgeIndex;}void CMap::primTree(int nodeIndex){ int value = 0; int edgeCount = 0; vector<int> nodeVec;//描述顶点的集合 vector<Edge> edgeVec;//描述边的集合 cout << m_pNodeArray[nodeIndex].m_data << endl; nodeVec.push_back(nodeIndex); m_pNodeArray[nodeIndex].m_isVisited = true; while (edgeCount < m_capacity - 1){ int temp = nodeVec.back(); int i = 0; for (; i < m_capacity; i++){ getValueFromMatrix(temp, i, value); if (value != 0){ if (m_pNodeArray[i].m_isVisited != true){ Edge edge(temp, i, value); edgeVec.push_back(edge); } } } int edgeIndex=getMinEdge(edgeVec); edgeVec[edgeIndex].m_selected = true; cout << edgeVec[edgeIndex].m_nodeIndexA << "------" << edgeVec[edgeIndex].m_nodeIndexB << " "; //将最小边放入最小生成树的边集合 m_edge[edgeCount] = edgeVec[edgeIndex]; edgeCount++; //找出最小边所连接的另一个点,并将点放入点集合 int nextNodeIndex = edgeVec[edgeIndex].m_nodeIndexB; nodeVec.push_back(nextNodeIndex); m_pNodeArray[nextNodeIndex].m_isVisited = true; cout << m_pNodeArray[nextNodeIndex].m_data << endl; }}void CMap::mergeNodeSet(vector<int> &nodeSetA, vector<int> nodeSetB){ for (int i = 0; i < nodeSetB.size(); i++){ nodeSetA.push_back(nodeSetB[i]); }}bool CMap::isInset(vector<int> nodeSet, int target){ for (int i = 0; i < nodeSet.size(); i++){ if (nodeSet[i] == target){ return true; } } return false;}void CMap::kruskalTree(){ int value = 0; int edgeCount = 0; vector<vector<int>> nodeSets; //得到所有边 vector<Edge> edgeVec; for (int i = 0; i < m_capacity; i++){ for (int j = i + 1; j < m_capacity; j++){ getValueFromMatrix(i, j, value); if (value != 0){ Edge edge(i, j, value); edgeVec.push_back(edge); } } } //从所有边中取出组成最小生成树的边 //1.找到算法结束条件 //2.找到集合中的最小边 //3.找出最小边相连的点 //4.找出点所在的点集合 //5.根据点所在集合的不同做出不同处理 while (edgeCount < m_capacity - 1){ int minEdgeIndex = getMinEdge(edgeVec); edgeVec[minEdgeIndex].m_selected = true; int nodeAIndex=0, nodeBIndex = 0; bool nodeAIsInSet = false; bool nodeBIsInset = false; nodeAIndex = edgeVec[minEdgeIndex].m_nodeIndexA; nodeBIndex = edgeVec[minEdgeIndex].m_nodeIndexB; 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; } } if (nodeAInSetLabel == -1 && nodeBInsetLabel == -1){ vector<int> vec; vec.push_back(nodeAIndex); vec.push_back(nodeBIndex); nodeSets.push_back(vec); } //A不属于任何集合,B属于某个集合 else if (nodeAInSetLabel == -1 && nodeBInsetLabel != -1){ nodeSets[nodeBInsetLabel].push_back(nodeAIndex); } else if (nodeBInsetLabel == -1 && nodeAInSetLabel != -1){ nodeSets[nodeAInSetLabel].push_back(nodeBInsetLabel); } //连接到两个集合中的不同点,需要合并两个集合 else if (nodeAInSetLabel != -1 && nodeBInsetLabel != -1 && nodeAInSetLabel != nodeBInsetLabel){ mergeNodeSet(nodeSets[nodeAInSetLabel], nodeSets[nodeBInsetLabel]); for (int j = nodeBInsetLabel; j < (int)nodeSets.size() - 1; j++){ nodeSets[j] = nodeSets[j + 1]; } } //表示形成回路 else if (nodeAInSetLabel != -1 && nodeBInsetLabel != -1 && nodeAInSetLabel == nodeBInsetLabel){ continue; } m_edge[edgeCount] = edgeVec[minEdgeIndex]; edgeCount++; cout << edgeVec[minEdgeIndex].m_nodeIndexA << "----" << edgeVec[minEdgeIndex].m_nodeIndexB << " "; cout << edgeVec[minEdgeIndex].m_weightValue << endl; }}
CMapDemo.cpp
#include <iostream>#include "CMap.h"using namespace std;int main(){ CMap* pMap = new CMap(8); 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'); Node* pNodeG = new Node('G'); Node* pNodeH = new Node('H'); pMap->addNode(pNodeA); pMap->addNode(pNodeB); pMap->addNode(pNodeC); pMap->addNode(pNodeD); pMap->addNode(pNodeE); pMap->addNode(pNodeF); pMap->addNode(pNodeG); pMap->addNode(pNodeH); pMap->setValueToMatrixForUndirectedGraph(0,1); pMap->setValueToMatrixForUndirectedGraph(0, 3); pMap->setValueToMatrixForUndirectedGraph(1, 2); pMap->setValueToMatrixForUndirectedGraph(1, 5); pMap->setValueToMatrixForUndirectedGraph(3, 6); pMap->setValueToMatrixForUndirectedGraph(3, 7); pMap->setValueToMatrixForUndirectedGraph(6, 7); pMap->setValueToMatrixForUndirectedGraph(2, 4); pMap->setValueToMatrixForUndirectedGraph(4, 5); pMap->printMatrix(); cout << "图的深度优先遍历:" << endl; pMap->depthFirstTraverse_self(0); cout << "\n换一种方法试试看:" << endl; pMap->resetNode(); pMap->depthFirstTraverse(0); pMap->resetNode(); cout << "\n图的广度优先遍历:" << endl; pMap->breadthFirstTraverse(0); cout << endl; return 0;}
CMapDemo_MiniGenerTree.cpp
#include <iostream>#include "CMap.h"using namespace std;int main(){ 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->kruskalTree(); cout << endl; return 0;}
PS:CMapDemo.cpp主要是针对图的遍历,广度深度优先进行的,CMapDemo_MiniGenerTree.cpp主要是针对图的最小生成树进行设计的,希望大家仔细品味。
CMap用到的图:
运行结果:
CMapDemo_MiniGenerTree.cpp用到的图:
运行结果:
阅读全文
0 0
- C/C++ 图的基本操作
- C的文件操作
- C的文件操作
- C的文件操作
- 单链表的操作(C#)
- C的位操作
- 注册表的操作(C#)
- c的io操作
- C 的文件操作
- C++------二进制文件的操作
- c的位操作
- C的位操作
- C的指针操作
- C的目录操作
- C++-类的操作
- C单链表的操作
- c的文本操作
- C的操作符
- VS2015动态库编程之Win32动态库的使用(中)
- linux yum命令简要记录
- 支持post,get请求(http,https)的HttpClientUtils
- Android 体系结构
- 步科触摸屏编程
- C++图的操作
- 一个Linux下c语言线程池的实现
- 如何在 SpringMVC Controller 上使用 Spring Data 的 Projection/投影?
- 如何在Github Pages搭建自己写的页面?
- tiny4412学习(四)之移植linux-设备树(2)设备树之LED点灯
- javaXML
- 1010. Radix (25)
- 电商平台的搭建(SpringMVC+SpringSecurity/Validation+Redis+MySQL+React)----购物车功能
- POJ 2919 Traveling Queen Problem 笔记