图论算法

问题1、图的邻接矩阵表示法

#define MAXSIZE 100        //定义最大顶点个数
typedef char   VertexType;  //顶点的类型
struct Graph
{
 VertexType Vertex[MAXSIZE];     //顶点
 int AdjMatrix[MAXSIZE][MAXSIZE];//两个顶点之间的权重
 int vexnum;   //实际顶点数
 int arcnum;   //实际的弧数
};
struct Info
{
 VertexType start;
 VertexType end;
 int weight;
};
void AddVextex(Graph *g){
    for (int i = 0; i<g->vexnum; i++){
         g->Vertex[i] = 'A' + i;
    }
}
void CreateGraph(Graph *g){
     g->vexnum = 5;//确定顶点个数
     g->arcnum = 6; //确定弧数
     //弧长初始化为1000
     for (int i = 0; i<g->vexnum; i++){
           for (int j = 0; j<g->vexnum; j++){
                 g->AdjMatrix[i][j] = 1000;
           }
     }
     Info info[6] = { 'A', 'B', 3,
      'B', 'C', 6, 'C', 'D', 9, 'A', 'D', 12, 'D', 'E', 23, 'D', 'A', 13
      };
     for (int i = 0; i<6; i++){
          g->AdjMatrix[info[i].start - 'A'][info[i].end - 'A'] = info[i].weight;
      } 
}
void Display(Graph g){
    for (int i = 0; i<g.vexnum; i++){
            for (int j = 0; j<g.vexnum; j++){
                   cout << g.AdjMatrix[i][j] << "\t";
            }
            cout << endl;
    }
}

问题2、图的深度优先遍历DFS

void DFS(Graph g){
    int *flag = new int[g.vexnum];//标记顶点是否被访问
    memset(flag, 0, sizeof(int) * 5);
    flag[0] = 1;//访问第一个顶点
    cout << "0" << "->";
    stack<int>   s;
    s.push(0);    //栈保存第一个顶点,先进后出
    while (!s.empty()){
        int cur = s.top();//栈中当前的顶点
        int i = 0;
        for (; i < g.vexnum; i++){
         if (g.AdjMatrix[cur][i] < 1000 && flag[i] == 0){
          flag[i] = 1;
          cout << i << "->";
          s.push(i);
          break;
         }
        }
        if (i==g.vexnum)
               s.pop();
     }
     cout << endl;
}

问题3、宽度优先遍历BFS

void BFS(Graph g){
    int *flag=new int[g.vexnum];
    memset(flag, 0, sizeof(int) * 5);
    flag[0]=1;
    cout<<"0->";
    queue<int>  q;
    q.push(0);
    while(!q.empty()){
        int cur=q.front();
        int index=-1;
        for(int i=0;i<g.vexnum;i++){
            if(g.AdjMatrix[cur][i]<1000&&flag[i]==0){
                    flag[i]=1;
                    cout<<i<<"->";
                    q.push(i);
            }
        }
        if(index==-1){
            q.pop();
        }
    }
}

问题4、图的最小生成树:在一个联通网的所有生成树中所有边的代价之和的那颗生成树。带权的最小生成树要求权重最小。Prime算法(针对于无向图)

void PrimeTree(Graph g,int start){
    int *path=new int[g.vexnum];
    memset(path,0,sizeof(int)*g.vexnum);
    for(int i=0;i<g.vexnum;i++){
            path[i]=g.AdjMatrix[start][i];
    }
    bool *tree=new bool[g.vexnum];
    memset(tree,0,sizeof(bool)*g.vexnum);
    tree[start]=1;  //遍历起点
    int next=0;
    cout<<start<<"->";
    int mindis=0;
    for(int i=1;i<g.vexnum;i++){
        //遍历下一个结点
        int min=INT_MAX;
        for(int j=0;j<g.vexnum;j++){
            if(!tree[j]&&min>path[j]){
                min=path[j];
                next=j;
            }
        }
        //更新path
        tree[next]=1;
        cout<<next<<"->";
        mindis+=min;
        for(int k=0;k<g.vexnum;k++){
            if(!tree[k]&&path[k]>g.AdjMatrix[next][k]){
                path[k]=g.AdjMatrix[next][k];
            }
        }
    }
    cout<<endl;
    cout<<"最小生成树权值为"<<mindis<<endl;
}

