源碼: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 = 0); 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 = 1);//為有向圖設置鄰接矩陣 bool setValueToMatrixForUndirectedGraph(int row, int col, int val = 1);//為無向圖設置鄰接矩陣 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 = 0; m_pNodeArray = new Node[m_iCapacity]; m_pMatrix = new int[m_iCapacity*m_iCapacity]; for (int i = 0; i < m_iCapacity*m_iCapacity; i++) { m_pMatrix[i] = 0; } }
析構函數
刪除頂點數組指針
刪除鄰接矩陣指針
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 = 0; 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<0 || row>=m_iCapacity) { return false; } if (col < 0 || 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<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; }
從矩陣中獲取權值
先判斷行和列的合法性
行不能小於0,不能大於等於容量
列不能小於0,不能大於等於容量
獲取當前索引的鄰接矩陣,賦值給變量返回
返回正確結果
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; }
打印鄰接矩陣
矩陣,用兩層循環遍歷
i是row,k就是col
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; } }
深度優先遍歷
深度優先遍歷相當於樹的前序遍歷
先直接輸出當前指定索引的鄰接矩陣的結點
講m_IsVisited置為未訪問
按序獲取獲取矩陣權值
如果權值不等於1,跳過本次循環
如果權值等於1,結點已訪問,跳過本次循環,這里是無向圖,這里判斷結點是否訪問是因為鄰接矩陣的權值1成主對角線對稱,防止A-B訪問,再訪問B-A的情況出現
如果未訪問,進入遞歸,進入方法前兩行,將結點輸出,以此類推
看懂過程要打斷點
void cMap::depthFirstTraverse(int nodeIndex) { int value = 0; cout << m_pNodeArray[nodeIndex].m_cData<<" "; m_pNodeArray[nodeIndex].m_IsVisited = true; for (int i = 0; i < m_iCapacity; i++) { getValueFromMatrix(nodeIndex,i,value); if (value == 1) { 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 = 0; vector<int> curVec; for (int j = 0; j < (int)preVec.size(); j++) { for (int i = 0; i < m_iNodeCount; i++) { getValueFromMatrix(preVec[j],i,value); if (value != 0) { 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() == 0) { return; } else { breathFirstTraverseImpl(curVec); } }