//採用的是鏈式存儲:
//頭文件:
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];
}
}
}
}
圖
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.