//采用的是链式存储:
//头文件:
struct Edge 
{
 friend class Graph_List;
 int VerAdj;  //邻接顶点序号,从0开始
 int cost;  //cost
 Edge *link;  //next point of Edge
};
struct Vertex
{
 friend class Graph_List;
 int VerName; //顶点的名称
 Edge *adjacent; //边链表的头指针
 
};
class Graph_List
{
private:
 Vertex *Head;
 int graphsize;
 
public:
 Graph_List();
 virtual ~Graph_List();
 
 //检查图是否为空
 int GraphEmpty(void) const; 
 //检测图中顶点个数是否已经超过规定的顶点个数上界
 int GraphFull(void) const; 
 //图中顶点的个数
 int NumberOfVertices(void) const;
 //图中边的个数
 int NumberOfEdges(void) const;
 //返回指定边的权值
 int GetWeight(const int &v1, const int &v2);
 //设置指定边的权值
 bool SetWeight(const int v1, const int v2, int weight);
 //返回顶点v的邻接顶点表
 Edge* GetNeighbors(const int v);
 //返回序号为v的顶点的第一个邻接顶点的序号
 int GetFirstNeighbors(const int v);
 //返回序号为v1的顶点相对于序号为v2的顶点的下一个邻接顶点的序号
 int GetNextNeighbors(const int v1, const int v2);
 //向图中插入一个顶点
 void InsertVertex(const int &v);
 //向图中插入一个边
 void InsertEdge(const int &v1, const int &v2, int weight);
 //从图中删除一个顶点
 void DeleteVertex(const int &v);
 //从图中删除一个边
 void DeleteEdge(const int &v1, const int &v2);
 //递归进行以第一个顶点开始的深度优先搜索
 void DepthFirstSearch();
 //采用递归的方法从指定顶点v开始深度优先搜索
 void Graph_List::RDFS(const int v, int *visited);
 //采用迭代的方法从指定顶点v开始深度优先搜索
 void DFS(const int v);
 //从指定的顶点v进行开始广度优先搜索
 void BFS(const int s);
 //输出图的拓扑排序
 void TopoOrder();
 //输出图的的关键路径
 void CriticalPath();
 //在非权图中求指定顶点到其他所有顶点的最短路径
 void ShortestPath(const int v);
 //在正权图中求指定顶点到其他所有顶点的最短路径
 void DShortestPath(const int v);
 //在正权图中求每对顶点间的最短路径
 void AllLength();
 //构造图的最小支撑树的普里姆算法
 void Prim();
 //构造图的最小支撑树的克鲁斯卡尔算法
 void Kruskar();
};

