有向图和无向图的数组C++实现
源码:https://github.com/cjy513203427/C_Program_Base/tree/master/55.%E5%9B%BE
结点类Noded.h
不需要存储索引
#pragma once
#ifndef NODE_H
#define NODE_H
#include<iostream>
using namespace std; class Node
{
public:
Node(char data = );
char m_cData;
bool m_IsVisited;
}; #endif // !NODE_H
Node.cpp
将数据赋值给数据成员m_cData,是否访问置为否
#include"Node.h" Node::Node(char data)
{
m_cData = data;
m_IsVisited = false;
}
需要实现的方法
图类cMap.h
#pragma once
#ifndef CMAP_H
#define CMAP_H
#include"Node.h"
#include<vector>
class cMap
{
public:
cMap(int capacity);
~cMap();
bool addNode(Node *pNode);//向图中加入顶点(结点)
void resetNode();//重置顶点
bool setValueToMatrixForDirectedGraph(int row, int col, int val = );//为有向图设置邻接矩阵
bool setValueToMatrixForUndirectedGraph(int row, int col, int val = );//为无向图设置邻接矩阵 void printMatrix();//打印邻接矩阵 void depthFirstTraverse(int nodeIndex);//深度优先遍历
void breadthFirstTraverse(int nodeIndex);//广度优先遍历
void breathFirstTraverseImpl(vector<int> preVec); private:
bool getValueFromMatrix(int row,int col,int &val);//从矩阵中获取权值
void breathFirstTraverse(int nodeIndex);//广度优先遍历实现函数 private:
int m_iCapacity;//图中最多可以容纳的顶点数
int m_iNodeCount;//已经添加的结点(顶点)个数
Node *m_pNodeArray;//用来存放顶点数组
int *m_pMatrix;//用来存放邻接矩阵
}; #endif // !CMAP_H
构造函数:
传入图容量参数给数据成员m_iCapacity
已经添加的结点数m_iNodeCount置为0
为顶点数组申请内存
申请m_iCapacity*m_iCapacity的矩阵
将矩阵元素全部置为0
cMap::cMap(int capacity)
{
m_iCapacity = capacity;
m_iNodeCount = ;
m_pNodeArray = new Node[m_iCapacity];
m_pMatrix = new int[m_iCapacity*m_iCapacity];
for (int i = ; i < m_iCapacity*m_iCapacity; i++)
{
m_pMatrix[i] = ;
}
}
析构函数
删除顶点数组指针
删除邻接矩阵指针
cMap::~cMap()
{
delete []m_pNodeArray;
delete []m_pMatrix;
}
添加结点
判断传入的pNode参数是否为空,如果pNode为空,返回错误
将pNode的数据部分m_cData传入到以已经添加的结点个数为索引的顶点数组
已经添加结点个数++
返回正确结果
bool cMap::addNode(Node *pNode)
{
if (pNode == NULL)
{
return false;
}
m_pNodeArray[m_iNodeCount].m_cData = pNode->m_cData;
m_iNodeCount++;
return true;
}
重置结点
将已经添加的结点的m_IsVisited置为未访问
void cMap::resetNode()
{
for (int i = ; i < m_iNodeCount; i++)
{
m_pNodeArray[i].m_IsVisited = false;
}
}
为有向图设置邻接矩阵
判断行列的合法性
如果行小于0,行大于等于最大容量,返回错误
如果列小于0,列大于等于最大容量,返回错误
图如下:

上图的邻接矩阵如下:

