Data Structure---Graph

来源:互联网 发布:python 处理get请求 编辑:程序博客网 时间:2024/05/22 17:40

图的存储方式

邻接矩阵、邻接表、十字链表、邻接多重表

邻接矩阵

属于图的顺序存储结构。用一个一维Array数组存储图Graph中顶点Vertex信息,用一个二维数组存储图中边Edge的信息,存储定点之间邻接关系的二维数组即邻接矩阵Matrix,适合稠密图,空间复杂度O(V^2)。

//图的邻接矩阵存储结构定义#define MaxVertexNum 100typedef char VertexType;typedef int EdgeType;typedef struct{    VertexType Vextex[MAxVertexNum];    //一维顶点表    EdgeType Edge[MaxVertexNum][MaxVertexNum];  //二维边表    int vexnum,arcnum;} MGraph;

邻接表

属于图的链式存储结构。对图G中的每个顶点Vi建立一个边表(邻接点域adjvex+指针域nextarc),顶点表(顶点域data+边表头指针firstarc)采用顺序存储,适合稀疏图,无向图空间复杂度O(V+2E),有向图空间复杂度O(V+E)。表示不唯一,取决于建立邻接Adjacency表的算法以及边的输入次序。

//图的邻接表存储结构定义#define MaxVertexNum 100typedef struct ArcNode{    int adjvex;    struct ArcNode *next;    //InfoType info;    } ArcNode; typedef struct Vnode{    VertexType data;    ArcNode *first;} Vnode,AdjList[MaxVertemNum];typedef struct{    AdjList vertices;   //邻接表    int vexnum,arcnum;} ALGraph;

十字链表

有向图的一种链式存储结构。对应有向图中的每条弧有一个结点,对应于每个顶点也有一个结点,顶点节点之间是顺序存储。很容易找到Vi为尾或头的弧,容易得到顶点的出度与入度。一个图的十字链表表示不唯一,但一个十字链表表示确定一个图。
弧节点有五个域(尾域tailvex,头域headvex,链域hlink,链域tlink,info),顶点节点有三个域(data,firstin,firstout)。

//图的十字链表存储结构定义#define MaxVertexNum 100typedef strruct ArcNode{    int headvex,tailvex;    struct ArcNode *hlink,*tlink;    //InfoType info;} ArcNode;typedef struct VNode{    VertexType data;    ArcNode *fristin,*firstout;} VNode;typedef struct{    VNode xlist[MaxVertexNum];    int vernum,arcnum;} GLGraph;

邻接多重表

无向图的一种链式存储结构。每一条边用一个结点表示(标志域mark,ivex,ilink,jvex,jlink,info),每一个顶点也用一个结点表示(data,firstedgc)。
所有依附与同一顶点的边串联在同一链表中,每个边节点同时链接在两个链表中。

//图的邻接多重表存储结构定义# define MaxVertexNum 100typedef struct ArcNode{} ArcNode;typedef struct VNode{    VertexType data;    ArcNode *firstedge;} VNode;typedef struct{    VNode adjmulist[MaxVertNum];    int vexnum,arcnum;} AMLGraph;

图的基本操作

# VertexInsertVertex(G,x)DeleteVertex(G,x)FirstNeighbor(G,x)NextNeighbor(G,x,y)Neighbors(G,x)# EdgeAdjacent(G,x,y) AddEdge(G,x,y)RemoveEdge(G,x,y)Get_edge_value(G,x,y)Set_edge_value(G,x,y,v)#SearchBFSTraverse(G)BFS_MIN_Distance(G,u)DFSTraverse(G)

Breadth-First-Search(BFS)

二叉树的层序历遍算法的拓展,借助辅助队列Q分层查找邻接顶点。邻接表存储时,时间复杂度O(V),空间复杂度O(E);邻接矩阵存储时,时间复杂度O(V^2)。

//BDF算法实现bool visited[MAX_VERTEX_NUM];void BFSTraverse(Graph G){    for(i=0;i<G.vexnum,++i)        visited[i]=FALSE;    InitQueue(Q);    for(i=0;i<G.vexnum;++i){        if(!visited[i]){            BFS(G,i)        }    }}void BFS(Graph G,int v){    visit(v);    visited[v]=True;    Enqueue(Q,v);    while(!isEmpty(Q)){        DeQueue(Q,v);        for(w=FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w)){            if(!visited[w]){                visit(w);                visited[w]=TRUE;                ENQueue(Q,w);            }        }    }}
//BFS算法求解无权图的单源最短路径问题void BFS_MIN_Distance(Graph G,int u){    for(i=0;i<G.vernum;++i){        d[i]= ∞;    }    visited[u]=TRUE;    d[u]=0;     //d[i]表示从i到u的最短路径    EnQueue(Q,u);    while(!isEmpty(Q)){        DeQueue(Q,u);   //队头元素出队        for(w=FirstNeighbor(G,u);w>=0;w=NextNeighbor(G,u,w)){            if(!visited[w]){                visited[w]=TRUE;                d[w]=d[u]+1;                EnQueue(Q,w);            }        }    }           }

Depth-First-Search(DFS)

二叉树的先序历遍的拓展,有退回的递归查找邻接顶点。

//DFS递归算法实现bool visited[MAX_VERTEX_NUM];void DFSTraverse(Graph G){    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){    visit(v);    visited[v]=TRUE;    //设已访问标记    for(w=FirstNeighbor(G,v);w>=0;w=Neighbor(G,v,w)){        if(!visited[w]){            DFS(G,w)        }    }}

图的应用

最小生成树、最短路径、拓扑排序、关键路径

Minimum-Spanning-Tree(MST)

连通图–图中任意两个定点都连通
连通分量–无向图的极大连通子图
生成树–连通图中包含全部顶点的一个极小连通子图

//通用MST算法GENERIC_MST(G){    T=NULL;    while(T未形成一棵最小生成树){        do  找到一条最小代价边(u,v)并且加入T后不会产生回路            T=TU(u,v);    }}
Prim-Algorithm

类似于最短路径的Dijkstra算法

//Prim算法构造MST,时间复杂度O(V^2)//从顶点开始找代价最小的边,适合边稠密的图void Prim(G,T){    T=∅;    U={w};    while((V-U)!=∅){        设(u,v)是使u∈U与v∈(V-U),且权值最小的边;        T=TU{(u,v)};        U=UU{v};    }}
Kruskal-Algorithm
//Kruskal算法构造MST,时间复杂度O(ElogE)//按边的权值递增次序选择合适的边,采用堆存放边的集合,适合边稀疏而顶点较多的图void Kruskal(G,T){    T=V;    numS=n;    while(numS>1){        从E中取出权值最小的边(v,u);        if(v与u属于T中不同的连通分量)「        T=TU{(v,u)};        numS--;    }}

最短路径

Dijkstra算法求单源最短路径,时间复杂度O(V^2)
Floyd算法求顶点之间最短路径,时间复杂度O(V^3)

拓扑排序

AOV网—顶点表示活动的有向无环图DGA
DGA的拓扑排序–DGA图中的每个顶点仅出现一次&&若顶点A在序列中排在B前则图中不存在顶点B到A的路径

关键路径

AOE网—用边表示活动的带权有向图(事件V,活动E,开销W)
关键路径–从源点到汇点的所有路径中具有最大路径长度的路径
关键活动–关键路径上的活动
最短完成时间–关键路径的长度