图的邻接矩阵存储之C++封装

1、定义:图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。

2、由定义可知,图的邻接矩阵存储方式是用两个数据来表示。一个数据中存储图中顶点信息,另一个数据中(称为邻接矩阵)存储图中的边的信息。见下图:(图片来源于《大话数据结构》)

                  

3、图的其它定义:

1)  有向图与无向图;完全图;弧和边;入度和出度;连通图与非连通图---自行查看相关定义。


4、图的遍历:

1)图的深度遍历:

图的深度优先遍历类似于二叉树的深度优先遍历,其基本思想是:从图中某个顶点v出发,访问此顶点,然后从v的未被访问的邻接点出发深度优先遍历图,直至图中所有和v有路径相通的顶点都被访问到。显然,这是一个递归的搜索过程。

image

在上图中我们坚持沿着右手边走,如果碰见标记的跳过,选择另一条。到最后时再返回遍历确认是否都有标记。其实就是树的前序遍历。以上图为例,假定A是出发点,首先访问A。这时两个邻接点B、F均未被访问,右手边为B,访问B之后,按照右手原则遍历到C,相同原理A→B→C→D→E→F,在F上向右为A,因为A遍历过,则访问G。最后到H,再走发现到D,E,两者都访问了。关键此时,还有没访问到的,按照原路返回,返回到G,一条条返回,最后得到的访问序列为A→B→C→D→E→F→G→H→I。

2)图的广度优先遍历:

图的广度优先遍历算法是一个分层遍历的过程,和二叉树的广度优先遍历类似,其基本思想在于:从图中的某一个顶点Vi触发,访问此顶点后,依次访问Vi的各个为层访问过的邻接点,然后分别从这些邻接点出发,直至图中所有顶点都被访问到广度优先遍历类似树的层序遍历。

首先访问v1 和v1 的邻接点v2 和v3,然后依次访问v2 的邻接点v4 和v5 及v3 的邻接点v6 和v7,最后访问v4 的邻接点v8。由于这些顶点的邻接点均已被访问,并且图中所有顶点都被访问,由些完成了图的遍历。得到的顶点访问序列为:

v1→v2 →v3 →v4→ v5→ v6→ v7 →v8


5、图的C++实现:

.h文件:

#pragma once
#include <vector>
using namespace std;



/*   一个无向图:假设无向图的权值都为1
            A
          /   \
         B     D
		/ \   / \
	   C  F  G   H
	    \/
	    E
*/

/*   对应的邻接矩阵:

     A B C D E F G H
  A  0 1 0 1 0 0 0 0
  B  1 0 1 0 0 1 0 0
  C  0 1 0 0 1 0 0 0
  D  1 0 0 0 0 0 1 1
  E  O O 1 O O 1 O O
  F  O 1 O O 1 O O O 
  G  0 0 0 1 0 0 0 0
  H  O O O 1 O O O O

*/

class CNode
{
public:
	CNode(char cData = 0);
public:
	char m_cData;
	bool m_bIsVisited;
};

class CZzcGrapha
{
public:
	CZzcGrapha(int nCapacity);
	~CZzcGrapha(void);
	bool AddNodeToGrapha(CNode* pNode); //向图中增加节点
	void ResetNodeVisitFlag();           //将所有节点的访问标识置为false
	bool SetValueToMatrixForDirectedGraph(int row,int col,int value = 1);//向有向图矩阵中设置值
	bool SetValueToMatrixForUnDirectedGraph(int row,int col,int value = 1);//向无向图矩阵设置值
	bool GetValueFromMatrix(int row,int col,int& value);//从邻接矩阵中获取值
	void PrintMatrix();//打印出图的邻接矩阵
	void DepthFirstTraverse(int nodeindex);//深度优先遍历
	void WidthFirstTraverse(int nodeindex);//广度优先遍历
	void WidthTraverseIteration(vector<int> prevec);
private:
	int m_nCapacity;        //图的容量(可以容纳的节点数)
	int m_nCurNodeCount;    //图中当前的节点个数
	CNode* m_pNodeArray;    //用来存放定点数据
	int* m_pMatrix;         //用来存放邻接矩阵数据
};



.cpp文件:

#include "StdAfx.h"
#include "ZzcGrapha.h"
#include "Windows.h"
#include <iostream>
using namespace std;


CNode::CNode(char cData)
{
	m_cData = cData;
	m_bIsVisited = false;
}

CZzcGrapha::CZzcGrapha(int nCapacity)
{
	m_nCapacity      = nCapacity;
	m_nCurNodeCount  = 0;
	m_pNodeArray     = new CNode[m_nCapacity];
	m_pMatrix        = new int[m_nCapacity * m_nCapacity];
	ZeroMemory(m_pMatrix,m_nCapacity * m_nCapacity * sizeof(int));
}

CZzcGrapha::~CZzcGrapha(void)
{
	if (m_pNodeArray)
	{
		delete[]m_pNodeArray;
		m_pNodeArray = NULL;
	}

	if (m_pMatrix)
	{
		delete[]m_pMatrix;
		m_pMatrix = NULL;
	}
}

bool CZzcGrapha::AddNodeToGrapha(CNode* pNode)
{
	if(pNode == NULL) return false;

	m_pNodeArray[m_nCurNodeCount].m_cData = pNode->m_cData;
	m_nCurNodeCount++;
	return true;
}

