//採用的是鏈式存儲:
//頭文件:
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];
   }
  }
 }
}
 

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