#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;
}
图的实现 邻接矩阵+无向图
最新推荐文章于 2022-08-15 16:33:25 发布