数据结构 第七章 图
四种基本存储结构之邻接矩阵表示法
/*
* 范围:第七章 图
* 日期:2018/4/1
*/
/*
笔记:
enum < 枚举类型名> {< 枚举表>};
enum day {Sun,Mon,Tue,Wed,Thu,Fri,Sat};
day d1,d2,d3;
d1 = Thu; d2 = Sat; d3 = Tue;
定义为枚举类型的变量,只能取枚举表中的值,枚举的本质是整型类型。
*/
#include <iostream>
#define INFINITY INT_MAX
using namespace std;
// 数组表示法/邻接矩阵表示法
const int MAXSIZE = 20;
typedef char vertexType;
typedef int vrType;
typedef char infoType;
typedef enum{DG,DN,UDG,UDN} graphKind;
typedef struct arcCell
{
vrType adj;
infoType *info;
}arcCell,adjMatrix[MAXSIZE][MAXSIZE];
typedef struct
{
vertexType vex[MAXSIZE];
adjMatrix arc;
int vexnum,arcnum;
graphKind kind;
}MGraph;
int locate(MGraph &g,vertexType v)
{
for (int i=0;i<g.vexnum;i++)
{
if( g.vex[i] == v)
return i;
}
return -1;
}
void createUDN(MGraph &g)
{
int hasInfo;
cout << "顶点数、边数、是否有信息"<<endl;
cin >> g.vexnum >>g.arcnum >> hasInfo;
int i,j;
for (i=0;i<g.vexnum;i++)
{
cin >>g.vex[i];
}
for (i=0;i<g.vexnum;i++)
for (j=0;j<g.vexnum;j++)
{
g.arc[i][j].adj = INFINITY;
g.arc[i][j].info = NULL;
}
vertexType v1,v2;
vrType w;
cout << "边:" <<endl;
for (int k=0;k<g.arcnum;k++)
{
cin >>v1 >>v2>>w;
i = locate(g,v1);
j = locate(g,v2);
g.arc[i][j].adj = w;
if (hasInfo)
cin >> g.arc[i][j].info;
g.arc[j][i] = g.arc[i][j];
}
}
void createGraph(MGraph &g)
{
graphKind kind;
cout << "graphkind"<<endl ;
cin >> (int &)kind;
switch(kind)
{
case UDN:createUDN(g);
}
}
void printMatrix(MGraph &g)
{
int i,j;
for (i=0;i< g.vexnum ; i++)
{
for (j = 0 ;j<g.arcnum;j++)
{
if (g.arc[i][j].adj == INFINITY)
cout << '#' << ' ';
else
cout << g.arc[i][j].adj <<' ';
}
cout <<endl;
}
}
// 深度优先搜索
bool visited[MAXSIZE];
int firstAdjVex(MGraph &g,int v)
{
// 邻接矩阵表示法中,点v的第一个邻接点,在矩阵中横着找不为无穷大的点
int j;
for (j = 0; j < g.vexnum ; j++)
{
if (g.arc[v][j].adj!=INFINITY)
return j;
}
return -1;
}
int nextAdjVex(MGraph &g,int v,int w)
{
// v的邻接点中在w之后的第一个邻接点
int j;
for (j = w+1;j<g.vexnum;j++)
{
if (g.arc[v][j].adj!=INFINITY)
return j;
}
return -1;
}
void DFS(MGraph &g,int v)
{
visited[v] = true; // 从V结点开始深度搜索
cout << g.vex[v] << ' ';
for (int w = firstAdjVex(g,v); w >= 0 ;w = nextAdjVex(g,v,w))
{
if (!visited[w])
DFS(g,w);// 对未被访问过的邻接点递归调用DFS
}
}
void DFSTraverse(MGraph &g)
{
int i;
for (i=0;i<g.vexnum;i++)
visited[i] = false; // 初始化visited,均未被访问
for (i=0;i<g.vexnum;i++) // 一次寻找后可能有仍旧未被访问的点
{
if (!visited[i])
DFS(g,i);
}
}
int main()
{
MGraph g;
createGraph(g);
// printMatrix(g);
DFSTraverse(g);
return 0;
}
邻接表表示法
/*
* 范围:第七章 图
* 日期:2018/4/1
*/
/*
笔记:
enum < 枚举类型名> {< 枚举表>};
enum day {Sun,Mon,Tue,Wed,Thu,Fri,Sat};
day d1,d2,d3;
d1 = Thu; d2 = Sat; d3 = Tue;
定义为枚举类型的变量,只能取枚举表中的值,枚举的本质是整型类型。
*/
#include <iostream>
#include <string>
#include <stdlib.h>
#define INFINITY INT_MAX
using namespace std;
// 邻接表
const int MAXSIZE = 20;
typedef char vertexType;
typedef char infoType;
typedef enum{DG,UDG} graphKind;
typedef struct arcNode
{
int adjvex;
infoType *info;
struct arcNode *nextarc;
}arcNode;
typedef struct
{
vertexType data;
struct arcNode *firstarc;
}VNode;
typedef struct
{
VNode adjList[MAXSIZE];
int vexnum,arcnum;
graphKind kind;
}ALGraph;
int locate(ALGraph &g,vertexType v)
{
int i;
for (i = 0;i<g.vexnum;i++)
{
if ( g.adjList[i].data == v )
return i;
}
return -1;
}
void createUDG(ALGraph &g)
{
int hasInfo;
cout << "顶点数、边数、是否有信息"<<endl;
cin >> g.vexnum >> g.arcnum>>hasInfo;
int i,j,k;
cout << "头结点" <<endl;
for (i=0;i<g.vexnum;i++)
{
cin >> g.adjList[i].data ;
g.adjList[i].firstarc = NULL;
}
vertexType v1,v2;
arcNode *p,*q;
cout << "边:" <<endl;
for (k = 0; k < g.arcnum;k++)
{ // 头插法建立链表
cin >> v1 >> v2;
i = locate(g,v1);
j = locate(g,v2);
p = (arcNode*)malloc(sizeof(arcNode));
if (hasInfo)
cin >> p->info;
p->adjvex = j;
p->nextarc = g.adjList[i].firstarc;
g.adjList[i].firstarc = p;
// 无向图一条边建立两个节点
q = (arcNode*)malloc(sizeof(arcNode));
if (hasInfo)
q->info = p->info;
q->adjvex = i;
q->nextarc = g.adjList[j].firstarc;
g.adjList[j].firstarc = q;
}
}
void createDG(ALGraph &g)
{
int hasInfo;
cout << "顶点数、弧数、有无信息"<<endl;
cin >>g.vexnum >>g.arcnum >> hasInfo;
int i,j,k;
cout << "顶点" <<endl;
for (i=0;i<g.vexnum;i++)
{
cin >> g.adjList[i].data;
g.adjList[i].firstarc = NULL;
}
arcNode *p;
vertexType v1,v2;
cout << "弧" <<endl ;
for (k = 0;k<g.arcnum;k++)
{
cin >>v1>>v2;
i = locate(g,v1);
j = locate(g,v2);
p = (arcNode*)malloc(sizeof(arcNode));
p->adjvex = j;
p->nextarc = g.adjList[i].firstarc;
if (hasInfo)
cin >> p->info;
g.adjList[i].firstarc = p;
}
}
void buildNALG(ALGraph &g,ALGraph &ng)
{
ng.vexnum = g.vexnum;
ng.arcnum = g.arcnum;
int i,j;
for (i=0;i<ng.vexnum;i++)
{
ng.adjList[i].data = g.adjList[i].data;
ng.adjList[i].firstarc = NULL;
}
arcNode *p,*q;
for (i = 0;i<g.vexnum;i++)
{
for (j = 0;j<g.vexnum;j++)
{
if (i==j)
continue;
p = g.adjList[j].firstarc;
while (p)
{
if (p->adjvex == i)
{
q = (arcNode *)malloc(sizeof(arcNode));
q->adjvex = j;
q->info = p->info;
q->nextarc = ng.adjList[i].firstarc;
ng.adjList[i].firstarc = q;
}
p = p->nextarc;
}
}
}
}
void createGraph(ALGraph &g)
{
graphKind kind;
cout << "kind:"<<endl;
cin >> (int &)kind;
switch(kind)
{
case UDG:createUDG(g);break;
case DG:createDG(g);
}
}
void printGraph(ALGraph &g)
{
int i;
arcNode *p;
for (i=0;i<g.vexnum;i++)
{
if (!g.adjList[i].firstarc)
cout <<g.adjList[i].data << "->NULL";
else
cout << g.adjList[i].data <<"->";
p = g.adjList[i].firstarc;
while (p)
{
if (!p->nextarc)
cout <<p->adjvex;
else
cout <<p->adjvex << "->";
p = p->nextarc;
}
cout <<endl;
}
}
// 深度优先搜索
bool visited[MAXSIZE];
int firstAdjVex(ALGraph &g,int v)
{
if (g.adjList[v].firstarc)
return g.adjList[v].firstarc->adjvex;
else
return -1;
}
int nextAdjVex(ALGraph &g,int v,int w)
{
arcNode *p;
p = g.adjList[v].firstarc;
for (p ; p ; p = p ->nextarc)
{
if (p->adjvex == w)
{
if (p->nextarc)
{
return p->nextarc->adjvex;
}
else
return -1;
}
}
}
void DFS(ALGraph &g,int v)
{
visited[v] = true;
cout << g.adjList[v].data<<' ';
for (int w = firstAdjVex(g,v) ; w>=0 ; w = nextAdjVex(g,v,w)) // 注意这里不能写w,因为我的return值是-1!所以条件亦成立
{
if (!visited[w])
DFS(g,w);
}
}
void DFSTraverse(ALGraph &g)
{
int i;
for (i=0;i<g.vexnum;i++)
{
visited[i] = false;
}
for (i = 0;i<g.vexnum;i++)
{
if (!visited[i])
DFS(g,i);
}
}
// 广度优先搜索
void BFSTraverse(ALGraph &g)
{
for (int i = 0;i<g.vexnum;i++)
visited[i] = false;
queue<int> que;
for (int i = 0;i<g.vexnum;i++)
{
if (!visited[i])
{
visited[i] = true;
cout << g.adjList[i].data<<' ';
que.push(i);
while (!que.empty())
{
int u = que.front();
que.pop();
for (int w = firstAdjVex(g,u) ; w >=0 ;w= nextAdjVex(g,u,w))
{
if (!visited[w])
{
visited[w] = true;
cout << g.adjList[w].data <<' ';
que.push(w);
}
}
}
}
}
}
int main()
{
ALGraph g,ng;
createGraph(g);
//buildNALG(g,ng);
printGraph(g);
DFSTraverse(g);
return 0;
}
####十字链表表示法
/*
* 范围:第七章 图
* 日期:2018/4/1
*/
/*
笔记:
enum < 枚举类型名> {< 枚举表>};
enum day {Sun,Mon,Tue,Wed,Thu,Fri,Sat};
day d1,d2,d3;
d1 = Thu; d2 = Sat; d3 = Tue;
定义为枚举类型的变量,只能取枚举表中的值,枚举的本质是整型类型。
*/
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
// 十字链表
const int MAXSIZE = 20;
typedef char vertexType;
typedef char infoType;
typedef struct arcNode
{
int tailvex,headvex;//尾部邻接点和头部邻接点
struct arcNode *hlink,*tlink;//hlink指向弧头相同的下一条弧
infoType *info;
}arcNode;
typedef struct
{
vertexType data;
struct arcNode *firstin,*firstout;
}VNode;
typedef struct
{
int vexnum,arcnum;
VNode olist[MAXSIZE];
}OLGraph;
int locate(OLGraph &g,vertexType v)
{
int i;
for (i=0;i<g.vexnum;i++)
{
if ( g.olist[i].data == v )
return i;
}return -1;
}
void createDG(OLGraph &g)
{
cout << "顶点数、弧数、有无信息" << endl;
int hasInfo;
cin >> g.vexnum >>g.arcnum >> hasInfo;
int i,j,k;
cout << "顶点:" << endl;
for (i=0;i<g.vexnum;i++)
{
cin >> g.olist[i].data;
g.olist[i].firstin = NULL;
g.olist[i].firstout = NULL;
}
cout << "弧:"<<endl;
vertexType v1,v2;
arcNode *p;
for (k = 0;k<g.arcnum;k++)
{
cin >> v1 >> v2;a
i = locate(g,v1);
j = locate(g,v2);
p->tailvex = i;
p->headvex = j;
if (hasInfo)
cin >> p->info;
p->tlink = g.olist[i].firstout;
g.olist[i].firstout = p;
// 至此完成邻接表的工作,十字链表即为邻接表+逆邻接表的结合体
p->hlink = g.olist[j].firstin;
g.olist[j].firstin = p;
}
}
int main()
{
return 0;
}
####邻接多重表表示法
/*
* 范围:第七章 图
* 日期:2018/4/1
*/
/*
笔记:
enum < 枚举类型名> {< 枚举表>};
enum day {Sun,Mon,Tue,Wed,Thu,Fri,Sat};
day d1,d2,d3;
d1 = Thu; d2 = Sat; d3 = Tue;
定义为枚举类型的变量,只能取枚举表中的值,枚举的本质是整型类型。
*/
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
// 邻接多重表 无向图的存储形式
const int MAXSIZE = 20;
typedef char vertexType;
typedef struct eNode
{
bool mark;
int ivex,jvex;
struct eNode *ilink,*jlink; // ilink 指向依附于ivex的边
}eNode;
typedef struct VNode
{
vertexType data;
struct eNode *firstedge;
}VNode;
typedef struct
{
VNode adjmulist[MAXSIZE];
int vexnum,edgenum;
}AMLGraph;
void createAMLGraph(AMLGraph &g)
{
cout << "顶点数、边数、有无信息"<<endl;
int hasInfo;
cin >> g.vexnum >> g.edgenum >> hasInfo;
int i,j,k;
for (i=0;i<g.vexnum;i++)
{
cin >> g.adjmulist[i].data;
g.adjmulist[i].firstedge = NULL;
}
eNode *p;
vertexType v1,v2;
for (k=0;k<g.edgenum;k++)
{
cin >> v1 >> v2;
i = locate(g,v1);
j = locate(g,v2);
p = (eNode *)malloc(sizeof(eNode));
p->ivex = i;
p->jvex = j;
p->ilink = g.adjmulist[i].firstedge;
p->jlink = g.adjmulist[j].firstedge;
g.adjmulist[i].firstedge = p;
g.adjmulist[j].firstedge = p;
}
}
int main()
{
return 0;
}
无向图的连通分量和生成树
/*
* 7.4 知识点
* 1. 遍历无向图时,对于连通图,从任一顶点出发进行深度或广度优先搜索即可;对于非联通图则需要从
* 多个顶点出发进行搜索,每次获得的顶点序列则为各个连通分量的顶点集。
* 2. 连通图有深度优先生成树和广度优先生成树,即搜索的路径形成的树。
* 3. 非连通图每个连通分量均可形成一个生成树,即一个生成森林。
* 4. 除了二叉树外的没有叉数限制的树一般用孩子-兄弟表示法表示成方便遍历的二叉树形式。
* 5. 森林的树的根节点其实亦为兄弟,也可以用孩子-兄弟表示法来表示。
*/
// 无向图的深度优先生成森林(非连通图)
typedef char Elemtype;
typedef struct CSNode
{
Elemtype data;
struct CSNode *child,*sibling;
}CSNode,*CSTree;
void DFSTree(ALGraph &g,CSTree &t,int v)
{
// 从v顶点开始深度搜索生成树
visited[v] = true;
cout <<g.adjList[v].data << ' ';
CSTree p,q;
bool isfirst = true;
for (int w = firstAdjVex(g,v) ; w>=0 ; w = nextAdjVex(g,v,w))
{
if (!visited[w])
{
p = (CSTree)malloc(sizeof(CSNode));
p->data = g.adjList[w].data;
p->child = NULL;
p->sibling = NULL;
// 创建新节点P作为根节点T的邻接点,但必须确定是第一个邻接点还是其他
if (isfirst)
{
t->child = p;
isfirst = false;
}else
{
q->sibling = p;
}
q = p;
DFSTree(g,p,w); // 递归寻找p的邻接点们!
}
}
}
void DFSForest(ALGraph &g,CSTree &t)
{
for (int i=0;i<g.vexnum;i++)
visited[i] = false;
CSTree p,q;
for (int i=0;i<g.vexnum;i++)
{
if (!visited[i])
{
p = (CSTree)malloc(sizeof(CSNode));
p->data = g.adjList[i].data;
p->child = NULL;
p->sibling = NULL;
if (!t)
{
t = p; // 第一棵生成树
}else
{
q->sibling = p; // 非第一棵生成树,则为上一棵生成树根节点的兄弟
}
q = p;
DFSTree(g,p,i);// 从i顶点出发建立以p为根节点的生成子树
}
}
}
void level(CSTree &t)
{
queue<CSTree> q;
CSTree p;
if (t) // 空树没有必要遍历了
{
q.push(t); // 根节点入队
while (!q.empty())
{
p = q.front(); // 弹栈一个元素
q.pop();
cout << p->data << ' ';
if (p->child)
{
q.push(p->child);
}
if (p->sibling)
{
q.push(p->sibling);
}
}
}
}
测试数据
3
13 13 0
ABCDEFGHIJKLM
A C
A F
A L
A B
B M
D E
G H
G K
G I
H K
J L
J M
M L
最小生成树 之 普利姆算法
struct
{
vertexType adjvex;
vrType lowcost;
}closedge[MAXSIZE];
// 辅助数组的意义:记录从U到V-U中具有最小代价的边
int locateVex(MGraph &g,vertexType v)
{
int k = -1;
for (int i = 0 ;i<g.vexnum;i++)
{
if (g.vex[i] == v)
k = i;
return k;
}
return k;
}
int minimum(MGraph &g)
{
int min1 = INFINITY;
int k = -1;
for (int i = 0;i<g.vexnum;i++)
{
if ( closedge[i].lowcost != 0 )
{
if ( closedge[i].lowcost < min1 )
{
min1 = closedge[i].lowcost;
k = i;
}
}
}
return k;
}
void miniSpanTree_prim(MGraph &g,vertexType u)
{
int k = locate(g,u);
for (int i=0;i<g.vexnum;i++)
{ // closedge 一开始并不包含K
if (i != k )
{
closedge[i].adjvex = u;
closedge[i].lowcost = g.arc[k][i].adj; //不与u邻接的点的lowcost是INFINITY
}
}
closedge[k].lowcost = 0; // 被选入U的顶点的权值均为0
for (int i = 1;i<g.vexnum ;i++) // 选择g.vexnum -1此V-U中的顶点,直到U = V为止
{
// 选择最小的权值,把顶点加入到U中
k = minimum(g); // 求出下一个结点K
cout <<"( " <<closedge[k].adjvex<<" , "<<g.vex[k]<<" )" << endl; // 打印找到的边
closedge[k].lowcost = 0; // 把K划入U集合中
// 更新closedge
for (int j = 0;j<g.vexnum;j++)
{
if (g.arc[k][j].adj < closedge[j].lowcost)
{
closedge[j].adjvex = g.vex[k];
closedge[j].lowcost = g.arc[k][j].adj;
}
}
}
}
测试数据:
3
6 10 0
ABCDEF
A B 6
A D 5
A C 1
B C 5
B E 3
C D 5
C E 6
C F 4
D F 2
E F 6
拓扑排序
/*
有向无环图的介绍:
1. 有向无环图:描述含有公共子式的工具,实现对相同子式地共享,从而节省存储空间
2. 检查一个有向图是否存在环比无向图复杂。无向图:深度优先遍历过程中遇到已访问过的顶点的边则必定存在环;
有向图:这条回边有可能是指向深度优先生成森林中另一棵生成树顶点的弧。
解决:从某个顶点V出发的遍历,在DFS(V)结束之前出现一条从顶点U到顶点V的回边,有向图上必定存在环。
3. 有向无环图是描述一项工程或系统的进行过程的有效工具。工程可分为若干个活动,活动之间存在条件的约束。
人们关心:1)工程能否顺利完成 2)工程完成所必须的最短时间
拓扑排序:
1. 由某个集合上的一个偏序得到该集合的一个全序的过程
2. 解释:偏序是指集合中仅有部分成员之间可比较,而全序为集合中全体成员之间均可比较,全序即为拓扑有序
3. 由偏序定义得到拓扑有序的操作便是拓扑排序
4. 顶点表示活动,弧表示活动之间优先关系的有向图称为顶点表示活动的网AOV网,直接前驱和直接后继
5. 在AOV网中不应该出现有向环,因此检测有向网中是否存在环的方法是:构造顶点的拓扑排序序列,若网中的所有顶点都在拓扑有序序列中则必定不存在环。
6. 如何进行拓扑排序?在有向图中选择一个没有前驱的顶点且输出,删除该顶点和所有以它为尾的弧
*/
int indegree[MAXSIZE];
void findInDegree(ALGraph &g)
{
ALGraph ng;
buildNALG(g,ng);
arcNode *p;
int d = 0;
for (int i=0;i<ng.vexnum;i++)
{
d = 0;
p = ng.adjList[i].firstarc;
while (p)
{
d ++ ;
p = p->nextarc;
}
indegree[i] = d;
}
// for (int i=0;i<g.vexnum;i++)
// cout <<indegree[i] << ' ';
}
int topoLogicalSort(ALGraph &g)
{
findInDegree(g); // 找到各定点的入度
stack<int> st;
// 把所有入度为0的顶点入栈
for (int i =0;i<g.vexnum;i++)
{
if (!indegree[i])
st.push(i);
}
int i;
arcNode *p;
int count = 0 ; // 对输出顶点计数
while (!st.empty())
{
i = st.top();
st.pop();
cout << g.adjList[i].data << ' ';
count ++;
for (p = g.adjList[i].firstarc ; p ; p=p->nextarc)
{
// 对I号顶点的每个邻接点的入度都减1
int k = p->adjvex;
if (!(--indegree[k]))
st.push(k); // 若减1后变为入度为0,入栈
}
}
if (count < g.vexnum)
return -1;
else
return 1;
}
关键路径
int ve[MAXSIZE]; // 各顶点的最早开始时间
int vl[MAXSIZE]; // 各顶点的最迟开始时间
/*
1. 计算各顶点的最早开始时间ve
2. T为拓扑序列顶点栈
3. S为零入度顶点栈
4. 若G无回路,则用栈T返回G的一个拓扑序列
*/
int topoLogicalOrder(ALGraph &g,stack<int> &t)
{
findInDegree(g,indegree);
stack<int> s;
for (int i = 0;i<g.vexnum;i++)
{
if (!indegree[i])
s.push(i);
}
int count = 0;
for (int i=0;i<g.vexnum;i++)
ve[i] = 0;
while (!s.empty())
{
int j = s.top();
s.pop();
t.push(j);
count ++ ;
for (arcNode *p = g->adjList[j].firstarc ; p ; p = p->nextarc)
{
int k = p->adjvex;
if (!(--indegree[k]))
s.push(k);
if (ve[j]+*(p->info) > ve[k])
ve[k] = ve[j] + *(p->info);
}
}
if (count <g.vexnum)
return -1;
else return 1;
}
// 关键路径
int criticalPath(ALGraph &g)
{
// 目的:输出G的各项关键活动
stack<int> t;
arcNode *p;
if (!topoLogicalOrder(g,t))
return -1;
for (int i=0;i<g.vexnum;i++)
vl[i] = ve[g.vexnum-1] ; // 初始化均为最大值
while (!t.empty())
{
int j = t.top();
t.pop();
for (p = g.adjList[j].firstarc ; p ; p= p->nextarc)
{
int k = p->adjvex;
dut = *(p->info);
if (vl[k]-dut < vl[j])
vl[j] = vl[k] - dut;
}
}
for (j = 0;j<g.vexnum;j++)
{
for (p = g.adjList[i].firstarc ; p;p=p->nextarc)
{
int k = p->adjvex;
dut = *(p->info);
int ee = ve[j];
el = vl[k] - dut;
tag = (ee == el) >
}
}
}
最短路径-迪杰斯特拉
/* 最短路径
1. 交通路网上从原点A到达目的地B的所含边的数目最少的路径,只需要广度优先搜索,遇到B点时停止
2. 源点到其余各个顶点的最短路径--迪杰斯特拉算法--按照路径长度递增的次序产生最短路径的算法
3. 求从源点v0到其余各点v的最短路径P[v]和带权长度d[v]
4. p[v][w] == true, 则w是v0 - v 上最短路径的一个顶点,该路径显然经过v0 和 v\
5. final[v]为已经归入点集合的点
*/
bool p[MAXSIZE][MAXSIZE];
int d[MAXSIZE];
bool final[MAXSIZE];
void shortestPath(MGraph &g,int v0)
{
for (int i=0;i<g.vexnum;i++)
{
final[i] = false;
d[i] = g.arc[v0][i].adj;
for (int j = 0;j<g.vexnum;j++)
p[i][j] = false;
if (d[i]!=INFINITY)
{
p[i][i] = true;
p[i][v0] = true;
}
}
final[v0] = true;
d[v0] = 0;
int v;
int min = INFINITY;
for (int i=1;i < g.vexnum;i++)
{ // 对其余的g.vexnum - 1个顶点,每次选择最短的一条路径的顶点加入final集合
min = INFINITY;
for (int j=0;j<g.vexnum;j++)
if (!final[j])
if (d[j] < min)
{
min = d[j];
v = j; // v是此次选出的顶点
}
final[v] = true;
// 更新最短路径及距离
for (int j = 0;j<g.vexnum;j++)
{
if (!final[j] && d[j] > (g.arc[v][j].adj + min)) //此处注意INFINIT + INT 不会小于 INFINIT,因为已经到了能存储的最大数
{
d[j] = min + g.arc[v][j].adj;
for (int k = 0;k<g.vexnum;k++)
p[j][k] = p[v][k];
p[j][j] = true;
}
}
}
}
void printShortestPath(MGraph &g)
{
int i;
for (i = 1;i<g.vexnum;i++)
{
cout << g.vex[i] << "\t"<<'(';
for (int j = 0;j<g.vexnum;j++)
if (p[i][j])
cout << g.vex[j] <<' ' ;
cout << ')'<<"\t" ;
cout << d[i] <<endl;
}
}
测试数据
// 迪杰特斯拉
1
6 8 0
ABCDEF
A C 10
A E 30
A F 100
B C 5
C D 50
E D 20
E F 60
D F 10