图的编码实战-最小生成树之克鲁斯卡尔算法

#include<iostream>
#include<stdlib.h>
#include<vector>
using namespace std;
//题目信息
/*
         A
       / | \
	  B--F--D
	   \/ \/
       C   H
	   
   A B C D E F
   0 1 2 3 4 5
*/
/*
  A-B  6     A-E  5     A-F  1
  B-C  3     B-F  2
  C-F  8     C-D  7
  D-F  4     D-E  2
  E-F  9
*/      
class Node
{
public:
   Node(char data=0)
   {
	   m_cData=data;
	   m_bIsVisited=false;
   }
   char m_cData;
   bool m_bIsVisited;
};
class Edge
{
public:
	Edge(int nodeIndexA=0,int nodeIndexB=0,int weightValue=0)
	{
		m_iNodeIndexA=nodeIndexA;
		m_iNodeIndexB=nodeIndexB;
		m_iWeightValue=weightValue;
		m_bSelected=false;
	}
	int m_iNodeIndexA;
	int m_iNodeIndexB;
	int m_iWeightValue;
	bool m_bSelected;
};
class CMap
{
public:

      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()
	  {
		   delete []m_pNodeArray;
		   delete []m_pMatrix;
		   delete []m_pEdge;
	  }

      bool addNode(Node *pNode)//向图中加入顶点 (结点)
	  {
		  m_pNodeArray[m_iNodeCount].m_cData=pNode->m_cData;
		  m_iNodeCount++;
		  return true;
	  }

	  void resetNode()  //重置顶点
	  {
		  for(int i=0;i<m_iNodeCount;i++)
		  {
			  m_pNodeArray[i].m_bIsVisited=false;
		  }
	  }

      bool setValueToMatrixForDirectedGraph(int row, int col, int val = 1)  //为有向图设置邻接矩阵
	  {
		  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 setValueToMatrixForUndirectedGraph(int row, int col, int val = 1) //为无向图设置邻接矩阵
      {
		  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;
	  }
	  void 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 depthFirstTraverse(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==1)
			  {
				  if(m_pNodeArray[i].m_bIsVisited)
				  {
					  continue;
				  }
				  else
				  {
                      depthFirstTraverse(i);
				  }
			  }
			  else
			  {
				  continue;
			  }
		  }
	  }
	  void breadthFirstTraverse(int nodeIndex) //广度优先遍历
      {
		  cout << m_pNodeArray[nodeIndex].m_cData << " ";
		  m_pNodeArray[nodeIndex].m_bIsVisited = true;
          vector<int> curVec;
          curVec.push_back(nodeIndex);
          breadthFirstTraverselmpl(curVec);
	  }
	  void primTree(int nodeIndex)
	  {
		  int value=0;
		  int edgeCount=0;
		  vector<int> nodeVec;
		  vector<Edge> edgeVec;
          
		  cout<<m_pNodeArray[nodeIndex].m_cData<<endl;

		  nodeVec.push_back(nodeIndex);

          while(edgeCount<m_iCapacity-1)
		  {
              int temp=nodeVec.back();

			  for(int i=0;i<m_iCapacity;i++)
			  {
				   getValueFromMatrix(temp,i,value);
				   if(value!=0)
				   {
					   if(m_pNodeArray[i].m_bIsVisited)
					   {
						   continue;
					   }
					   else
					   {
							Edge edge(temp,i,value);
							edgeVec.push_back(edge);
					   }
				   }
			  }
			  //从可选边集合中找出最小的边
			  int edgeIndex=getMinEdge(edgeVec);//定义了一个获取最小边的函数并定义为int 类型,用edgeIndex接受它的值
			  edgeVec[edgeIndex].m_bSelected=true;


			  cout<<edgeVec[edgeIndex].m_iNodeIndexA<<"----"<<edgeVec[edgeIndex].m_iNodeIndexB<<endl;
              cout<<edgeVec[edgeIndex].m_iWeightValue<<endl;

			  m_pEdge[edgeCount]=edgeVec[edgeIndex];
			  edgeCount++;
			  int nextNodeIndex=edgeVec[edgeIndex].m_iNodeIndexB;

			  nodeVec.push_back(nextNodeIndex);//把找到的点放入点集合
			  cout<<m_pNodeArray[nextNodeIndex].m_cData<<endl;
			  m_pNodeArray[nextNodeIndex].m_bIsVisited=true;

		  }
	  }
	  void kruskalTree()
	  {
		  int value=0;
		  int edgeCount=0;

		  //定义存放结点集合的数组
          vector<int> nodeSets;

		  //第一步:取出所有边
          vector<Edge> edgeVec;
		  for(int i=0;i<m_iCapacity;i++)
		  {
			  for(int k=i+1;k<m_iCapacity;k++)
			  {
				  getValueFromMatrix(i,k,value);
				  if(value!=0)
				  {
					  Edge edge(i,k,value);
					  edgeVec.push_back(edge);
				  }
			  }
		  }

		  //第二步:从所有边中取出组成最小生成树的边
		  //1.从找到算法结束条件
		  while(edgeCount<m_iCapacity-1)
		  {
		  //2.边集合中找到最小边
			  int minEdgeIndex=getMinEdge(edgeVec);
			  edgeVec[minEdgeIndex].m_bSelected=true;

		  //3.找出最小边连接的点
		  int nodeAIindex=edgeVec[minEdgeIndex].m_iNodeIndexA;
          int nodeBIindex=edgeVec[minEdgeIndex].m_iNodeIndexB;

		  bool nodeAIsIndex=false;
		  bool nodeBIsIndex=false;

		  int nodeAInSetLabel=-1;
		  int nodeBInSetLabel=-1;
 
		  //4.找出点所在的点集合
		  for(int i=0;i<nodeSets.size();i++)
		  {
			  nodeAIsInset=isInSet(nodeSets[i],nodeAIndex);
			  if(nodeAIsInset)
			  {
				  nodeAInSetLabel=i;
			  }
		  }
		  for(int i=0;i<nodeSets.size();i++)
		  {
			  nodeBIsInset=isInSet(nodeSets[i],nodeBIndex);
			  if(nodeBIsInset)
			  {
				  nodeBInSetLabel=i;
			  }
		  }

		  //5.根据点所在集合的不同做出不同处理
		  if(nodeAInSetLabel==-1&&nodeBInSetLabel==-1)
		  {
			  vector<int> vec;
			  vec.push_back(nodeAIndex);
			  vec.push_back(nodeBIndex);
			  nodeSets.push_bsck(vec);
		  }

		  else if(nodeAInSetLabel==-1&&nodeBInSetLabel!=-1)
		  {
			  nodeSets[nodeBInSetLabel].push_back(nodeAIndex);
		  }

		  else if(nodeAInSetLabel!=-1&&nodeBInSetLabel==-1)
		  {
			  nodeSets[nodeAInSetLabel].push_back(nodeBIndex);
		  }
      
		  else if(nodeAInSetLabel!=-1&&nodeBInSetLabel!=-1&&nodeAInSetLabel!=nodeBInSetLabel)
		  {
			  mergeNodeSet(nodeSets[nodeAInSetLabel],nodeSets[nodeBInSetLabel]);
			  for(int k=nodeBInSetLabel;k<(int)nodeSets.size();k++)
              {
				  nodeSets[k]=nodeSets[k+1];
			  }
		  }

		  else if(nodeAInSetLabel!=-1&&nodeBInSetLabel!=-1&&nodeAInSetLabel==nodeBInSetLabel)
		  {
			  continue;
		  }
		  m_pEdge[edgeCount]=edgeVec[minEdgeIndex];
          edgeCount++;
		  cout<<edgeVec[minEdgeIndex].m_iNodeIIndexA<<"--"<<edgeVec[minEdgeIndex].m_iNodeIIndexB<<endl;
		  cout<<edgeVec[minEdgeIndex].m_iWeightValue<<endl;
		  }
	  }