void CZzcGrapha::ResetNodeVisitFlag()
{
	for(int i = 0;i < m_nCapacity;i++)
	{
		m_pNodeArray[i].m_bIsVisited = false;
	}
}

bool CZzcGrapha::SetValueToMatrixForDirectedGraph(int row,int col,int value)
{
	if(row < 0||row >= m_nCapacity) return false;

	if(col < 0||col >= m_nCapacity) return false;

	m_pMatrix[m_nCapacity * row + col] = value;

	return true;
}

bool CZzcGrapha::SetValueToMatrixForUnDirectedGraph(int row,int col,int value)
{
	if(row < 0||row >= m_nCapacity) return false;

	if(col < 0||col >= m_nCapacity) return false;

	m_pMatrix[m_nCapacity * row + col] = value;
	m_pMatrix[m_nCapacity * col + row] = value;

	return true;
}

bool CZzcGrapha::GetValueFromMatrix(int row,int col,int& value)
{
	if(row < 0||row >= m_nCapacity) return false;

	if(col < 0||col >= m_nCapacity) return false;

	value = m_pMatrix[m_nCapacity * row + col];

	return true;
}

void CZzcGrapha::PrintMatrix()
{
	for (int i = 0;i < m_nCapacity;i++)
	{
		for (int k = 0;k < m_nCapacity;k++)
		{
			cout<<m_pMatrix[m_nCapacity * i + k]<<" "; 
		}

		cout<<endl;
	}
}

void CZzcGrapha::DepthFirstTraverse(int nodeindex)
{
	int value = 0;

	cout<<m_pNodeArray[nodeindex].m_cData<<" ";
	m_pNodeArray[nodeindex].m_bIsVisited = true;

	for (int i = 0;i < m_nCapacity;i++)
	{
		GetValueFromMatrix(nodeindex,i,value);

		if (value == 1)
		{
			if(m_pNodeArray[i].m_bIsVisited == true) continue;

			DepthFirstTraverse(i);
		} 
		else
		{
			continue;
		}
	}
}

void CZzcGrapha::WidthFirstTraverse(int nodeindex)
{
	cout<<m_pNodeArray[nodeindex].m_cData<<" ";
	m_pNodeArray[nodeindex].m_bIsVisited = true;

	vector<int> curVec;
	curVec.push_back(nodeindex);
	WidthTraverseIteration(curVec);
}

void CZzcGrapha::WidthTraverseIteration(vector<int> prevec)
{
	int value = 0;

	vector<int> curVec;

	for(int i = 0;i < (int)prevec.size();i++)
	{
		for (int j = 0;j < m_nCapacity;j++)
		{
			GetValueFromMatrix(prevec[i],j,value);

			if (value != 0)
			{
				if(m_pNodeArray[j].m_bIsVisited) continue;

				cout<<m_pNodeArray[j].m_cData<<" ";
				m_pNodeArray[j].m_bIsVisited = true;

				curVec.push_back(j);
			} 
			else
			{
				continue;
			}
		}
	}

	if(curVec.size() == 0) return;

	WidthTraverseIteration(curVec);
}

测试:

// 图.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "ZzcGrapha.h"
#include <iostream>
using namespace std;


int _tmain(int argc, _TCHAR* argv[])
{
	CZzcGrapha* pGrapha = new CZzcGrapha(8);

	CNode* pNodeA = new CNode('A');
	CNode* pNodeB = new CNode('B');
	CNode* pNodeC = new CNode('C');
	CNode* pNodeD = new CNode('D');
	CNode* pNodeE = new CNode('E');
	CNode* pNodeF = new CNode('F');
	CNode* pNodeG = new CNode('G');
	CNode* pNodeH = new CNode('H');

	pGrapha->AddNodeToGrapha(pNodeA);
	pGrapha->AddNodeToGrapha(pNodeB);
	pGrapha->AddNodeToGrapha(pNodeC);
	pGrapha->AddNodeToGrapha(pNodeD);
	pGrapha->AddNodeToGrapha(pNodeE);
	pGrapha->AddNodeToGrapha(pNodeF);
	pGrapha->AddNodeToGrapha(pNodeG);
	pGrapha->AddNodeToGrapha(pNodeH);

	pGrapha->SetValueToMatrixForUnDirectedGraph(0,1);
	pGrapha->SetValueToMatrixForUnDirectedGraph(0,3);
	pGrapha->SetValueToMatrixForUnDirectedGraph(1,2);
	pGrapha->SetValueToMatrixForUnDirectedGraph(1,5);
	pGrapha->SetValueToMatrixForUnDirectedGraph(3,6);
	pGrapha->SetValueToMatrixForUnDirectedGraph(3,7);
	pGrapha->SetValueToMatrixForUnDirectedGraph(6,7);
	pGrapha->SetValueToMatrixForUnDirectedGraph(2,4);
	pGrapha->SetValueToMatrixForUnDirectedGraph(4,5);

	pGrapha->PrintMatrix();
	cout<<endl;

	pGrapha->DepthFirstTraverse(0);
	cout<<endl;
	pGrapha->ResetNodeVisitFlag();
	pGrapha->WidthFirstTraverse(0);

	//......delete操作省略......
	return 0;
}




发布了415 篇原创文章 · 获赞 123 · 访问量 64万+

猜你喜欢

转载自blog.csdn.net/u012372584/article/details/76377125