Asp.net 学习资料

伦惠峰

求图的最短路径和最小生成树

const int MaxValue=10000;

//定义邻接矩阵类型
typedef int** adjmatrix;

//初始化图的邻接矩阵
void InitGMatrix(adjmatrix& GA, int n);

//建立图的邻接矩阵
void CreateMatrix(adjmatrix GA, int n, int k1, int k2);
       //k1为0则无向否则为有向, k2为0则无权否则为有权

//从初始点vi出发深度优先搜索由邻接矩阵GA表示的图
void dfsMatrix(adjmatrix GA, bool*& visited, int i, int n);

//从初始点vi出发广度优先搜索由邻接矩阵GA表示的图
void bfsMatrix(adjmatrix GA, bool*& visited, int i, int n);

//定义邻接表中的边结点类型
struct edgenode {
 int adjvex;      //邻接点域
 int weight;      //权值域
 edgenode* next;  //指向下一个边结点的链域
};

//定义邻接表类型
typedef edgenode** adjlist;

//初始化图的邻接表
void InitGAdjoin(adjlist& GL, int n);

//建立图的邻接表
void CreateAdjoin(adjlist GL, int n, int k1, int k2);

//从初始点vi出发深度优先搜索由邻接表GL表示的图
void dfsAdjoin(adjlist GL, bool*& visited, int i, int n);

//从初始点vi出发广度优先搜索由邻接表GL表示的图
void bfsAdjoin(adjlist GL, bool*& visited, int i, int n);

//根据图的邻接矩阵得到图的邻接表
void graphChange(adjmatrix GA, adjlist GL, int n);
//定义边集数组中的元素类型
struct edge {
 int fromvex;  //起点域
 int endvex;   //终点域
 int weight;   //权域
};

//定义边集数组类型
typedef edge* edgeset;
//输出边集数组中的每条边
void OutputEdgeSet(edgeset GE, int e);

//根据图的邻接矩阵生成图的边集数组
void ChangeEdgeSet(adjmatrix GA, edgeset GE, int n, int e);
#include<iostream.h>


//初始化图的邻接表
void InitGAdjoin(adjlist& GL, int n)
{
 GL=new edgenode*[n];
 for(int i=0; i<n; i++) GL[i]=NULL;
}

//检查输入的边序号是否越界,若越界则重输
void Check(int n, int& i, int& j);

//初始化图的邻接矩阵
void InitGMatrix(adjmatrix& GA, int n)
{
 GA=new int*[n];
 int i,j;
 for(i=0; i<n; i++)
  GA[i]=new int [n];
 for(i=0; i<n; i++)
  for(j=0; j<n; j++)
   if(i==j) GA[i][j]=0;
   else GA[i][j]=MaxValue;
}

//建立图的邻接矩阵
void CreateMatrix(adjmatrix GA, int n, int k1, int k2)
       //k1为0则无向否则为有向, k2为0则无权否则为有权
{
 int i,j,k,e,w;
 cout<<"输入图的总边数:";
 cin>>e;
 if(k1==0 && k2==0) {  //建立无向无权图
  cout<<"输入"<<e<<"条无向无权边的起点和终点序号!"<<endl;
     for(k=1; k<=e; k++) {
            cin>>i>>j; 
   Check(n,i,j);
      GA[i][j]=GA[j][i]=1;
  }
 }
 else if(k1==0 && k2!=0) {  //建立无向有权图
  cout<<"输入"<<e<<"条无向带权边的起点和终点序号及权值!"<<endl;
     for(k=1; k<=e; k++) {
            cin>>i>>j>>w; 
   Check(n,i,j);
      GA[i][j]=GA[j][i]=w;
  }
 }
 else if(k1!=0 && k2==0) {  //建立有向无权图
  cout<<"输入"<<e<<"条有向无权边的起点和终点序号!"<<endl;
     for(k=1; k<=e; k++) {
            cin>>i>>j; 
   Check(n,i,j);
      GA[i][j]=1;
  }
 }
 else if(k1!=0 && k2!=0) {  //建立有向有权图
  cout<<"输入"<<e<<"条有向有权边的起点和终点序号及权值!"<<endl;
     for(k=1; k<=e; k++) {
            cin>>i>>j>>w; 
   Check(n,i,j);
      GA[i][j]=w;
  }
 }
}