//问题5、最短路径Dijkstra算法

//求起点start到任何一点的最短路径
void Dijkstra(Graph g,int start){
        int  path[MAXSIZE];  //保存到当前结点的上一个结点是谁
        int flag[MAXSIZE];            //标记顶点是否被访问过
        memset(flag,0,sizeof(flag));  //
        int dist[MAXSIZE];            //dist保存的是start到当前位置的最短路径值
        forint end=0;end<g.vexnum;end++){
            dist[end]=h.AdjMatrix[start][end];
            if(dist[end]<1000)
                path[end]=start;    //初始化保存到达当前结点的上一个结点
            else 
                path[end]=-1;
        }
        dist[start]=0;    //将start到start的路径设为0
        flag[start]=1;    //访问了第一个结点,将结点并入s
        int next=start;
        for(int i=1;i<g.vexnum;i++){
            int min=INT_MAX;
            for(int j=0;j<g.vexnum;j++){
                if(!flag[j]&&min>dist[j]){
                    next=j;
                    min=dist[j];
                }
            }
            flag[next]=1; //将next并入s
            //更新最短路径信息
            for(int k=0;k<g.vexnum;k++){
                if(!flag[k]&&min<1000&&g.AdjMatrix[next][k]<1000&&g.AdjMatrix[next][k]+min<dist[next]){
                    dist[next]=min;
                    path[k]=next;
                }
            }
        }
   //打印路径信息
    for (int i = 0; i < g.vexnum; i++){
        cout << start << "到" << i << "的距离为:"<<dist[i]<<",最短路径为:";
        for (int j = path[i]; j != -1; j = path[j])
            cout << j << "->";
        cout << endl;
    }
}

最后附上完整的代码

#include<iostream>
#include<stack>
#include<queue>
#include<algorithm>
using namespace std;

