template<class T>
void Graph::UnweightPath(int index) // 求图中某个顶点的无权最短路径
{
if (index >= size)
cout << "Out of range";
int Currdist; // 表示遍历过程中每一次的到index顶点的距离
for (Currdist = 0;Currdist < size;Currdist++) // 每次通过Currdist来指示接下来要处理的顶点及其邻接表
{
for (int i = 0;i < size;i++) // 遍历index顶点状态信息表
{
if (VSet[index].table[i].Known == false && VSet[index].table[i].dist == Currdist) // 如果某个顶点没被经过,且dist为当前距离值
{
VSet[index].table[i].Known = true; // 改变其状态
for (vector >::iterator iter = VSet[i].adj_list.begin();iter != VSet[i].adj_list.end();iter++) // 遍历该顶点的邻接点
{
if (VSet[index].table[iter->value].dist == INF) // 如果邻接点的dist为INF
{
VSet[index].table[iter->value].dist = Currdist + 1; // 更新其dist值
VSet[index].table[iter->value].Path = VSet[i].value;
}
}
}
}
}
}
主要步骤:
template<class T>
void Graph::UnweightPathQ(int index)
{
queue > Q; // 借助队列模板建立一个元素类型为Vertex的队列Q
Vertex W;
Q.push(VSet[index]); // 下标为index的顶点入队列
while (!Q.empty()) // 当队列不为空
{
W = Q.front(); // 取队首元素
Q.pop(); // 出队
VSet[index].table[W.value].Known = true; // 该句可以省略
for (vector >::iterator iter = W.adj_list.begin(); iter != W.adj_list.end();iter++) // 遍历W的邻接表
{
if (VSet[index].table[iter->value].dist == INF) // 如果邻接顶点的dist为无穷大
{
VSet[index].table[iter->value].dist = VSet[index].table[W.value].dist + 1; // 则更新其dist为刚出队顶点的dist值加1
VSet[index].table[iter->value].Path = VSet[W.value].value; // 更新其Path为刚出队顶点(关键字值)
Q.push(VSet[iter->value]); // 邻接点入队列
}
}
}
}
#include
#include
#include
#include
#include
using namespace std;
const int INF = 0x7fffffff; // 表示最大整型数
template<class T> class Vertex; // 提前声明顶点类
template<class T>
class InfoTable { // 创建一个信息表类
public:
bool Known; // 是否被遍历
int dist; // 顶点间的距离
T Path; // 用顶点关键字表示的路径栏
};
template<class T>
class Vertex { // 创建一个顶点类
public:
T value; // 顶点的关键字值
vector > adj_list; // 顶点的邻接表
InfoTable* table; // 最短路径时每个顶点的信息栏
Vertex(T value = 0) :value(value) {}
};
template<class T>
class Graph{ // 创建一个图类
public:
vector > VSet; // 表示顶点的集合
Graph(int sz) :size(sz) {} // 构造函数
Graph(const Graph &G) { size = G.size;VSet = G.VSet; } // 复制构造函数
void UnweightPath(int index); // 无权最短路径
void InitInfoTable(); // 初始化图中顶点的状态信息表
void PrintPath(int index); // 打印某个节点的最短路径
void UnweightPathQ(int index); // 借助队列的指定下标顶点的无权最短路径
private:
int size; // 图中顶点的个数
};
template<class T>
void Graph::InitInfoTable() // 初始化图中每个顶点的状态信息表
{
for (int i = 0;i < size;i++)
{
VSet[i].table = new InfoTable[size]; // 为每个顶点的状态表申请空间
for (int j = 0;j < size;j++)
{
VSet[i].table[j].Known = false; // 每个节点都没被经过
VSet[i].table[j].dist = INF; // 初始时每个顶点距离为无穷,表示不可达
VSet[i].table[j].Path = -1; // 初始Path为-1,方便以后遍历
}
VSet[i].table[i].dist = 0; // 初始时每个顶点距离自身为0
}
}
template<class T>
void Graph::UnweightPath(int index) // 求图中某个顶点的无权最短路径
{
if (index >= size)
cout << "Out of range";
int Currdist; // 表示遍历过程中每一次的到index顶点的距离
for (Currdist = 0;Currdist < size;Currdist++)
{
for (int i = 0;i < size;i++) // 遍历该顶点的状态表
{
if (VSet[index].table[i].Known == false && VSet[index].table[i].dist == Currdist) // 如果某个顶点没被经过,且dist为当前距离值
{
VSet[index].table[i].Known = true; // 改变其状态
for (vector >::iterator iter = VSet[i].adj_list.begin();iter != VSet[i].adj_list.end();iter++) // 遍历该顶点的邻接点
{
if (VSet[index].table[iter->value].dist == INF) // 如果邻接点的dist为INF
{
VSet[index].table[iter->value].dist = Currdist + 1; // 更新其dist值
VSet[index].table[iter->value].Path = VSet[i].value;
}
}
}
}
}
}
template<class T>
void Graph::UnweightPathQ(int index)
{
queue > Q; // 借助队列模板建立一个元素类型为Vertex的队列Q
Vertex W;
Q.push(VSet[index]); // 下标为index的顶点入队列
while (!Q.empty()) // 当队列不为空
{
W = Q.front(); // 取队首元素
Q.pop(); // 出队
VSet[index].table[W.value].Known = true; // 该句可以省略
for (vector >::iterator iter = W.adj_list.begin(); iter != W.adj_list.end();iter++) // 遍历W的邻接表
{
if (VSet[index].table[iter->value].dist == INF) // 如果邻接顶点的dist为无穷大
{
VSet[index].table[iter->value].dist = VSet[index].table[W.value].dist + 1; // 则更新其dist为刚出队顶点的dist值加1
VSet[index].table[iter->value].Path = VSet[W.value].value; // 更新其Path为刚出队顶点(关键字值)
Q.push(VSet[iter->value]); // 邻接点入队列
}
}
}
}
template<class T>
void Graph::PrintPath(int index)
{
cout << "The InfoTable of V" << index << " is:\n";
for (int i = 0;i < size;i++) // 打印下标为index的顶点的状态表
{
cout<<"V"<" "<" " << VSet[index].table[i].dist
<< " "<<"V"<< VSet[index].table[i].Path << endl;
}
cout << "\nShow the unweighted paths form V"<< index << " to other vertices: \n";
stack S; // 借助栈输出从index顶点出发到各个顶点的无权最短路径
for (int i = 0;i < size;i++)
{
int j = i; // 每次取一个顶点作为开始
S.push(VSet[j].value); // 顶点入栈
while (VSet[index].table[j].Path != -1) // 当遍历指定顶点的“Path”形成路径
{
S.push(VSet[index].table[j].Path); // 将路径上的顶点的Path值入栈
j = VSet[index].table[j].Path; // 更新顶点下标
}
while (!S.empty()) // 栈不为空时,打印路径并出栈
{
cout << "->";
cout << "V" << S.top();
S.pop();
}
cout << endl;
}
cout << endl;
}
int main()
{
Graph<int> G(7); // 创建一个图对象G
Vertex<int> V[] = { Vertex<int>(0), Vertex<int>(1), Vertex<int>(2), Vertex<int>(3),
Vertex<int>(4), Vertex<int>(5), Vertex<int>(6) };
V[0].adj_list.push_back(V[1]);
V[0].adj_list.push_back(V[3]); // 顶点0的邻接表
V[1].adj_list.push_back(V[3]);
V[1].adj_list.push_back(V[4]); // 顶点1的邻接表
V[2].adj_list.push_back(V[0]);
V[2].adj_list.push_back(V[5]); // 顶点2的邻接表
V[3].adj_list.push_back(V[2]); // 顶点3的邻接表
V[3].adj_list.push_back(V[4]);
V[3].adj_list.push_back(V[5]);
V[3].adj_list.push_back(V[6]);
V[4].adj_list.push_back(V[6]); // 顶点4的邻接表
V[6].adj_list.push_back(V[5]); // 顶点6的邻接表
for (int i = 0;i < 7;i++)
{
G.VSet.push_back(V[i]);
}
G.InitInfoTable(); // 初始化图中顶点的状态信息表
G.UnweightPath(2); // 改变该顶点的状态信息表
G.PrintPath(2); // 打印从V2到其他顶点路径
Graph<int> G1(G); // 复制构造G1
G1.InitInfoTable(); // 初始化图中顶点的状态信息表
G1.UnweightPathQ(0); // 借助队列的无权最短路径,同样通过改变index顶点的状态信息表实现
G1.PrintPath(0); // 打印从V2到其他顶点路径
system("pause");
return 0;
}
The InfoTable of V2 is:
V0 1 1 V2
V1 1 2 V0
V2 1 0 V-1
V3 1 2 V0
V4 1 3 V1
V5 1 1 V2
V6 1 3 V3
Show the unweighted paths form V2 to other vertices:
->V2->V0
->V2->V0->V1
->V2
->V2->V0->V3
->V2->V0->V1->V4
->V2->V5
->V2->V0->V3->V6
The InfoTable of V0 is:
V0 1 0 V-1
V1 1 1 V0
V2 1 2 V3
V3 1 1 V0
V4 1 2 V1
V5 1 2 V3
V6 1 2 V3
Show the unweighted paths form V0 to other vertices:
->V0
->V0->V1
->V0->V3->V2
->V0->V3
->V0->V1->V4
->V0->V3->V5
->V0->V3->V6
请按任意键继续. . .
Mark Allen Weiss: 数据结构与算法分析