**图**
新的一周,最近感觉时间过得好快啊!!!
争取在开学前整理完!!!开学后二刷王道!!!
(加油!!!!!)
直接上图吧!
开始正题!!
1.图的存储
//图的邻接矩阵
#define MaxVertexNum 100 //顶点数目的最大值
typedef char VertexType;//顶点的数据类型
typedef int EdgeType;//带权图中边上权值的数据类型
typedef struct{
VertexType Vex[MaxVertexNum];//顶点表
EdgeType Edge[MaxVerteNum][MaxVerteNum];//邻接矩阵,边表
int vexnum,arcnum;//图的当前顶点数和边数
}MGraph;
//图的邻接表存储
#define MaxVertexNum 100 //图中顶点数目的最大值
typedef struct ArcNode{ //边表结点
int adjvex;//该边所指向的顶点的位置
struct ArcNode *next; //指向下一条边的指针
}ArcNode;
typedef struct VNode{ //顶点表结点
VertexType data;//顶点信息
ArcNode *first;//指向第一依附该顶点的边的指针
}VNode,AdjList[MaxVertexNum];
typedef struct{
AdjList vertices;//邻接表
int vexnum,arcnum;//图的顶点数和边数
}ALGraph; //ALGraph是以邻接表存储的图类型
2.十字链表的结构定义
//图的十字链表结构定义
#define MaxVertexNum 100
typedef struct ArcNode{ //边表结点
int tailvex,headvex;//该边的头尾结点
struct ArcNode *hlink,*tlink;//分别指向边头相同和边尾相同的结点
}ArcNode;
typedef struct VNode{//顶点表结点
VertexType data;//顶点信息
ArcNode *firstin,*firstout;//珍惜第一条入边和出边
}VNode;
typedef struct{
VNode xlist[MaxVertexNum];//邻接表
int vexnum,arcnum;//图的顶点数和边数
}GLGraph;//GLGraph是以十字邻接存储的图类型
3.图的邻接多重表存储结构定义
//图的邻接多重表存储结构定义
#define MaxVertexNum 100
typedef struct ArcNode{//边表结点
bool mark;//访问标记
int ivex,jvex;//分别指向该边的两个结点
struct ArcNode *ilink,*jlink;//分别指向两个顶点的下一条边
}ArcNode;
typedef struct VNode{ //顶点表结点
VertexType data;//顶点信息
ArcNode *firstedge;//指向第一条依附该顶点的边
}VNode;
typedef struct{
VNode adjmulist[MaxVertexNum];//邻接表
int vexnum,arcnum;//图的顶点数和边数
}AMLGraph;//AMLGraph是以邻接多重表存储的图类型
4.广度优先算法的伪代码
//广度优先搜索算法的伪代码
bool visited[MAX_VERTEX_NUM];//访问标记数组
void BFSTraverse(Graph G){
//对图G进行广度优先遍历,设访问函数为visit()
for(int i=0;i<G.vexnum;i++)
visited[i]=FALSE;//访问标记数组初始化
InitQueue(Q);//初始化辅助队列Q
for(i=0;i<G.vexnum;i++) //从0号顶点开始遍历
if(!visited[i])//对每个连通分量调用一次BFS
BFS(G,i);//vi未被访问过,从vi开始BFS
}
void BFS(Graph G,int v){
//从顶点v出发,广度优先遍历图G,算法借助一个辅助队列Q
visit(v);//访问初始顶点v
visited[v]=TRUE;//对v做已访问标记
Enqueue(Q,v);//顶点v入队列
while(!isEmpty(Q)) {
Dequeue(Q,v);//顶点v出队列
for(w=FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w)) //检测v所有邻接点
//FirstNeighbor(G,v)求图G中顶点v的第一个邻接点,若有则返回顶点号。若u没有邻接点或图中不存在v,则返回-1
if(!visited[w]) {
//w为v的尚未访问的邻接顶点
visited[w]=TRUE;//对w做已访问标记
EnQueue(Q,w);//顶点w入队列
}
}
}
BFS算法求解单源最短路径问题
//BFS算法求解单源最短路径问题
void BFS_MIN_Distance(Graph G,int u)
{
//d[i]表示从u到i结点的最短路径
for(i=0;i<G.vexnum;++i)
d[i]= ∞;//初始化路径长度
visited[u]=TRUE;d[u]=0;
EnQueue(Q,u);
while(!isEmpty(Q)) {
//BFS算法主要过程
DeQueue(Q,u);//队头元素u出队
for(w=FirstNeighbor(G,u);w>=0;w=NextNeighbor(G,u,w))
//FirstNeighbor(G,u)求图G中顶点u的第一个邻接点,若有则返回顶点号。若u没有邻接点或图中不存在u,则返回-1
//NextNeighbor(G,u,w)假设图G中顶点w是顶点u的一个邻接点,返回除w之外顶点u的下一个邻接点的顶点号,
//若w是u的最后一个邻接点,则返回-1
if(!visited[w]){
//w为u的尚未访问的邻接顶点
visited[w]=TRUE;//设已访问标记
d[w]=d[u]+1;//路径长度+1
EnQueue(Q,w);//顶点w入队
}
}
}
5.递归形式 深度优先算法
//递归形式 深度优先算法
bool visited[MAX_VERTEX_NUM];//访问标记数组
void DFSTraverse(Graph G){
//对图G进行深度优先遍历,访问函数为visit()
for(v=0;v<G.vexnum;++v)
visited[v]=FALSE;//初始化已访问标记数组
for(v=0;v<G.vexnum;++v)
if(!visited[v])
DFS(G,v);
}
void DFS(Graph G,int v)
{
//从顶点v出发,采用递归思想,深度优先遍历图G
visit(v);//访问顶点v
visited[v]=TRUE;//设已访问标记
for(w=FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v.w))
if(!visited[w]){ //w为u的尚未访问的邻接顶点
DFS(G,w);
}
}
6.弗洛伊德算法(天勤)
//弗洛伊德算法(天勤)
void Floyd(MGraph g,int Path[][maxSize])
{
int i,j,k;
int A[maxSize][maxSize];
//双循环对数组A[][]和Path[][]进行了初始化
for(i=0;i<g.n;i++)
{
A[i][j]=g.edges[i][j];
Path[i][j]=-1;
}
//下面三层循环是本算法主要操作,完成了以k为空间点对所有的顶点对{i,j}进行行检测和修改
for(k=0;k<g.n;++k)
for(j=0;j<g.n;++j)
if(A[i][j]>A[i][k]+A[k][j])
{
A[i][j]>A[i][k]+A[k][j];
Path[i][j]=k;
}
}
7.拓扑排序
//拓扑排序
bool TopologicalSort(Graph G)
{
//若G存在拓扑序列,返回true,否则返回false,这时G中存在环
InitStack(S);//初始化栈,存储入度为0的顶点
for(int i=0;i<G.vexnum;i++)
if(indegree[i]==0)
Push(S,i);//将所有入度为0的顶点进栈
int count=0;//计数,记录当前已经输出的顶点数
while(!IsEmpty(S)) {
///栈不空,则存在入度为0的顶点
Pop(S,i);//栈顶元素出栈
print[count++]=i;//输出顶点i
for(p=G.vertices[i].firstarc;p->nextarc){
//将所有i指向的顶点的入度减一,并且将入度减为0的顶点压入栈S
v=p->adjvex;
if(!(--indegree[v]))
Push(S,v);//入度为0,则入栈
}
}
if(count<G.vexnum)
return false;//排序失败,有向图中有回路
else
return true;//拓扑排序成功
}