Graph.h
#pragma once
#include<iostream>
#include<string>
#include<queue>
#include<stack>
using namespace std;
#define MAXN 100 //最大顶点数
#define PERRROR perror("Allocate dynamic memory");
typedef struct Edge //边
{
int adjvexID; //邻接点id
int weight;
Edge* next;
}*EdgePtr;
typedef struct Node //顶点
{
string name; //顶点名称
int id;
EdgePtr firstedg; //边表头指针
}*NodePtr;
struct UnWeightedTable //路径
{
bool Known;
int dist;
int path;
};
class Graph
{
private:
Node Vertex[MAXN]; //顶点集合
bool visited[MAXN]; //遍历用
int Indegree[MAXN]; //记录每个顶点的入度
int NameToID(string str);
void InitIndegree();
void DFS(int i);
void PrintPath(int vertex, UnWeightedTable* table);
public:
int numVertexs; //点数
int numEdges; //边数
void DFSTraverse(); //DFS遍历
void BFSTraverse(); //BFS遍历
void TopSort(); //拓扑排序
void UnWeightedPath(string source, string dest);//无权最短路径
void WeightedPath(string source, string dest); //带权最短路径
Graph();
~Graph();
void MakeGraph();
void PrintGraph();
};
Graph::Graph()
{
numVertexs = numEdges = 0;
}
Graph::~Graph()
{
EdgePtr temp;
for (int i = 0; i < numVertexs; i++)
{
while (Vertex[i].firstedg)
{
temp = Vertex[i].firstedg;
Vertex[i].firstedg = Vertex[i].firstedg->next;
free(temp);
}
}
}
int Graph::NameToID(string str)
{
int i = 0;
for (i = 0; i < numVertexs; i++)
{
if (!Vertex[i].name.compare(str))
break;
}
if (i < numVertexs)
return i;
else
cout << "Wrong Vertex name: " << str << endl;
return -1;
}
//构建图
void Graph::MakeGraph()
{
int v, e, w;
string s, t;
cout << "输入顶点数和边数:\n";
cin >> v >> e;
numVertexs = v;
numEdges = e;
cout << "输入顶点名称:\n";
for (int i = 0; i < v; i++)
{
cin >> Vertex[i].name;
Vertex[i].id = i;
Vertex[i].firstedg = NULL;
}
cout << "输入边的信息:\n";
for (int i = 0; i < e; i++)
{
cin >> s >> t >> w;
//申请一个新的边
EdgePtr edge = (EdgePtr)malloc(sizeof(Edge));
if (edge == NULL)
PERRROR;
edge->adjvexID = NameToID(t);
edge->weight = w;
edge->next = Vertex[NameToID(s)].firstedg;
Vertex[NameToID(s)].firstedg = edge;
无向图同时添加2条边
申请一个新的边
//EdgePtr edge1 = (EdgePtr)malloc(sizeof(Edge));
//if (edge1 == NULL)
// PERRROR;
//edge1->adjvexID = NameToID(s);
//edge1->weight = w;
//edge1->next = Vertex[NameToID(t)].firstedg;
//Vertex[NameToID(s)].firstedg = edge1;
}
}
//输出图
void Graph::PrintGraph()
{
EdgePtr p;
cout << "顶点数: " << numVertexs << " 边数: " << numEdges << endl;
for (int i = 0; i < numVertexs; i++)
{
cout << Vertex[i].name << ": ";
p = Vertex[i].firstedg;
while (p)
{
cout << Vertex[p->adjvexID].name << "(" << p->weight << ") ";
p = p->next;
}
cout << endl;
}
}
//深度优先遍历
void Graph::DFS(int i)
{
visited[i] = true;
cout << Vertex[i].name << " ";
EdgePtr p = Vertex[i].firstedg;
while (p)
{
if (!visited[p->adjvexID])
DFS(p->adjvexID);
p = p->next;
}
}
void Graph::DFSTraverse()
{
cout << "DFS: ";
memset(visited, false, numVertexs*sizeof(bool));
for (int i = 0; i < numVertexs; i++)
{
if (!visited[i])
DFS(i);
}
cout << endl;
}
//广度优先遍历
void Graph::BFSTraverse()
{
cout << "BFS: ";
EdgePtr p;
queue<Node> q;
memset(visited, false, numVertexs*sizeof(bool));
for (int i = 0; i < numVertexs; i++)
{
if (!visited[i])
{
visited[i] = true;
cout << Vertex[i].name << " ";
q.push(Vertex[i]);
while (!q.empty())
{
p = q.front().firstedg;
q.pop();
while (p)
{
if (!visited[p->adjvexID])
{
visited[p->adjvexID] = true;
cout << Vertex[p->adjvexID].name << " ";
q.push(Vertex[p->adjvexID]);
}
p = p->next;
}
}
}
}
cout << endl;
}
void Graph::InitIndegree()
{
EdgePtr p;
memset(Indegree, 0, numVertexs*sizeof(int)); //暂且用来寻找那些入度为0的顶点
for (int i = 0; i < numVertexs; i++)
{
p = Vertex[i].firstedg;
while (p)
{
Indegree[p->adjvexID]++;
p = p->next;
}
}
}
//拓扑排序
void Graph::TopSort()
{
cout << "TopSort: ";
int count = 0;
EdgePtr p;
queue<int> q;
int temp;
InitIndegree();
//初始化入度为0的入队
for (int i = 0; i < numVertexs; i++)
{
if (!Indegree[i])
{
q.push(i);
}
}
while (!q.empty())
{
temp = q.front();
q.pop();
cout << Vertex[temp].name << " ";
count++;
p = Vertex[temp].firstedg;
while (p)
{
Indegree[p->adjvexID]--;
if (!Indegree[p->adjvexID])
q.push(p->adjvexID);
p = p->next;
}
}
if (!count == numVertexs)
cout << "Graph has a cycle";
cout << endl;
}
//无权图求最短路径
void Graph::UnWeightedPath(string source, string dest)
{
UnWeightedTable* table = (UnWeightedTable*)malloc(numVertexs*sizeof(UnWeightedTable));;
for (int i = 0; i < numVertexs; i++)
{
table[i].dist = INT16_MAX;
table[i].path = i;
}
queue<int> q;
q.push(NameToID(source));
table[NameToID(source)].dist = 0;
int temp;
EdgePtr p;
while (!q.empty())
{
temp = q.front();
q.pop();
p = Vertex[temp].firstedg;
while (p)
{
if (table[p->adjvexID].dist == INT16_MAX)
{
table[p->adjvexID].dist = table[temp].dist + 1;
table[p->adjvexID].path = temp;
q.push(p->adjvexID);
}
p = p->next;
}
}
stack<string> paths;
temp = NameToID(dest);
while (temp != NameToID(source))
{
paths.push(Vertex[temp].name);
temp = table[temp].path;
}
paths.push(Vertex[temp].name);
cout << "Paths: ";
while (!paths.empty())
{
cout << paths.top() << " ";
paths.pop();
}
cout<<"Length: " <<table[NameToID(dest)].dist<< endl;
free(table);
}
void Graph::PrintPath(int vertex, UnWeightedTable* table)
{
if (table[vertex].path != -1)
{
PrintPath(table[vertex].path, table);
}
cout << Vertex[vertex].name << " ";
}
//有权图求最短路径
void Graph::WeightedPath(string source, string dest)
{
UnWeightedTable* table = (UnWeightedTable*)malloc(numVertexs*sizeof(UnWeightedTable));;
for (int i = 0; i < numVertexs; i++)
{
table[i].Known = false;
table[i].dist = INT32_MAX;
table[i].path = i;
}
table[NameToID(source)].dist = 0;
table[NameToID(source)].path = -1;
int i,smallest = INT32_MAX;
int smallID = -1;
EdgePtr p;
for (;;)
{
smallest = INT32_MAX;
smallID = -1;
for (i = 0; i < numVertexs; i++)
{
if (!table[i].Known && table[i].dist < smallest)
{
smallest = table[i].dist;
smallID = i;
}
}
if (smallID == -1)
break;
table[smallID].Known = true;
p = Vertex[smallID].firstedg;
while (p)
{
if( ! table[p->adjvexID].Known )
if (table[smallID].dist + p->weight < table[p->adjvexID].dist)
{
table[p->adjvexID].dist = table[smallID].dist + p->weight;
table[p->adjvexID].path = smallID;
}
p = p->next;
}
}
PrintPath(NameToID(dest), table);
cout <<"Length: "<<table[NameToID(dest)].dist<< endl;
free(table);
}
Graph.cpp
#include"Graph.h"
#include<iostream>
using namespace std;
/*
输入:
7 12
v1 v2 v3 v4 v5 v6 v7
v1 v2 2
v1 v3 4
v1 v4 1
v2 v4 3
v2 v5 10
v3 v6 5
v4 v3 2
v4 v5 2
v4 v6 8
v4 v7 4
v5 v7 6
v7 v6 1
*/
int main()
{
Graph G;
G.MakeGraph();
G.DFSTraverse();
G.BFSTraverse();
G.TopSort();
G.UnWeightedPath("v1", "v6");
G.WeightedPath("v1", "v5");
return 0;
}