1. 程式人生 > >圖的實現 鄰接矩陣+無向圖

圖的實現 鄰接矩陣+無向圖

#include <iostream>
#include <string.h>
#include <vector>
#include <stdlib.h>
using namespace std;

class Node
{
public:
    Node(char data = 0);//建構函式 初始化 
    char m_Data; //值 
    bool m_blsVisited; //標識是否被訪問過       
};

class Edge
{
public:
    Edge(int nodeIndexA = 0, int nodeIndexB = 0
, int weightValue = 0); int m_iNodeIndexA; int m_iNodeIndexB; int m_iWeightValue; bool m_bSelected; }; class CMap { public: CMap(int iCapacity); ~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 primTree(int nodeIndex); //nodeIndex指定的第一個點 void KruskalTree(); private
: bool GetValueFromMatrix(int row, int col, int &val); void BreadthFirstTraverseImpl(vector<int> preVec); int GetMinEdge(vector<Edge> EdgeVec); bool IsInSet(vector<int> nodeSet, int target); void MergeNodeSet(vector<int> &nodeSetA, vector<int> nodeSetB); private: int m_iCapacity; //途中最多可以容納的頂點數 int m_iNodeCount; //已經新增的頂點個數 Node *m_pNodeArray; //用來存放頂點陣列 int *m_pMatrix; //存放鄰接矩陣 Edge *m_pEdge; //存最小生成樹中的邊 }; Node::Node(char data) { m_Data = data; m_blsVisited = false; } CMap::CMap(int iCapacity) { m_iCapacity = iCapacity; 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)); m_pEdge = new Edge[iCapacity - 1]; } CMap::~CMap() { delete [] m_pNodeArray; delete [] m_pMatrix; delete [] m_pEdge; } bool CMap::AddNode(Node* pNode) { m_pNodeArray[m_iNodeCount].m_Data = pNode->m_Data; m_iNodeCount++; return true; } void CMap::ResetNode() { for(int i = 0; i < m_iNodeCount; i++) { m_pNodeArray[i].m_blsVisited = false; } } //有向圖鄰接矩陣 bool CMap::SetValueToMatrixForDirectedGraph(int row, int col, int val) { m_pMatrix[row*m_iCapacity + col] = val; return true; } bool CMap::SetValueToMatrixForUndirectedGraph(int row, int col, int val) { 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) { val = m_pMatrix[row*m_iCapacity + col]; return true; } void CMap::PrintMatrix() { for(int i = 0; i < m_iCapacity; i++) { for(int j = 0; j < m_iCapacity; j++) { cout << m_pMatrix[i*m_iCapacity + j] << " "; } cout << endl; } } void CMap::DepthFirstTraverse(int NodeIndex) { int value = 0; cout << m_pNodeArray[NodeIndex].m_Data << " "; m_pNodeArray[NodeIndex].m_blsVisited = true; for(int i =0; i < m_iCapacity; i++) { GetValueFromMatrix(NodeIndex, i, value); if(value == 1) { if(m_pNodeArray[i].m_blsVisited) { continue; } else { DepthFirstTraverse(i); } } else { continue; } } } void CMap::BreadthFirstTraverse(int NodeIndex) { cout << m_pNodeArray[NodeIndex].m_Data << " "; m_pNodeArray[NodeIndex].m_blsVisited = true; vector<int> curVec; curVec.push_back(NodeIndex); BreadthFirstTraverseImpl(curVec); } void CMap::BreadthFirstTraverseImpl(vector<int> preVec) { int value = 0; vector<int> curVec; //儲存當前這一層所有節點 //preVec 上一層所有節點 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_blsVisited) { continue; } else { cout << m_pNodeArray[i].m_Data << " "; m_pNodeArray[i].m_blsVisited = true; curVec.push_back(i); } } } } if(curVec.size() == 0) { return ; } else { BreadthFirstTraverseImpl(curVec); } } Edge::Edge(int nodeIndexA, int nodeIndexB, int weightValue) { m_iNodeIndexA = nodeIndexA; m_iNodeIndexB = nodeIndexB; m_iWeightValue = weightValue; m_bSelected = false; } //普利姆生成樹 void CMap::primTree(int nodeIndex) { int value = 0; //取邊的權值 int edgeCount = 0; vector<int> NodeVec; //儲存點的集合 vector<Edge> EdgeVec; //備選邊的集合 cout << m_pNodeArray[nodeIndex].m_Data << endl; m_pNodeArray[nodeIndex].m_blsVisited = true; NodeVec.push_back(nodeIndex); while(edgeCount < m_iCapacity - 1) { int temp = NodeVec.back(); //取出最尾部的元素 //將與temp節點所連的所有的邊都放入備選邊集合 for(int i = 0; i < m_iCapacity; i++) { GetValueFromMatrix(temp, i, value); if(value != 0) { if(m_pNodeArray[i].m_blsVisited) { continue; } else { Edge edge(temp, i, value); EdgeVec.push_back(edge); } } } //從備選邊集合中找出最小的邊 傳出最小邊的邊索引 int edgeIndex = GetMinEdge(EdgeVec); EdgeVec[edgeIndex].m_bSelected = true; cout << EdgeVec[edgeIndex].m_iNodeIndexA << "......" << EdgeVec[edgeIndex].m_iNodeIndexB << " "; cout << EdgeVec[edgeIndex].m_iWeightValue << endl; m_pEdge[edgeCount++] = EdgeVec[edgeIndex]; //找到與當前最小邊所連線的點 int nextNodeIndex= EdgeVec[edgeIndex].m_iNodeIndexB; NodeVec.push_back(nextNodeIndex); m_pNodeArray[nextNodeIndex].m_blsVisited = true; cout << m_pNodeArray[nextNodeIndex].m_Data << endl; } } int CMap::GetMinEdge(vector<Edge> EdgeVec) { int minWeight = 0; int edgeIndex = 0; int i= 0; //取出第一條未訪問的邊 for(; i < EdgeVec.size(); i++) { if(!EdgeVec[i].m_bSelected) { minWeight = EdgeVec[i].m_iWeightValue; edgeIndex = i; break; } } if(minWeight == 0) { return -1; } //剩餘邊中找最小邊 for(; i < EdgeVec.size(); i++) { if(!EdgeVec[i].m_bSelected) { if(minWeight > EdgeVec[i].m_iWeightValue) { minWeight = EdgeVec[i].m_iWeightValue; edgeIndex = i; } } else { continue ; } } return edgeIndex; } bool CMap::IsInSet(vector<int> nodeSet, int target) { for(int i = 0; i < nodeSet.size(); i++) { if(nodeSet[i] == target) { return true; } } return false; } void CMap::MergeNodeSet(vector<int> &nodeSetA, vector<int> nodeSetB) { for(int i = 0; i < nodeSetB.size(); i++) { nodeSetA.push_back(nodeSetB[i]); } } void CMap::KruskalTree() { int value = 0; int edgeCount = 0; //定義一個點集合的陣列 vector< vector<int> > NodeSets; //1.取出所有的邊 vector<Edge> EdgeVec; for(int i = 0; i < m_iCapacity; i++) { for(int j = i + 1; j < m_iCapacity; j++) //取出鄰接矩陣上半個三角,不含主對角線上的資料 { GetValueFromMatrix(i, j, value); if(value != 0) { Edge edge(i, j, value); EdgeVec.push_back(edge); } } } //2. 從所有邊中取出組成最小生成樹的邊 // 找到演算法結束條件 邊數 = 頂點數 - 1 while(edgeCount < m_iCapacity - 1) { // 從邊集合中找到最小邊 int minEdgeIndex = GetMinEdge(EdgeVec); EdgeVec[minEdgeIndex].m_bSelected = true; //找到最小邊連線的點 int nodeAIndex = EdgeVec[minEdgeIndex].m_iNodeIndexA; int nodeBIndex = EdgeVec[minEdgeIndex].m_iNodeIndexB; bool nodeAIsInSet = false; bool nodeBIsInSet = false; int nodeAInSetLabel = -1; int nodeBInSetLabel = -1; //找出A點所在的集合 for(int i = 0; i < NodeSets.size(); i++) { nodeAIsInSet = IsInSet(NodeSets[i], nodeAIndex); if(nodeAIsInSet) { nodeAInSetLabel = i; } } //找出B點所在的集合 for(int i = 0; i < NodeSets.size(); i++) { nodeBIsInSet = IsInSet(NodeSets[i], nodeAIndex); if(nodeBIsInSet) { nodeBInSetLabel = i; } } //根據點所在的集合做出不同的處理 if(nodeAInSetLabel == -1 && nodeBInSetLabel == -1) { vector<int> vec; vec.push_back(nodeAInSetLabel); vec.push_back(nodeBInSetLabel); NodeSets.push_back(vec); } else if(nodeAInSetLabel == -1 && nodeBInSetLabel != -1) { NodeSets[nodeBInSetLabel].push_back(nodeAInSetLabel); } else if(nodeAInSetLabel != -1 && nodeBInSetLabel == -1) { NodeSets[nodeAInSetLabel].push_back(nodeBInSetLabel); } else if(nodeAInSetLabel != -1 && nodeBInSetLabel != -1 && nodeAInSetLabel != nodeBInSetLabel) { MergeNodeSet(NodeSets[nodeAInSetLabel], NodeSets[nodeBInSetLabel]);//合併集合 for(int k = nodeBInSetLabel; k < (int)NodeSets.size() - 1; k++) //類似於在佇列中刪除一個節點 { NodeSets[k] = NodeSets[k + 1]; } } else if(nodeAInSetLabel != -1 && nodeBInSetLabel != -1 && nodeAInSetLabel == nodeBInSetLabel) { continue ; } m_pEdge[edgeCount++] = EdgeVec[minEdgeIndex]; cout << EdgeVec[minEdgeIndex].m_iNodeIndexA << "......" << EdgeVec[minEdgeIndex].m_iNodeIndexB << " "; cout << EdgeVec[minEdgeIndex].m_iWeightValue << endl; } } int main() { CMap *pMap = new CMap(6); 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->AddNode(pNodeA); pMap->AddNode(pNodeB); pMap->AddNode(pNodeC); pMap->AddNode(pNodeD); pMap->AddNode(pNodeE); pMap->AddNode(pNodeF); // pMap->AddNode(pNodeG); // pMap->AddNode(pNodeH); #if 0 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); #endif pMap->SetValueToMatrixForUndirectedGraph(0, 1, 6); pMap->SetValueToMatrixForUndirectedGraph(0, 4, 5); pMap->SetValueToMatrixForUndirectedGraph(0, 5, 1); pMap->SetValueToMatrixForUndirectedGraph(1, 2, 3); pMap->SetValueToMatrixForUndirectedGraph(1, 5, 2); pMap->SetValueToMatrixForUndirectedGraph(2, 5, 8); pMap->SetValueToMatrixForUndirectedGraph(2, 3, 7); pMap->SetValueToMatrixForUndirectedGraph(3, 5, 4); pMap->SetValueToMatrixForUndirectedGraph(3, 4, 2); pMap->SetValueToMatrixForUndirectedGraph(4, 5, 9); pMap->PrintMatrix(); cout << endl; #if 0 pMap->ResetNode(); pMap->DepthFirstTraverse(0); cout << endl; pMap->ResetNode(); pMap->BreadthFirstTraverse(0); cout << endl; #endif pMap->KruskalTree(); system("pause"); return 0; }