//从初始点vi出发深度优先搜索由邻接矩阵GA表示的图
void dfsMatrix(adjmatrix GA, int*& visited, int i, int n)
{
 cout<<i<<' '; 
 visited[i]=1;        //标记vi已被访问过
 for(int j=0; j<n; j++)  //依次搜索vi的每个邻接点
  if(i!=j && GA[i][j]!=MaxValue && !visited[j])
   dfsMatrix(GA,visited,j,n); 
}

//从初始点vi出发广度优先搜索由邻接矩阵GA表示的图
void bfsMatrix(adjmatrix GA, int*& visited, int i, int n)
{
 const int  MaxLength=30;
  //定义一个队列q,其元素类型应为整型
 int q[MaxLength]={0};
  //定义队首和队尾指针
 int front=0, rear=0;
  //访问初始点vi
 cout<<i<<' '; 
  //标记初始点vi已访问过
 visited[i]=1; 
  //将已访问过的初始点序号i入队
 q[++rear]=i; 
  //当队列非空时进行循环处理
 while(front!=rear) { 
      //删除队首元素,第一次执行时k的值为i
  front=(front+1)%MaxLength;
  int k=q[front];
      //依次搜索vk的每一个可能的邻接点
  for(int j=0; j<n; j++)
  { 
   if(k!=j && GA[k][j]!=MaxValue && !visited[j]) {
    cout<<j<<' ';            //访问一个未被访问过的邻接点vj
    visited[j]=true;         //标记vj已访问过
    rear=(rear+1)%MaxLength; //顶点序号j入队
    q[rear]=j;
   }
  }
 }
}

 

//检查输入的边序号是否越界,若越界则重输
void Check(int n, int& i, int& j)
{
     while(1) {
  if(i<0 || i>=n ||j<0 || j>=n)
   cout<<"输入有误,请重输!";
  else return;
     cin>>i>>j;
 }
}

//利用普里姆算法从顶点v0出发求出用邻接矩阵GA表示的图的最小生成树,
//最小生成树的边集存于数组CT中
void Prim(adjmatrix GA, edgeset CT, int n)
{
 int i,j, k, min, t, m, w;
  //给CT赋初值,对应为v0依次到其余各顶点的边
 for(i=0; i<n-1; i++) {
  CT[i].fromvex=0;
  CT[i].endvex=i+1;
  CT[i].weight=GA[0][i+1];
 }
  //进行n-1次循环,每次求出最小生成树中的第k条边
 for(k=1; k<n; k++)
 {
   //从CT[k-1]~CT[n-2]中查找最短边CT[m]
  min=MaxValue;
  m=k-1;
  for(j=k-1; j<n-1; j++)
   if(CT[j].weight<min) {
    min=CT[j].weight;
    m=j;
   }
   //把最短边对调到第k-1下标位置
  edge temp=CT[k-1];
  CT[k-1]=CT[m];
  CT[m]=temp;
   //把新并入最小生成树T中的顶点序号赋给j
  j=CT[k-1].endvex;
   //修改有关边,使T中到T外的每一个顶点各保持
   //一条到目前为止最短的边
  for(i=k; i<n-1; i++) {
   t=CT[i].endvex;
   w=GA[j][t];
   if(w<CT[i].weight) {
    CT[i].weight=w;
    CT[i].fromvex=j;
   }
  }
 }
}

//初始化图的边集数组
void InitGEdge(edgeset& GE, int e)
{
 GE=new edge[e];
 for(int i=0; i<e; i++) GE[i].weight=0;
}

//输出边集数组中的每条边
void OutputEdgeSet(edgeset GE, int e)
{
 cout<<'{';
 for(int i=0; i<=e-2; i++) {
  cout<<'('<<GE[i].fromvex<<','<<GE[i].endvex<<')';
  cout<<GE[i].weight<<", ";
 }
 if(e>0) {
  cout<<'('<<GE[e-1].fromvex<<','<<GE[e-1].endvex<<')';
  cout<<GE[e-1].weight<<' ';
 }
 cout<<'}'<<endl;
}
//求最短路径(狄克斯特拉算法)
void PATH(adjlist path,int m,int j)
//由顶点m的最短距离和顶点j构成到顶点j的目前最短路径
{
 edgenode *p,*q,*s;
 //把顶点j的当前路径清除掉
 p=path[j];
 while(p!=NULL){
  path[j]=p->next;
  delete p;
  p=path[j];
 }
 //把顶点m的最短路径拷贝过来到顶点j的最短路径上
 p=path[m];
 while(p!=NULL){
  q=new edgenode;
  q->adjvex=p->adjvex;
  if(path[j]==NULL)
   path[j]=q;
  else
   s->next=q;
  s=q;
  p=p->next;
 }
 //把顶点j加入到path[j]单链表的最后,形成新的最短路径
 q=new edgenode;
 q->adjvex=j;
 q->next=NULL;
    s->next=q;
}

 

