数据结构考研 - 图的知识点与思维导图 幕布链接
1. 存储结构
1.1 邻接矩阵(顺序表)
1.1.1 结构型定义
typedef struct
{
int no;
char info;
} VertexType
typedef struct
{
int edges[maxSize][maxSize];
int n, e;
VertexType vex[maxSize];
} MGraph;
1.2 邻接表(链表)(很少考代码)
1.3 邻接多重表(很少考代码)
类似于十字链表
2. 遍历
2.1 深度优先遍历 DFS
void DFS(AGraph *G, int v)
{
ArcNode *p;
visit[v]=1;
Visit(v);
p=G->adjlist[v].firstarc; //p指向顶点v的第一条边
while(p!=NULL)
{
if(visit[p->adjvex]==0)
DFS(G, p->adjvex);
p=p->nextarc; // p指向顶点v的下一条边
}
}
2.2 广度优先遍历 BFS
void BFS(AGraph *G, int v, int visit[maxSize])
//注意这里的visit数组作为参数传入,与DFS不一样
// visit[] 数组初始化为0
{
ArcNode *;
int que[maxSize], front = 0, rear = 0;
int j;
Visit(v);
visit[v]=1;
rear=(rear+1)%maxSize;
que[rear]=v;
while(front!=rear) //队空时表示遍历完成
{
front=(front+1)%maxSize;
j=que[front];
p=G->adjlist[j].firstarc;
while(p!=NULL) // 将p的所有邻接点钟未被访问的入队
{
if (visit[p->adjvex]==0)
{
Visit(p->adjvex);
visit[p->adjvex]=1;
rear=(rear+1)%maxSize;
que[rear]=p->adjvex;
}
p = p->nextarcc;
}
}
}
3. 最小生成树
3.1 克鲁斯卡尔算法 Kruskal
适用于 无向图 稀疏图
//此为求的最小代价的函数,因为求生成树考的极少
typedef struct
{
int a,b;
int w;
}Road;
Road road[maxSize];
int v[maxSize]; //定义查找集数组
int getRoot(int a) //定义查找集中找根结点的函数
{
while(a!=v[a]) a=v[a];
return a;
}
void Kruskal(MGraph g; int &sum, Road road[])
{
int i;
int N, E, a, b;
N=g.n;
E=g.e;
sum=0;
for(i=0;i<N;++i) v[i]=i;
sort(road, E); //对road数组中的E条边按其权值从大到小排序
for(i=0;i<E;++i)
{
a=getRoot(road[i].a)
b=getRoot(road[i].b)
if(a!=b)
{
v[a]=b;
sum+=road[i].w;
}
}
}
3.2 普里姆算法 PRIM
适用于 稠密图
//此为求的最小代价的函数,因为求生成树考的极少
void Prim(MGraph g, int v0, int &sum)
{
int lowcost[maxSize], vset[maxSize], v;
int i,j,k,min;
v=v0;
for(i=0;i<g.n;++i)
{
lowcost[i]=g.edges[v0][i];
vest[i]=0;
}
vset[v0]=1;
sum=0;
for(i=0;i<g.n-1;++i)
{
min = INF;
// 下面这个循环用于选出候选边中的最小者
for(j=0;j<g.n;++j)
{
if(vset[j]==0&&lowcost[j]<min)
{
min=lowcost[j];
k=j;
}
vset[k]=1;
v=k;
sum+=sum;
// 下面这个循环以刚并入的顶点v为媒介更新候选边
for(j=0;j<g.n;++j)
if(vset[j]==0&&g.edges[v][j]<lowcost[j])
lowcost[j]=g.edges[v][j];
}
}
4. 最短路径
4.1 迪杰斯特拉算法 Dijkstra
4.2 佛罗伊德算法 Floyd
void Floyd(MGraph g, int Path[][maxSize])
{
int i,j,k;
int A[maxSize][maxSize];
/* 这个双循环对数组A[][]和Path[][]进行了初始化*/
for(i=0;i<g.n;++i)
for (j=0;j<g.n;++j)
{
A[i][j]=g.edges[i][j];
Path[i][j]=-1;
}
/* 下面的三层循环是主要操作,完成了以k为中间点对所有的顶点对{i,j}进行检测和修改*/
for(k=0;k<g.n;++k)
for(i=0;i<g.n;++i)
for(j=0;j<j.n;++j)
if(A[i][j]>A[i][k]+A[k][i])
{
A[i][j]=A[i][k]+A[k][i];
Path[i][j]=k;
}
}
5. 拓扑结构
// 以邻接表为存储结构
typedef struct
{
char data;
int count;
ArcNode *firstarc; // 统计顶点当前的入度
} VNode;
int TopSort(AGraph *G) //注意这里传入的是图的地址指针
{
int i,j,n=0;
int stack[maxSize], top=-1; //用于记录当前图中入度为0的顶点
ArcNode *p;
/* 将图中入度为0的顶点入栈 */
for(i=0;i<G->n;++j) //图中顶点从0开始编号
if(G->adjlist[i].count==0) //假设count已经存储了所有入度为0的顶点
stack[++top]=i;
/* 关键操作 */
while(top!=-1)
{
i=stack[top--];
++n;
count<<i<<" ";
p=G->adjlist[i].firstarc;
/* 此循环实现了将所有由此顶点引出的边所指向的顶点的入度都减少1 */
/* 并将这个过程中入度为0的顶点入栈 */
while(p!=NULL)
{
j=p->adjvex;
--(G->adjlist[j].count);
if(G->adjlist[j].count==0)
stack[++top]=j;
p=p->nextarc;
}
}
/* 关键操作结束 */
if(n==G->n)
return 1;
else
return 0;
}
6. 关键路径
一般不考代码实现