#define MAXSIZE 100        //定义最大顶点个数
typedef char   VertexType;  //顶点的类型
struct Graph
{
 VertexType Vertex[MAXSIZE];     //顶点
 int AdjMatrix[MAXSIZE][MAXSIZE];//两个顶点之间的权重
 int vexnum;   //实际顶点数
 int arcnum;   //实际的弧数
};
struct Info
{
 VertexType start;
 VertexType end;
 int weight;
};
void AddVextex(Graph *g){
 for (int i = 0; i<g->vexnum; i++){
  g->Vertex[i] = 'A' + i;
 }
}
void CreateGraph(Graph *g){
     g->vexnum = 5;//确定顶点个数
     g->arcnum = 6; //确定弧数
     //弧长初始化为1000
     for (int i = 0; i<g->vexnum; i++){
       for (int j = 0; j<g->vexnum; j++){
         g->AdjMatrix[i][j] = 1000;
       }
     }
     Info info[8] = { 'A', 'B', 6, 'A', 'E',12,
      'B', 'C', 8, 'C', 'D', 6, 'A', 'D', 7, 'E', 'D', 5, 'E', 'C', 4, 'E', 'B',9
      };
     for (int i = 0; i<8; i++){
          g->AdjMatrix[info[i].start - 'A'][info[i].end - 'A'] = info[i].weight;
          g->AdjMatrix[info[i].end - 'A'][info[i].start - 'A'] = info[i].weight;
      } 
}
void Display(Graph g){
    for (int i = 0; i<g.vexnum; i++){
       for (int j = 0; j<g.vexnum; j++){
          cout << g.AdjMatrix[i][j] << "\t";
      }
      cout << endl;
     }
}
int FindNext(Graph g, int cur){
 for (int i = 1; i<g.vexnum; i++){
  if (g.AdjMatrix[cur][i]<1000)
   return i;
 }
 return -1;
}
void DFS(Graph g){
    int *flag = new int[g.vexnum];//标记顶点是否被访问
    memset(flag, 0, sizeof(int) * 5);
    flag[0] = 1;//访问第一个顶点
    cout << "0" << "->";
    stack<int>   s;
    s.push(0);    //栈保存第一个顶点,先进后出
    while (!s.empty()){
        int cur = s.top();//栈中当前的顶点
        int i = 0;
        for (; i < g.vexnum; i++){
         if (g.AdjMatrix[cur][i] < 1000 && flag[i] == 0){
          flag[i] = 1;
          cout << i << "->";
          s.push(i);
          break;
         }
        }
        if (i==g.vexnum)
               s.pop();
     }
     cout << endl;
}
void BFS(Graph g){
 int *flag = new int[g.vexnum];
 memset(flag, 0, sizeof(int) * 5);
 flag[0] = 1;
 cout << "0->";
 queue<int>  q;
 q.push(0);
 while (!q.empty()){
  int cur = q.front();
  int index = -1;
  for (int i = 0; i<g.vexnum; i++){
   if (g.AdjMatrix[cur][i]<1000 && flag[i] == 0){
    flag[i] = 1;
    cout << i << "->";
    q.push(i);
   }
  }
  if (index == -1){
   q.pop();
  }
 }
 cout << endl;
}
void PrimeTree(Graph g,int start){
    int *path = new int[g.vexnum];
    memset(path, 0, sizeof(int)*g.vexnum);
    for (int i = 0; i<g.vexnum; i++){
        path[i] = g.AdjMatrix[start][i];
    }
    bool *tree = new bool[g.vexnum];
    memset(tree, 0, sizeof(bool)*g.vexnum);
    tree[start] = 1;  //遍历起点
    int next = 0;
    cout << start << "->";
    int mindis = 0;
    for (int i = 1; i<g.vexnum; i++){
        //遍历下一个结点
        int min = INT_MAX;
        for (int j = 0; j<g.vexnum; j++){
            if (!tree[j] && min>path[j]){
                min = path[j];
                next = j;
            }
        }
        //更新path
        tree[next] = 1;
        cout << next << "->";
        mindis += min;
        for (int k = 0; k<g.vexnum; k++){
            if (!tree[k] && path[k]>g.AdjMatrix[next][k]){
                path[k] = g.AdjMatrix[next][k];
            }
        }
    }
    cout << endl;
    cout << "最小生成树权值为" << mindis << endl;
}
//求起点start到任何一点的最短路径
void Dijkstra(Graph g, int start){
    int  path[MAXSIZE];  //保存start到end的最短路径
    int flag[MAXSIZE];            //标记顶点是否被访问过
    memset(flag, 0, sizeof(flag));  //
    int dist[MAXSIZE];            //dist保存的是start到当前位置的最短路径值
    for(int end = 0; end < g.vexnum; end++){
        dist[end] = g.AdjMatrix[start][end];
        //记录经过的路径
        if (dist[end] < 1000)
            path[end] = start;
        else
            path[end] = -1;

    }
    dist[start] = 0;    //将start到start的路径设为0
    flag[start] = 1;    //访问了第一个结点,将结点并入s
    int next = start;
    for (int i = 1; i<g.vexnum; i++){
        int min = INT_MAX;
        for (int j = 0; j<g.vexnum; j++){
            if (!flag[j] && min>dist[j]){
                next = j;
                min = dist[j];
            }
        }
        flag[next] = 1; //将next并入s
        //更新最短路径信息
        for (int k = 0; k<g.vexnum; k++){
            if (!flag[k] && min<1000 && g.AdjMatrix[next][k]<1000 && (g.AdjMatrix[next][k] + min)<dist[k]){
                dist[k] = min+g.AdjMatrix[next][k];
                path[k] = next;   //保存的是到达当前的结点的上一个结点,不断更新
            }
        }
    }
    //打印路径信息
    for (int i = 0; i < g.vexnum; i++){
        cout << start << "到" << i << "的距离为:"<<dist[i]<<",最短路径为:";
        for (int j = path[i]; j != -1; j = path[j])
            cout << j << "->";
        cout << endl;
    }
}
int main(){
 Graph g;
 CreateGraph(&g);
 Display(g);
 DFS(g);
 BFS(g);
 //PrimeTree(g,0);
 Dijkstra(g, 0);

 system("pause");
 return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值