1.图的表示

1)邻接矩阵

   对于普通图,0 /1

    对于网络(或带权图),邻接矩阵的值  0/N

2)邻接表

    如果点多边少,用邻接矩阵很浪费存储空间,这时候用邻接表。

   用邻接表的话,如果想得到顶点的入度,必须检测其他所有顶点对应的边链表,这时候可以建立逆邻接表。

 

3.邻接多重表

邻接多重表在要求每条边处理一次的实际应用中特别有用。


2.图的遍历

1)深度优先遍历(DFS)

给每个点一个位记录是否已经访问;要使用递归。

算法代码:

//从顶点位置v出发

void DFS(Graph G,int v,bool visited[]){

visited[v]=true;

int w=G.getFirstNeighbor(v);

while(w!=-1){

       if(visited[w]==false) 

                 DFS(G,w,visited);

       w=G.getNextNeighbor(v,w);

}

};

      

     

2)广度优先遍历(BFS)

给每个点一个位记录是否已经访问;要用到一个队列;不递归。

void BFS(Graph G){

     Queue q;

     Q.enqueue(v);

     while(!q.empty()){

          int v=q.dequeue();

          int d=G.getFirstNeighbor(v);

          while(d!=-1){

                if(visited(d)==false)

                      visited(d)=true;

                      q.enqueue(d);

                d=G.getNextNeighbor(v);

           }

    }

}


3.最小生成树

1)Kruskal算法

     每次选出一条具有最小权值,且两端点不在同一连通分量上的边,加入生成树。

2)Prim算法

    每次选出一个端点在生成树中,另一个端点不在生成树中的权值最小的边加入生成树中。


4.最短路径

1)非负权值的单元最短路径_Dijkstra算法

(以下转自http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html)

[cpp] view plaincopy

  1. const int  MAXINT = 32767;  

  2. const int MAXNUM = 10;  

  3. int dist[MAXNUM];  

  4. int prev[MAXNUM];  

  5.   

  6. int A[MAXNUM][MAXNUM];  

  7.   

  8. void Dijkstra(int v0)  

  9. {  

  10.     bool S[MAXNUM];                                  // 判断是否已存入该点到S集合中  

  11.       int n=MAXNUM;  

  12.     for(int i=1; i<=n; ++i)  

  13.     {  

  14.         dist[i] = A[v0][i];  

  15.         S[i] = false;                                // 初始都未用过该点  

  16.         if(dist[i] == MAXINT)      

  17.               prev[i] = -1;  

  18.         else   

  19.               prev[i] = v0;  

  20.      }  

  21.      dist[v0] = 0;  

  22.      S[v0] = true;     

  23.     for(int i=2; i<=n; i++)  

  24.     {  

  25.          int mindist = MAXINT;  

  26.          int u = v0;                               // 找出当前未使用的点j的dist[j]最小值  

  27.          for(int j=1; j<=n; ++j)  

  28.             if((!S[j]) && dist[j]<mindist)  

  29.             {  

  30.                   u = j;                             // u保存当前邻接点中距离最小的点的号码   

  31.                   mindist = dist[j];  

  32.             }  

  33.          S[u] = true;   

  34.          for(int j=1; j<=n; j++)  

  35.              if((!S[j]) && A[u][j]<MAXINT)  

  36.              {  

  37.                  if(dist[u] + A[u][j] < dist[j])     //在通过新加入的u点路径找到离v0点更短的路径    

  38.                  {  

  39.                      dist[j] = dist[u] + A[u][j];    //更新dist   

  40.                      prev[j] = u;                    //记录前驱顶点   

  41.                   }  

  42.               }  

  43.      }  

  44. }  

算法实例

先给出一个无向图

用Dijkstra算法找出以A为起点的单源最短路径步骤如下



2)任意权值的单源最短路径_Bellman-Ford算法

主要是两点:

1.此路径最多有n-1条边

2.递推式 



3)所有顶点之间的最短路径_Floyd算法

[cpp] view plaincopy

  1. typedef struct            

  2. {          

  3.     char vertex[VertexNum];                                //顶点表           

  4.     int edges[VertexNum][VertexNum];                       //邻接矩阵,可看做边表           

  5.     int n,e;                                               //图中当前的顶点数和边数           

  6. }MGraph;   

  7.   

  8. void Floyd(MGraph g)  

  9. {  

  10.    int A[MAXV][MAXV];  

  11.    int path[MAXV][MAXV];  

  12.    int i,j,k,n=g.n;  

  13.    for(i=0;i<n;i++)  

  14.       for(j=0;j<n;j++)  

  15.       {     

  16.              A[i][j]=g.edges[i][j];  

  17.             path[i][j]=-1;  

  18.        }  

  19.    for(k=0;k<n;k++)  

  20.    {   

  21.         for(i=0;i<n;i++)  

  22.            for(j=0;j<n;j++)  

  23.                if(A[i][j]>(A[i][k]+A[k][j]))  

  24.                {  

  25.                      A[i][j]=A[i][k]+A[k][j];  

  26.                      path[i][j]=k;  

  27.                 }   

  28.      }   

  29. }  



5.AOV网络(activity on vertice)

拓扑排序:

每次选出入度为0的顶点,然后去掉这个顶点以及它的发出边。