源码: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++实现的更多相关文章

  1. 概率图模型之有向图与无向图之间的关系 I map D map perfect map(完美图) 概念

    我们已经讨论了有向图和无向图框架下的概率模型,那么我们有必要讨论一下它们二者的关系.

  2. 图论 Make Unique:有向图和无向图的一些算法

    计算机科学入门资料之一的<算法与数据结构-C语言版>,覆盖了基础算法的几乎所有分支,其中的一个典型分支为图理论. 一个简介:图论基础-图数据结构基础 一个简洁的博客:图论基础,简列一本书 ...

  3. tarjan——有向图、无向图

    强连通块只存在于有向无环图DAG中 实际上low[i]的理解是:一个强连通块在dfs搜索树中子树的根节点 //把一个点当成根提溜出来,抖搂抖搂成一棵树 void dfs(int u) { //记录df ...

  4. 有向图与无向图的合并操作区别D(递归与并查集)

    有向图的合并,典型问题:通知小弟(信息只能单向传播)https://www.nowcoder.com/acm/contest/76/E 无向图的合并,典型问题:修道路问题 由于无向图只要二者有联系即可 ...

  5. WBS任务分解中前置任务闭环回路检测:有向图的简单应用(C#)

    1 场景描述 系统中用到了进度计划编制功能,支持从project文件直接导入数据,并能够在系统中对wbs任务进行增.删.改操作.wbs任务分解中一个重要的概念就是前置任务,前置任务设置确定了不同任务项 ...

  6. Java数据结构和算法(十五)——无权无向图

    前面我们介绍了树这种数据结构,树是由n(n>0)个有限节点通过连接它们的边组成一个具有层次关系的集合,把它叫做“树”是因为它看起来像一棵倒挂的树,包括二叉树.红黑树.2-3-4树.堆等各种不同的 ...

  7. 有向网络(带权的有向图)的最短路径Dijkstra算法

    什么是最短路径? 单源最短路径(所谓单源最短路径就是只指定一个顶点,最短路径是指其他顶点和这个顶点之间的路径的权值的最小值) 什么是最短路径问题? 给定一带权图,图中每条边的权值是非负的,代表着两顶点 ...

  8. UVA 1660 Cable TV Network 电视网络(无向图,点连通度,最大流)

    题意:给一个无向图,求其点连通度?(注意输入问题) 思路: 如果只有1个点,那么输出“1”: 如果有0条边,那么输出“0”: 其他情况:用最大流解决.下面讲如何建图: 图的连通度问题是指:在图中删去部 ...

  9. POJ2186(有向图缩点)

    Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 28379   Accepted: 11488 De ...

随机推荐

  1. [LeetCode 题解]: Remove Duplicates from Sorted List

    Given a sorted linked list, delete all duplicates such that each element appear only once. For examp ...

  2. [LeetCode 题解]: Insertion Sort List

    Sort a linked list using insertion sort. 题目要求:链表的插入排序,由于没有时间复杂度的要求,可以直接循环操作. /** * Definition for si ...

  3. 重新理解javascript回调函数

    把函数作为参数传入到另一个函数中.这个函数就是所谓的回调函数 经常遇到这样一种情况,某个项目的A层和B层是由不同的人员协同完成.A层负责功能funA,B层负责funcB.当B层要用到某个模块的数据,于 ...

  4. Bitnami WordPress如何让默认URL指向WordPress目录?

    Bitnami WordPress下载地址:https://bitnami.com/stack/wordpress/installer ,根据自己操作系统选择对应版本,我是windows server ...

  5. Mysql内置功能《四》存储过程

    存储过程 一 存储过程介绍 存储过程包含了一系列可执行的sql语句,存储过程存放于MySQL中,通过调用它的名字可以执行其内部的一堆sql 使用存储过程的优点: #1. 用于替代程序写的SQL语句,实 ...

  6. CSS3 文本溢出问题

    一.单行: 效果: 实现这各效果必须要加上: text-overflow: ellipsis; /*文本溢出*/ overflow: hidden; /*配合使用:溢出隐藏*/ white-space ...

  7. python 控制台输出带颜色的文字的方法

    python_控制台输出带颜色的文字方法   在python开发的过程中,经常会遇到需要打印各种信息.海量的信息堆砌在控制台中,就会导致信息都混在一起,降低了重要信息的可读性.这时候,如果能给重要的信 ...

  8. python(unittest)报告导出(二):使用 BeautifulReport导出

    BeautifulReport(导出的报告比HTMLTestRunner更全面) 下载地址及安装位置 https://github.com/TesterlifeRaymond/BeautifulRep ...

  9. [八分之三的男人] POJ - 1741 点分治 && 点分治笔记

    题意:给出一棵带边权树,询问有多少点对的距离小于等于\(k\) 本题解参考lyd的算法竞赛进阶指南,讲解的十分清晰,比网上那些讲的乱七八糟的好多了 不过写起来还是困难重重(史诗巨作 打完多校更详细做法 ...

  10. PM2的安装和使用简介

    一.简介 PM2是node进程管理工具,可以利用它来简化很多node应用管理的繁琐任务,如性能监控.自动重启.负载均衡等,而且使用非常简单. 二.前期必备 node 环境 npm 三.安装 全局安装 ...