Kruskal算法

来源:互联网 发布:网站seo初学者教程 编辑:程序博客网 时间:2024/06/06 00:12
图的类定义,Kruskal算法求最小生成树
graph.h中-----------------------------------------
#ifndef GRAPH_H
#define GRAPH_H
class Graph
{
private:
 int n;
 int A[10][10];
public:
//图的初始化
 Graph(int len = 10);
 int getvertex(){ return n;}
 int countEdges();
 void insertEdge(int v1, int v2, int weight);
 void deleteEdge(int v1, int v2);
 void drawGraph();
//判断图的连通性
 void throughDFS(int v);
 bool through();
//Kruskal算法
 Graph* kruskal(Graph* &g);
 bool cycleDetectionDFS(int v);
 bool cycleDetection();
 int seekMin(int m);
//Dijkstra算法
 Graph* Dijkstra(Graph* &g);
 int seekMax(int m);
//图的输出
 void DFS(int v);
 void DepthFirstSearch();
 void printEdges();
};
#endif
graph.cpp中--------------------------------------
#include"graph.h"
#include<iostream>
using namespace std;
//图的初始化---------------------------------------------------------------------
Graph::Graph(int len)
{
 n = len;
 for(int i= 1; i<=n; i++)
  for(int j=1; j<=n; j++)
   A[i][j] = 1000;
}
int Graph::countEdges()  //边数
{
 int number = 0;
 for(int i=1;i<=n;i++)
  for(int j=1;j<i;j++)
   if(A[i][j] < 1000)
    number++;
 return number;
}
void Graph::insertEdge(int v1, int v2, int weight) //添加边
{
 if(v1>0 && v1<=n && v2>0 && v2<=n){
  A[v1][v2] = weight;  //无向图,邻接矩阵沿对角线对称
  A[v2][v1] = weight;
 }
}
void Graph::deleteEdge(int v1, int v2)  //删除边
{
 if(v1>0 && v1<=n && v2>0 && v2<=n && A[v1][v2]<1000){
  A[v1][v2] = 1000;
  A[v2][v1] = 1000;
 }
}
void Graph::drawGraph()  //画图
{
 int v1, v2, w, t = 1;
 cout<<"你要在哪两个顶点之间画边?\n请输入顶点对及边的权值(输入完毕按0 0):"<<endl;
 cout<<"("<<t<<"), ";cin>>v1>>v2;
 while(v1!=0 && v2!=0)
 {
  cout<<"     权值 = ";
  cin>>w;
  insertEdge(v1, v2, w);
  cout<<"("<<++t<<"), ";cin>>v1>>v2;
 }
}
//判断图的连通性-----------------------------------------------------------------
int visited[10], counter, edges[10][10];
void Graph::throughDFS(int v)
{
 visited[v] = 1;
 for(int i=1;i<=n;i++)
  if(A[v][i]<1000 && visited[i] == 0)
   throughDFS(i);
}
bool Graph::through()
{
 counter = 0;
 for(int i=1;i<=n;i++)
  visited[i] = 0;
 for(int j=1;j<n;j++)
  if(visited[j]==0)
  {
   counter++;
   throughDFS(j);
  }
 if(counter == 1)
  return true;
 else
  return false;
}
//Kruskal算法的子函数------------------------------------------------------------
bool Graph::cycleDetection()  //环的检测
{
 for(int i=1;i<=n;i++)
 {
  visited[i] = 0;
  for(int j=0;j<=n;j++)
   edges[i][j] = 0;
 }
 return cycleDetectionDFS(1);
}
bool Graph::cycleDetectionDFS(int v)
{
 visited[v] = 1;
 for(int i=1; i<=n; i++)
  if(A[v][i]<1000)
  {
   if(visited[i] == 0)
   {
    visited[i] = 1;
    edges[v][i] = 1;
    cycleDetectionDFS(i);
   }
   else if(edges[i][v] == 0)
    return true;
  }
 return false;
}
int Graph::seekMin(int m)//寻找大于m的最小权值
{
 int i, j, min = 1000;
 for(i=1;i<=n;i++)
  for(j=1;j<=i;j++)
   if(A[i][j]<min && A[i][j]>m)
    min = A[i][j];
 return min;
}
//另一种方法:Kruskal算法镜像的子函数-------------------------------------------------------------------
int Graph::seekMax(int m)//寻找小于m的最大权值
{
 int i, j, max = 0;
 for(i=1;i<=n;i++)
  for(j=1;j<=i;j++)
   if(A[i][j]>max && A[i][j]<m)
    max = A[i][j];
 return max;
}
//图的输出----------------------------------------------------------------------
void Graph::DepthFirstSearch()  //图的深度优先遍历
{
 for(int i=1;i<=n;i++)
  visited[i] = 0;
 for(int j=1;j<=n;j++)
  if(visited[j]==0)
   DFS(j);
}
void Graph::DFS(int v)
{
 cout<<v<<" ";
 visited[v] = 1;
 for(int i=1;i<=n;i++)
  if(A[v][i]<1000 && visited[i]==0)
   DFS(i);
}
void Graph::printEdges()  //输出边集
{
 cout<<"边集为:";
 for(int i=1;i<=n;i++)
  for(int j=n;j>=i;j--)
   if(A[i][j] < 1000)
    cout<<"("<<i<<","<<j<<") = "<<A[i][j]<<"   ";
 cout<<endl;
}
kruskal.cpp中------------------------------------
#include"graph.h"
Graph * Graph::kruskal(Graph* &g)
{
 int i, j, side = 0, min = 0;
 while(side < n-1)
 {    //控制循环:共加入n-1条边
  min = seekMin(min);//找权比min大的最小边
  for(i=1;i<=n;i++)
   for(j=1;j<=i;j++)
    if(A[i][j] == min)
    {
     g->insertEdge(i, j, min);
     side++;      
     if(g->cycleDetection())
     {       //判断是否成环
      g->deleteEdge(i, j);
      side--;
     }
    }
 }
 return g;
    
}
similarDijkstra.cpp中-----------------------------------
#include"graph.h"
Graph* Graph::Dijkstra( Graph* &g)
{
 int i, j, side = g->countEdges(), max = 1000;
 while(side > n-1)
 {    //控制循环:直到剩下n-1条边
  max = g->seekMax(max);//找权比max小的最大边
  for(i=1;i<=n;i++)
   for(j=1;j<=i;j++)
    if(A[i][j] == max)
    {
     g->deleteEdge(i, j);
     side--;      
     if(!g->through()) //如不连通则将其加回
     {       
      g->insertEdge(i, j, max);
      side++;
     }
    }
 }
 return g;
}
main.cpp中--------------------------------------
#include"graph.h"
#include<iostream>
using namespace std;
void main()
{
 int v;
 cout<<"-----------------------图的构造-------------------------------";
 cout<<"\n请输入图的顶点数( < 10 ): N(v) = ";
 cin>>v;
 Graph graph(v);
 Graph minTree(v);
 Graph *g = &minTree;
 graph.drawGraph();
 cout<<"您画的图的深度优先遍历结果为:";
 graph.DepthFirstSearch();
 cout<<endl;
 graph.printEdges();
 if(!graph.through())
 {
  cout<<"\n您画的不是连通图,无最小生成树!"<<endl;
  exit(1);
 }
 else
 {
  char a;
  cout<<"---------------------求最小生成树-----------------------------";
  cout<<"\n请选择应用哪一种方法求最小生成树( k = Kruskal,  d = similarDijkstra):";
  cin>>a;
  if(a=='k' || a=='K')
  {
   cout<<"\n应用Kruskal算法求得最小生成树,其深度优先遍历结果为:";
   g = graph.kruskal(g);
   g->DepthFirstSearch();
   cout<<endl;
   g->printEdges();
   cout<<endl;
  }
  else if(a=='d' || a=='D')
  {
   minTree = graph;
   cout<<"\n应用Dijkstra算法求得最小生成树,其深度优先遍历结果为:";
   g = graph.Dijkstra(g);
   g->DepthFirstSearch();
   cout<<endl;
   g->printEdges();
   cout<<endl;
  }
  else
  {
   cout<<"无此种方法!";
   exit(1);
  }
 }
}
0 0
原创粉丝点击