以(A,B)即(0,1),0行1列,0*8+1=1。
满足row*m_iCapacity计算的索引
bool cMap::setValueToMatrixForDirectedGraph(int row, int col, int val)
{
if(row< || row>=m_iCapacity)
{
return false;
}
if (col < || col >= m_iCapacity)
{
return false;
}
m_pMatrix[row*m_iCapacity + col] = val;
return true;
}
为无向图设置邻接矩阵
逻辑同上
col*m_iCapacity和row*m_iCapacity+col与主对角线成轴对称
bool cMap::setValueToMatrixForUndirectedGraph(int row, int col, int val)
{
if (row< || row >= m_iCapacity)
{
return false;
}
if (col < || col >= m_iCapacity)
{
return false;
}
m_pMatrix[row*m_iCapacity + col] = val;
m_pMatrix[col*m_iCapacity + row] = val;
}
从矩阵中获取权值
先判断行和列的合法性
行不能小于0,不能大于等于容量
列不能小于0,不能大于等于容量
获取当前索引的邻接矩阵,赋值给变量返回
返回正确结果
bool cMap::getValueFromMatrix(int row, int col, int &val)
{
if (row< || row >= m_iCapacity)
{
return false;
}
if (col < || col >= m_iCapacity)
{
return false;
}
val = m_pMatrix[row*m_iCapacity+col];
return true;
}
打印邻接矩阵
矩阵,用两层循环遍历
i是row,k就是col
void cMap::printMatrix()
{
for (int i=;i<m_iCapacity;i++)
{
for (int k = ; k<m_iCapacity; k++)
{
cout << m_pMatrix[i*m_iCapacity + k] << " ";
}
cout << endl;
}
}
深度优先遍历
深度优先遍历相当于树的前序遍历
先直接输出当前指定索引的邻接矩阵的结点
讲m_IsVisited置为未访问
按序获取获取矩阵权值
如果权值不等于1,跳过本次循环

