文章目錄
注:轉載請標明原文出處鏈接:https://xiongyiming.blog.csdn.net/article/details/100918881
1 圖簡介
圖 (Graph) 結構是一種非線性的數據結構,圖在實際生活中有很多例子,比如交通運輸網,地鐵網絡,社交網絡,計算機中的狀態執行(自動機)等等都可以抽象成圖結構。圖結構比樹結構複雜的非線性結構。
圖分爲 有向圖 和 無向圖,如下圖所示:
有向圖,如下圖所示,對於頂點V1:初度=2,入度=1.
弧:有向圖中頂點和頂點之間的連線。
無向圖,如下圖所示:
邊:無向圖中,頂點和頂點之間的連線。
2 圖的存儲
要想使用圖去解決實際問題,那麼就需要知道,圖是如何進行存儲的。
在存儲有向圖和無向圖有一定的差別。
如下圖所示,圖的存儲結構有:鄰接矩陣、鄰接表、十字鏈表和鄰接多重表。其中,鄰接矩陣使用數組表示,主要表達無向圖和有向圖;而鄰接表和十字鏈表使用鏈表進行表示,主要表達有向圖。鄰接多重表使用鏈表進行表示,主要表達無向圖。
2.1 鄰接矩陣——數組
鄰接矩陣由數組進行存儲.
對於有向圖:
對於無向圖:
2.2 鄰接表——鏈表
鄰接表由鏈表進行存儲.
2.3 十字鏈表——鏈表
十字鏈表由鏈表進行存儲.
2.4 鄰接多重表——鏈表
2.5 圖的遍歷
圖的遍歷分爲:深度優先搜索 和 廣度優先搜索
(1) 深度優先搜索
相當於前序遍歷
(2) 廣度優先搜索
(3) 代碼示例
要求
圖的遍歷
深度優先遍歷
廣度優先遍歷
Node.h
#pragma once
class Node
{
public:
Node(char data = 0);
char m_cData;
bool m_bIsVisited;
};
Node.cpp
#include<iostream>
#include"Node.h"
using namespace std;
Node::Node(char data)
{
m_cData = data;
m_bIsVisited = false;
}
CMap.h
#pragma once
#include<iostream>
#include<vector>
#include"Node.h"
using namespace std;
class CMap
{
public:
CMap(int capacity);
~CMap();
bool addNote(Node *pNode);
void resetNode();
bool setValueToMatrixForDirectedGraph(int row, int col, int val = 1);//爲有向圖設置鄰接矩陣
bool setValueToMatrixForUndirectedGraph(int row, int col, int val = 1);//爲無向圖設置鄰接矩陣
void printMatrix();//打印鄰接矩陣
void depthFristTraverse(int nodeIndex);//深度優先遍歷
void breadthFirstTraverse(int nodeIndex);//廣度優先遍歷
private:
bool getValueFromMatrix(int row, int col, int &val);//從矩陣中獲取權值
void breadthFirstTraverseImpl(vector<int>preVec);//廣度優先遍歷函數
private:
int m_iCapacity;//圖中最多可以容納的頂點數
int m_iNodeCount;//已經添加的頂點(結點)個數
Node *m_pNodeArray;//用來存放頂點數組
int *m_pMatrix;//用來存放鄰接矩陣
};
CMap.cpp
#include<iostream>
#include<vector>
#include"CMap.h"
using namespace std;
CMap::CMap(int capacity)
{
m_iCapacity = capacity;
m_iNodeCount = 0;
m_pNodeArray = new Node[m_iCapacity];
m_pMatrix = new int[m_iCapacity*m_iCapacity];
memset(m_pMatrix, 0, m_iCapacity*m_iCapacity * sizeof(int));
}
CMap::~CMap()
{
delete[]m_pNodeArray;
delete[]m_pMatrix;
}
bool CMap::addNote(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_iNodeCount; i++)
{
m_pNodeArray[i].m_bIsVisited = false;
}
}
bool CMap::setValueToMatrixForDirectedGraph(int row, int col, int val)
{
if (row < 0 || row >= m_iCapacity)
{
return false;
}
if (col < 0 || col >= m_iCapacity)
{
return false;
}
m_pMatrix[row*m_iCapacity + col] = val;
return true;
}
bool CMap::setValueToMatrixForUndirectedGraph(int row, int col, int val)
{
if (row < 0 || row >= m_iCapacity)
{
return false;
}
if (col < 0 || col >= m_iCapacity)
{
return false;
}
m_pMatrix[row*m_iCapacity + col] = val;
m_pMatrix[col*m_iCapacity + row] = val;
return true;
}
bool CMap::getValueFromMatrix(int row, int col, int &val)//從矩陣中獲取權值
{
if (row < 0 || row >= m_iCapacity)
{
return false;
}
if (col < 0 || col >= m_iCapacity)
{
return false;
}
val = m_pMatrix[row*m_iCapacity + col];
return true;
}
void CMap::printMatrix()//打印鄰接矩陣
{
for (int i = 0; i < m_iCapacity; i++)
{
for (int k = 0; k < m_iCapacity; k++)
{
cout << m_pMatrix[i*m_iCapacity + k] << " ";
}
cout << endl;
}
}
//深度優先遍歷
void CMap::depthFristTraverse(int nodeIndex)
{
int value = 0;
cout << m_pNodeArray[nodeIndex].m_cData << " ";
m_pNodeArray[nodeIndex].m_bIsVisited = true;
//通過鄰接矩陣判斷是否與其他的頂點有連接
for (int i = 0; i < m_iCapacity; i++)
{
getValueFromMatrix(nodeIndex, i, value);
if (value != 0)
{
//再判斷該點是否被訪問過
if (m_pNodeArray[i].m_bIsVisited)
{
continue;
}
else
{
depthFristTraverse(i);//遞歸
}
}
}
}
//廣度優先遍歷
void CMap::breadthFirstTraverse(int nodeIndex)
{
cout << m_pNodeArray[nodeIndex].m_cData << " ";
m_pNodeArray[nodeIndex].m_bIsVisited = true;
vector<int>curVec;
curVec.push_back(nodeIndex);
breadthFirstTraverseImpl(curVec);
}
//廣度優先遍歷函數
void CMap::breadthFirstTraverseImpl(vector<int>preVec)
{
int value = 0;
vector<int>curVec;
for (int j = 0; j < (int)preVec.size(); j++)
{
for (int i = 0; i <= m_iCapacity; i++)
{
getValueFromMatrix(preVec[j], i, value);
if (value != 0)
{
//再判斷該點是否被訪問過
if (m_pNodeArray[i].m_bIsVisited)
{
continue;
}
else
{
cout << m_pNodeArray[i].m_cData << " ";
m_pNodeArray[i].m_bIsVisited = true;
curVec.push_back(i);
}
}
}
}
if (curVec.size() == 0)
{
return;
}
else
{
breadthFirstTraverseImpl(curVec);
}
}
main.cpp
#include<iostream>
#include<vector>
#include"CMap.h"
#include"Node.h"
using namespace std;
/*******************************************
圖的遍歷
深度優先遍歷
廣度優先遍歷
A
/ \
B D
/\ /\
C F G H
\ /
E
**********************************************/
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->addNote(pNodeA);
pMap->addNote(pNodeB);
pMap->addNote(pNodeC);
pMap->addNote(pNodeD);
pMap->addNote(pNodeE);
pMap->addNote(pNodeF);
pMap->addNote(pNodeG);
pMap->addNote(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->resetNode();
cout << "深度優先遍歷: " ;
pMap->depthFristTraverse(0);
cout << endl;
cout << endl;
//廣度優先遍歷
pMap->resetNode();
cout << "廣度優先遍歷: " ;
pMap->breadthFirstTraverse(0);
cout << endl;
cin.get();
return 0;
}
運行結果
3 最小生成樹
參考資料
[1] 數據結構探險之圖篇