private:

      bool 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 breadthFirstTraverselmpl(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
		  {
			  breadthFirstTraverselmpl(curVec);
		  }
	  }
	  int 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;
			  }
		  }
          
		  if(minWeight==0)
		  {
               return -1;
		  }

		  for(;i<edgeVec.size();i++)
		  {
			  if(edgeVec[i].m_bSelected)
			  {
				  continue;
			  }
			  else
			  {
				  if(minWeight>edgeVec[i].m_iWeightValue)
				  {
                      minWeight=edgeVec[i].m_iWeightValue;
				      edgeIndex=i;
				  }
			  }
		  }
		  return edgeIndex;
	  }
	  bool isInSet(vector<int> nodeSet,int target)
	  {
          for(int i=0;i<nodeSet.size();i++)
		  {
			  if(nodeSet[i]==target)
			  {
				  return true;
			  }
		  }
		  return false;
	  }
	  void mergeNodeSet(vector<int > &nodeSetA,vector<int> nodeSetB)//第一个是引用
	  {
          for(int i=0;i<nodeSetB.size();i++)
		  {
			  nodeSetA.push_back(nodeSetB[i]);
		  }
	  }
private:

      int m_iCapacity;  //图中最多可以容纳的顶点数 
      int m_iNodeCount; //已经添加的顶点(结点)个数
	  Node *m_pNodeArray; //用来存放顶点数组
	  int *m_pMatrix;     //用来存放邻接矩阵
	  
	  Edge *m_pEdge;

};
int main()
{
    CMap *pMap=new CMap(86);

	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');

	pMap->addNode(pNodeA);
    pMap->addNode(pNodeB);
	pMap->addNode(pNodeC);
	pMap->addNode(pNodeD);
	pMap->addNode(pNodeE);
	pMap->addNode(pNodeF);
   
	pMap->setValueToMatrixForDirectedGraph(0,1,6);
    pMap->setValueToMatrixForDirectedGraph(0,4,5);
	pMap->setValueToMatrixForDirectedGraph(0,5,1);
	pMap->setValueToMatrixForDirectedGraph(1,2,3);
	pMap->setValueToMatrixForDirectedGraph(1,5,2);
	pMap->setValueToMatrixForDirectedGraph(2,5,8);
	pMap->setValueToMatrixForDirectedGraph(2,3,7);
	pMap->setValueToMatrixForDirectedGraph(3,5,4);
	pMap->setValueToMatrixForDirectedGraph(3,4,2);
	pMap->setValueToMatrixForDirectedGraph(4,5,9);

	//pMap->primTree(0);
	pMap->kruskalTree(0);

	pMap->printMatrix();
	cout<<endl;

	pMap->depthFirstTraverse(0);
	cout<<endl;
    
	pMap->resetNode();
	pMap->breadthFirstTraverse(0);
	cout<<endl;

	system("pause");
	return 0;
}


 

猜你喜欢

转载自blog.csdn.net/qq_40354578/article/details/88650260