void Dijkstra(adjmatrix GA, int dist[],adjlist path,int i,int n)
//求出图GA中从i点到、其他的每个结点的的最短距离和最短路径,它们分别放在dist和path数组中。
{
 int j,k,w,m;
 int *s=new int [n];
 for(j=0;j<n;j++){
  if(j==i)
   s[j]=1;
  else
   s[j]=0;
  dist[j]=GA[i][j];
  if(dist[j]<MaxValue&&j!=i){
   edgenode *p1=new edgenode;
   edgenode *p2=new edgenode;
   p1->adjvex=i;
   p2->adjvex=j;
   p2->next=NULL;
   p1->next=p2;
   path[j]=p1;
  }
  else
   path[j]=NULL;
 }
 //共进行n-2次循环,每次求出从源点i到终点m的最短路径及长度
 for(k=1;k<=n-2;k++)
 {
  //求出第k个终点m
  w=MaxValue;m=i;
  for(j=0;j<n;j++)
   if(s[j]==0&&dist[j]<w){
    w=dist[j];
    m=j;
   }
   //如果条件成立,就把顶点m并入集合s中,否则就退出循环,因为剩下的顶点
   //他们的的最短路径长度都是MaxValue,无需再计算下去
   if(m!=i)
    s[m]=1;
   else
    break;
   //对S元素为0的对应的dist和path中的元素都做必要的修改
   for(j=0;j<n;j++)
    if(s[j]==0&&dist[m]+GA[m][j]<dist[j]){
     dist[j]=dist[m]+GA[m][j];
     PATH(path,m,j);
    }
 }
}
//输出邻接表
void Outadjlist(adjlist GL,int n)
{
 for(int k=0;k<n;k++)
 {
  edgenode *p=GL[k];
  while(p!=NULL){
   cout<<p->adjvex<<" ";
   p=p->next;
  }
  cout<<endl;
 }
}
   
void Outminload(adjlist GL,int begin,int end)
{
 edgenode *p=GL[end];
  while(p!=NULL){
   cout<<p->adjvex;
   if(p->next==NULL) break;
   cout<<"--->";
   p=p->next;
  }
  cout<<endl;

}

void main()
{
 

 int n;
     
 int begin,end;
 cout<<"输入顶点的个数"<<endl;
 cin>>n;
    int *visited=new int[n];
 for(int k=0;k<n;k++)
 visited[k]=0;
 adjmatrix GA;
 InitGMatrix(GA,n);
 CreateMatrix(GA,n,1,1);
 cout<<"这个图是"<<endl;
 for(int m=0;m<n;m++)
  for(int s=0;s<n;s++)
  {
   cout<<GA[m][s]<<" ";
   if(s==n-1) cout<<endl;
  }
 //cout<<"图的深度遍历:"<<endl;
    //dfsMatrix(GA,visited,0,n);
    //cout<<endl;
    //cout<<"图的广度遍历:"<<endl;
    //bfsMatrix(GA,visited,0,n);
    //cout<<endl;
 //dfsMatrix(GA,visited,1,n);
 //edgeset GE;
 //InitGEdge(GE,n-1);
 //Prim(GA,GE,n);
 //cout<<"最小生成树"<<endl;
 //OutputEdgeSet(GE,6);//求出最小生成树
 

 


  while(1){
   
     


   
   cout<<"*****************************************"<<endl;
   cout<<"        求图的最小距离和最小路径         "<<endl;
   cout<<"*****************************************"<<endl;


   ////////////////////////////////
   int *dist=new int[n];
   adjlist path;
         InitGAdjoin(path,n);
         cout<<"请输入任意两点,求最短路径"<<endl;
         cin>>begin>>end;
         Dijkstra(GA,dist,path,begin,n);
         cout<<"最小距离是"<<endl;
         cout<<dist[end]<<endl;
         cout<<"最小路径是"<<endl;
         Outminload(path,begin,end);
   
  }


}

posted on 2007-08-13 21:45  伦惠峰  阅读(1108)  评论(0)    收藏  举报

导航