如果权值等于1,结点已访问,跳过本次循环,这里是无向图,这里判断结点是否访问是因为邻接矩阵的权值1成主对角线对称,防止A-B访问,再访问B-A的情况出现
如果未访问,进入递归,进入方法前两行,将结点输出,以此类推
看懂过程要打断点
void cMap::depthFirstTraverse(int nodeIndex)
{
int value = ;
cout << m_pNodeArray[nodeIndex].m_cData<<" ";
m_pNodeArray[nodeIndex].m_IsVisited = true; for (int i = ; i < m_iCapacity; i++)
{
getValueFromMatrix(nodeIndex,i,value);
if (value == )
{
if (m_pNodeArray[i].m_IsVisited == true)
{
continue;
}
else
{
depthFirstTraverse(i);
}
}
else
{
continue;
}
}
}
广度优先遍历
广度优先遍历相当于按层次的树的前序遍历
思路:将上层结点放到一个vector里,该结点的下层结点再放到一个vector里
void cMap::breadthFirstTraverse(int nodeIndex)
{
cout << m_pNodeArray[nodeIndex].m_cData<<" ";
m_pNodeArray[nodeIndex].m_IsVisited = true; vector<int> currentVec;
currentVec.push_back(nodeIndex); breathFirstTraverseImpl(currentVec);
} void cMap::breathFirstTraverseImpl(vector<int> preVec)
{
int value = ;
vector<int> curVec; for (int j = ; j < (int)preVec.size(); j++)
{
for (int i = ; i < m_iNodeCount; i++)
{
getValueFromMatrix(preVec[j],i,value);
if (value != )
{
if (m_pNodeArray[i].m_IsVisited)
{
continue;
}
else
{
cout << m_pNodeArray[i].m_cData << " ";
m_pNodeArray[i].m_IsVisited = true; curVec.push_back(i);
}
}
}
}
if (curVec.size() == )
{
return;
}
else
{
breathFirstTraverseImpl(curVec);
}
}
有向图和无向图的数组C++实现的更多相关文章
- 概率图模型之有向图与无向图之间的关系 I map D map perfect map(完美图) 概念
我们已经讨论了有向图和无向图框架下的概率模型,那么我们有必要讨论一下它们二者的关系.
- 图论 Make Unique:有向图和无向图的一些算法
计算机科学入门资料之一的<算法与数据结构-C语言版>,覆盖了基础算法的几乎所有分支,其中的一个典型分支为图理论. 一个简介:图论基础-图数据结构基础 一个简洁的博客:图论基础,简列一本书 ...
- tarjan——有向图、无向图
强连通块只存在于有向无环图DAG中 实际上low[i]的理解是:一个强连通块在dfs搜索树中子树的根节点 //把一个点当成根提溜出来,抖搂抖搂成一棵树 void dfs(int u) { //记录df ...
- 有向图与无向图的合并操作区别D(递归与并查集)
有向图的合并,典型问题:通知小弟(信息只能单向传播)https://www.nowcoder.com/acm/contest/76/E 无向图的合并,典型问题:修道路问题 由于无向图只要二者有联系即可 ...
- WBS任务分解中前置任务闭环回路检测:有向图的简单应用(C#)
1 场景描述 系统中用到了进度计划编制功能,支持从project文件直接导入数据,并能够在系统中对wbs任务进行增.删.改操作.wbs任务分解中一个重要的概念就是前置任务,前置任务设置确定了不同任务项 ...
- Java数据结构和算法(十五)——无权无向图
前面我们介绍了树这种数据结构,树是由n(n>0)个有限节点通过连接它们的边组成一个具有层次关系的集合,把它叫做“树”是因为它看起来像一棵倒挂的树,包括二叉树.红黑树.2-3-4树.堆等各种不同的 ...
- 有向网络(带权的有向图)的最短路径Dijkstra算法
什么是最短路径? 单源最短路径(所谓单源最短路径就是只指定一个顶点,最短路径是指其他顶点和这个顶点之间的路径的权值的最小值) 什么是最短路径问题? 给定一带权图,图中每条边的权值是非负的,代表着两顶点 ...
- UVA 1660 Cable TV Network 电视网络(无向图,点连通度,最大流)
题意:给一个无向图,求其点连通度?(注意输入问题) 思路: 如果只有1个点,那么输出“1”: 如果有0条边,那么输出“0”: 其他情况:用最大流解决.下面讲如何建图: 图的连通度问题是指:在图中删去部 ...
- POJ2186(有向图缩点)
Popular Cows Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 28379 Accepted: 11488 De ...
随机推荐
- ArcGIS应用——使用Python为图斑连续编号及扩展应用
为图斑连续编号 在GIS应用中,为图斑连续编号(编号递增)是一项常见的需求,利用ArcGIS,可以方便的实现. Python脚本如下: rec=0 def autoIncrement(): globa ...
- Verilog HDL VGA Driver for Xilinx Nexys 4 适用于Nexys4的VGA驱动
/* * Function: VGA Timing Generator * Author: Liutianchen * Date: 2016-12-5 * Version: 6.0 * Environ ...
- 利用Trace.WriteLine定位难以重现的问题
最近的一个项目中,在客户测试环境(UAT)发现了一个bug,却反复尝试都无法在开发环境和QA环境来重现.界面上也没有出现任何异常和错误,只是某个数据的显示错误,其他数据都正常.仔细分析和调试了出错位置 ...
- How can i use iptables on centos 7 or fedora?
http://stackoverflow.com/questions/24756240/how-can-i-use-iptables-on-centos-7 # sudo service iptabl ...
- C#反射(转载)
转载原文出处忘了,一直保存在本地(勿怪) 前期准备 在VS2012中新建一个控制台应用程序(我的命名是ReflectionStudy),这个项目是基于.net 4.0.接着我们打开Program.cs ...
- select2 模糊查询远程数据
详细:http://www.cnblogs.com/linJie1930906722/p/6060370.html $("#name").select2({ language: & ...
- 关于C#低版本升级高版本时,项目中引用Microsoft.Office.Interop.Word,程序提示不存在类型或命名空间名office.
Report.cs里using Microsoft.Office.Interop.Word;就会报错:编译器错误消息: CS0234: 命名空间“Microsoft.Office”中不存在类型或命名空 ...
- [ActionSprit 3.0] FMS服务器带宽检测
package { import flash.display.Sprite; import flash.net.NetConnection; import flash.events.NetStatus ...
- 使用 final 关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?
使用 final 关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的.例如,对于如下语句:final StringBuffer a=new StringBuffer( ...
- uC/OS-II 函数之邮箱管理相关函数
上文主要介绍了消息队列相关的函数,本文介绍邮箱管理相关的函数:OSMboxCreate()建立一个邮箱,OSMboxDel()删除一个邮箱,OSMboxPend()等待邮箱中的消息,OSMboxPos ...