//源文件:
#include <iostream.h>
#include "LQueue.h"
#include "LStack.h"
#include "Graph_List.h"
const int MaxGraphSize = 999;
const int MaxWeight = 10000;
const int max = 1000000000;
Graph_List::Graph_List()
{
 int e, from, to, weight;
 Head = new Vertex[MaxGraphSize];
 cin >> graphsize;
 for (int i = 0; i < graphsize; i++)
 {
  Head[i].VerName = i;
  Head[i].adjacent = NULL;
 }
 cin >> e;
 //将新边插入图中
 for (i = 0; i < e; i++)
 {
  cin >> from >> to >>weight;
  Edge *p = new Edge;
  p->VerAdj = to;
  p->cost = weight;
  p->link = NULL;
  Edge *q = Head[from].adjacent;
  if (q == NULL)
   Head[from].adjacent = p;
  else
  {
   while(q->link != NULL)
    q = q->link;
   q->link = p; 
  }  
 }
}
Graph_List::~Graph_List()
{
 for (int i = 0; i < graphsize; i++)
 {
  Edge *p = Head[i].adjacent;
  while(p != NULL)
  {
   Head[i].adjacent = p->link;
   delete p;
   p = Head[i].adjacent;
  }
 }
 delete []Head;
}
//检查图是否为空
int Graph_List::GraphEmpty(void) const
{
 return (graphsize ? 1 : -1);
}
//检测图中顶点个数是否已经超过规定的顶点个数上界
int Graph_List::GraphFull(void) const
{
 return ((graphsize > MaxGraphSize) ? 1 : -1);
} 
//图中顶点的个数
int Graph_List::NumberOfVertices(void) const
{
 return graphsize;
}
//图中边的个数
int Graph_List::NumberOfEdges(void) const
{
 int num = 0 ;
 for (int i = 0; i < graphsize; i++)
 {
  Edge *q = Head[i].adjacent;
  if (q != NULL)
  {
   ++ num;
   while(q->link != NULL)
   {
    q = q->link;
    ++ num;
   }
  }
 }
 return num;
}
//返回指定边的权值
int Graph_List::GetWeight(const int &v1, const int &v2)
{
 if (v1 == -1 || v2 == -1)
  return -1;
 Edge *p = Head[v1].adjacent;
 while(p != NULL)
 {
  if (p->VerAdj == v2)
   return p->cost;
  p = p->link;
 }
 return -1;
}
//设置指定边的权值
bool Graph_List::SetWeight(const int v1, const int v2, int weight)
{
 if (v1 == -1 || v2 == -1)
  return false;
 
 Edge *p = Head[v1].adjacent;
 while(p != NULL)
 {
  if (p->VerAdj == v2)
  {
   p->cost = weight;
   return true;
  }
  p = p->link;
 }
 return false;
}
//返回顶点v的邻接顶点表
Edge* Graph_List::GetNeighbors(const int v)
{
 if(v == -1)
  return NULL;
 else
  return Head[v].adjacent; 
}
//返回序号为v的顶点的第一个邻接顶点的序号
int Graph_List::GetFirstNeighbors(const int v)
{
 if (v == -1)
  return -1;
 Edge *p = Head[v].adjacent;
 if (p != NULL)
  return p->VerAdj;
 else
  return -1;
}
//返回序号为v1的顶点相对于序号为v2的顶点的下一个邻接顶点的序号
int Graph_List::GetNextNeighbors(const int v1, const int v2)
{
 if ((v1 != -1) && (v2 != -1))
 {
  Edge *p = Head[v1].adjacent;
  while(p->VerAdj != v2 && p != NULL)
   p = p->link;
  if (p == NULL)
   return -1;
  p = p->link;
  if (p == NULL)
   return -1;
  return p->VerAdj; 
 }
 return -1;
}
//向图中插入一个顶点
void Graph_List::InsertVertex(const int &v)
{
 if (v < graphsize)
  cout <<"This node is existed!"<<endl;
 Head[++graphsize].VerName = v;
 Head[graphsize].adjacent = NULL;
}
//向图中插入一个边
void Graph_List::InsertEdge(const int &v1, const int &v2, int weight)
{
 if (v1 == -1 || v2 == -1)
  return;
 if (weight == 0 || weight >= MaxWeight)
  return;
 if (GetWeight(v1, v2) == -1)
  cout <<"This is an edge existed!"<<endl;
 else
 {
  Edge *p = new Edge;
  p->VerAdj = v2;
  p->cost = weight;
  p->link = NULL;
  Edge *q = Head[v1].adjacent;
  if (q == NULL)
   Head[v1].adjacent = p;
  else
  {
   while(q->link != NULL)
    q = q->link;
   q->link = p;
  }
 }
}
//从图中删除一个顶点
void Graph_List::DeleteVertex(const int &v)
{
 if (v == -1)
  cout <<"This vertex is not in the graph "<<endl;
 else
 {
  graphsize --;
  for (int i = 0; i < graphsize; i++)
  {
   Edge *p = Head[i].adjacent;
   if (i == v)
   {
    while(p != NULL)
    {
     Head[i].adjacent = p->link;
     delete p;
     Edge *p = Head[i].adjacent;
    }
   }
   else
   {
    while((p->link->VerAdj != v) && (p->link != NULL))
    {
     if (p->VerAdj > v)
      p->VerAdj --;
     p = p->link;
    }
    if (p->link->VerAdj == v)
    {
     Edge *q = p->link;
     p->link = q->link;
     delete p;
    }
    while(p->link != NULL)
    {
     if (p->VerAdj > v)
      p->VerAdj --;
     p = p->link;
    }
   }
  }
 }
 graphsize --;
}
//从图中删除一个边
void Graph_List::DeleteEdge(const int &v1, const int &v2)
{
 if (v1 == -1 || v2 == -1)
  return;
 Edge *p = Head[v1].adjacent;
 Edge *q = NULL;
 while(p->link != NULL)
 {
  if (p->link->VerAdj == v2)
  {
   q = p->link;
   p->link = q->link;
   delete q;
  }
 }
 p = Head[v2].adjacent;
 while(p->link != NULL)
 {
  if (p->link->VerAdj == v1)
  {
   q = p->link;
   p->link = q->link;
   delete q;
  }
 }
}
//递归进行以第一个顶点开始的深度优先搜索
void Graph_List::DepthFirstSearch()
{
 int *visited = new int[graphsize];
 for (int i = 0; i < graphsize; i++)
  visited[i] = 0;
 RDFS(0, visited);
 delete [] visited;
}
//采用递归的方法从指定顶点v开始深度优先搜索
void Graph_List::RDFS(const int v, int *visited)
{
 cout<<v<<" ";
 visited[v] = 1;
 int w = GetFirstNeighbors(v);
 while(w != -1)
 {
  if (!visited[w])
   RDFS(w, visited);
  w = GetNextNeighbors(v, w);
 }
}
//采用迭代的方法从指定顶点v开始深度优先搜索
void Graph_List::DFS(const int v)
{
 int *visited = new int[graphsize];
 int k;
 int w;
 for( k = 0; k < graphsize; k ++)
  visited[k] = 0;
 LStack<int> S;
 S.Push(v);
 while(!S.IsEmpty())
 {
  w = S.Pop();
  visited[w] = 1;
  cout <<w<<" ";
  k = GetFirstNeighbors(w);
  while(k != -1)
  {
   if (visited[k] == 0)
    S.Push(k);
   k = GetNextNeighbors(w, k);  
  }
 }
 delete [] visited;
}
//从指定的顶点v进行开始广度优先搜索
void Graph_List::BFS(const int s)
{
 int v, w;
 int *visited = new int[graphsize];
 for (int k = 0; k < graphsize; k ++)
  visited[k] = 0;
 cout<<s<<" ";
 visited[s] = 1;
 LQueue<int> q;
 q.QInsert(s);
 while(q.IsEmpty())
 {
  q.QDelete(v);
  w = GetFirstNeighbors(v);
  while(w != -1)
  {
   if (! visited[w])
   {
    cout << w << "";
    visited[w] = 1;
    q.QInsert(w);
   }
   w = GetNextNeighbors(v, w);
  }  
 }
 delete []visited;
}
//输出图的拓扑排序
void Graph_List::TopoOrder()
{
 int n = graphsize;
 int top = -1;
 int j = -1;
 int k = -1;
 int i = -1;
 int *count = new int[n];
 Edge *p;
 for (i = 0; i < n; i++) count[i] = 0;
 for (i = 0; i < n; i++)
 {
  p = Head[i].adjacent;
  while(p != NULL)
  {
   count[p->VerAdj] ++;
   p = p->link;
  }
 }
 for(i = 0; i < n; i++)
  if (count[i] == 0)
  {
   count[i] = top;
   top = i;
  }
 for (i = 0; i < n; i++)
 {
  if (top == -1)
   cout<<"There is a cycle in network!"<<endl;
  else
  {
   j = top;
   top = count[top];
   cout<<j<<" ";
   p = Head[i].adjacent;
   while(p != NULL)
   {
    k = p->VerAdj;
    if(-- count[k] == 0)
    {
     count[k] = top;
     top = k;
    }
    p= p->link;
   }
  } 
 }
 delete []count;
}
//输出图的的关键路径
void Graph_List::CriticalPath()
{
 int i, k, e, l;
 int n = graphsize;
 int *ve = new int[n];
 int *vl = new int[n];
 Edge *p = NULL;
 for(i = 0; i < n; i++) ve[i] = 0;
 for (i = 0; i < n; i++)
 {
  p = Head[i].adjacent;
  while (p != NULL)
  {
   k = p->VerAdj;
   if (ve[i] + p->cost > ve[k])
    ve[k] = ve[i] + p->cost;
   p = p->link;  
  }
 }
 for (i = 0; i < n; i++)
  vl[i] = ve[n-1];
 for (i = n-2; i >= 0; i--)
 {
  p = Head[i].adjacent;
  while (p != NULL)
  {
   k = p->VerAdj;
   if (vl[i] + p->cost < vl[k])
    vl[k] = vl[i] - p->cost;
   p = p->link;  
  }
 }
 for(i = 0; i < n; i++)
 {
  p = Head[i].adjacent;
  while (p != NULL)
  {
   k = p->VerAdj;
   e = ve[i];
   l = vl[k] - p->cost;
   if (l == e)  
    cout<<"<"<<i<<","<<k<<">"<<"is Critical Activity!"<<endl;
   p = p->link;
  }
 }
 delete []ve;
 delete []vl;
}
//在非权图中求指定顶点到其他所有顶点的最短路径
void Graph_List::ShortestPath(const int v)
{
 int i, u, k;
 Edge *p;
 int n = graphsize;
 int *path = new int[n];
 int *dist = new int[n];
 for (i = 0; i < n; i ++)
 {
  path[i] = -1;
  dist[i] = -1;
 }
 dist[v] = 0;
 LQueue<int> Q;
 Q.QInsert(v);
 while (!Q.IsEmpty())
 {
  Q.QDelete(u);
  p = Head[u].adjacent;
  while(p != NULL)
  {
   k = p->VerAdj;
   if (dist[k] == -1)
   {
    Q.QInsert(k);
    dist[k] = dist[u] + 1;
    path[k] = u;
   }
   p = p->link;
  }   
 }
 for (i = 0; i < n; i ++) cout<<path[i]<<" ";
 for (i = 0; i < n; i ++) cout<<dist[i]<<" ";
 delete []path;
 delete []dist;
}
//在正权图中求指定顶点到其他所有顶点的最短路径
void Graph_List::DShortestPath(const int v)
{
 int i, u, k;
 int max = 10000;
 int ldist;
 Edge *p;
 int n = graphsize;
 int *path = new int[graphsize];
 int *dist = new int[graphsize];
 int *s = new int[n];
 for (i = 0; i < n; i ++)
 {
  path[i] = -1;
  dist[i] = max;
  s[i] = 0;
 }
 dist[v] = 0;
 s[v] = 1;
 p = Head[v].adjacent;
 u = v;
 for (int j = 0; j < n; j ++)
 {
  while(p != NULL)
  {
   k = p->VerAdj;
   if (s[k] != 1 && dist[u] + p->cost < dist[k])
   {
    dist[k] = dist[u] + p->cost;
    path[k] = u;
   }
   p = p->link;
  }
  ldist = max;
  for (i = 0; i < n; i ++)
  {
   if (dist[i] > 0 && dist[i] < ldist && s[i] == 0)
   {
    ldist = dist[i];
    u = i;
   }
  }
  s[u] = 1;
  p = Head[u].adjacent;
 }
 for (i = 0; i < n; i ++) cout<<path[i]<<" ";
 for (i = 0; i < n; i ++) cout<<dist[i]<<" ";
 delete []path;
 delete []dist;
}
//在正权图中求每对顶点间的最短路径
void Graph_List::AllLength()
{
 int n = graphsize;
 int i, j, k;
 int **path = new int *[n];
 int **A = new int *[n];
 for (i = 0; i < n; i ++)
 {
  path[i] = new int[n];
  A[i] = new int[n];
 }
 for (i = 0; i < n; i ++)
 {
  for (j = 0; j < n; j++)
  {
   A[i][j] = GetWeight(i, j);
   if (i != j && A[i][j] < max)
    path[i][j] = i;
   else
    path[i][j] = -1;
  
  }
 }
 for(k = 0; k < n; k ++)
  for(i = 0; i < n; i++)
   if(i != k)
    for(j = 0; j < n; j++)
     if(j != k && j != i && A[i][k] < max && A[i][k] + A[k][j] < A[i][j])
     {
      A[i][j] = A[i][k] + A[k][j];;
      path[i][j] = path[k][j];
     }
 for(i = 0; i < n; i++)
 {
  delete []path[i];
  delete []A[i];
 }
 delete []path;
 delete []A;
}
//构造图的最小支撑树的普里姆算法
void Graph_List::Prim()
{
 int n = graphsize;
 int i ,j;
 int min;
 int v;
 struct LV 
 {
  int Lowcost;
  int Vex;
 } * closedge = new LV[n];
 struct Edge
 {
  int head;
  int tail;
  int cost;
 } *TE = new Edge[n-1];
 for (i = 0; i < n; i ++)
  for(j = 0; j < n; j ++)
   if(GetWeight(i, j) == 0) SetWeight(i, j, max);
 for (i = 0; i < n; i ++)
 {
  closedge[i].Lowcost = GetWeight(0, i);
  closedge[i].Vex = 0;
 }
 closedge[0].Vex = -1;
 int count = 0;
 for (i = 1; i < n; i ++)
 {
  min = max + 1;
  v = 0;
  for (j = 0; j < n; j++)
   if (closedge[j].Vex != -1 && closedge[j].Lowcost < min)
   {
    v = j;
    min = closedge[j].Lowcost;
   }
  if (v != 0)
  {
   TE[count].head = closedge[v].Vex;
   TE[count].tail = v;
   TE[count].cost = closedge[v].Lowcost;
   count ++;
   closedge[v].Lowcost = 0;
   closedge[v].Vex = -1;
   for (j = 0; j < n; j++)
    if (closedge[j].Vex != -1 && GetWeight(v, j) < closedge[j].Lowcost)
    {
     closedge[j].Lowcost = GetWeight(v, j);
     closedge[j].Vex = v;
    } 
  }
 }
 for (i = 0; i < n-1; i++)
  cout<<"("<<TE[i].head<<","<<TE[i].tail<<","<<TE[i].cost<<")"<<endl;
 delete []closedge;
 delete []TE;
}
//构造图的最小支撑树的克鲁斯卡尔算法
void Graph_List::Kruskar()
{
 int *set = new int(graphsize);
 int k = 1, a = 0, b= 0, min = MaxWeight;
 for(int i = 0; i < graphsize; i++)
  set[i] = i;
 while(k < graphsize)
 {
  for (int j = i+1; j < graphsize; ++ j )
  {
   if (GetWeight(i, j) < min)
   { 
    min = GetWeight(i, j);
    a = i;
    b = j;
   }
  }
  min = MaxWeight;
  SetWeight(i, j, MaxWeight);
  if (set[a] != set[b])
  {
   k ++;
   for (i = 0; i < graphsize; i ++)
   {
    if(set[i] == set[b])
     set[i] = set[a];
   }
  }
 }
}
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章