数据结构 C6 图(上)

简介: 数据结构 C6 图

6.1图的基本概念


6.1.1图的定义(见王道书)


图的基本定义(


有向图/无向图


简单图/完全图,数据结构只讨论简单图


完全图/子图


连通/连通图/连通分量/最大连通分量/最小连通分量/强连通/强连通图/强连通分量/最大强连通分量/最小强连通分量


生成树/生成森林


度/入度/出度


边的权和网


稠密图/稀疏图


路径/路径长度/回路/简单路径/简单回路/距离


有向树


6.2图的存储及其基本操作


6.2.1邻接矩阵法


邻接矩阵法:

图的存储结构 有向图 无向图

对于图,它分为顶点还有边;边就是两个顶点的邻接关系,所以说要把图这个东西储存的话,就一定要分别储存点还有边。

图一般意义分为有向图还有无向图;对于前者后者顶点存储方式相同;但是对于后者存储方式是不同的;

那么我们怎么储存呢;

对于点来说,他就是一个整形数据啥的,用一个一维数组就可以了;对于边来说用二维数组了。如下图1。左边有向 右边无向;

1670672670054.jpg

看一个有向图的存储方法:

1670672733093.jpg

最后的存储结构:

1670672743854.jpg

看一个无向图的存储矩阵:错了(第一列最后一个元素是1)

1670672753073.jpg


最后转化为:

1670672761890.jpg


网呢 储存结构

我们之前说了,如果给每条边一个数值作为该边的权重:就变成了网;

那么我们该如何存储网呢?同样是利用矩阵和数组;如果该边不存在则存放无穷

1670672772628.jpg

举个例子:

1670672781043.jpg


网或者图在语言中是如何定义的?

#define MaxVertexNum 100
typedef char VertexType;
typedef int EdgeType;
typedef struct{
  VertexType Vex[MaxVertexNum];
  EdgeType Edge[MaxVertexNum][MaxVertexnum];
int vexnum,arcnum;
}MGraph;

1670672796741.jpg

性质

1670672805207.jpg

运算:

1670672815057.jpg

1670672824638.jpg

6.2.2邻接表法


当一个图相对比较稠密的时候,他适合采用上面一种邻接矩阵的方法 ,但是把,如果说这个图相对比较稀疏的话,那么采用以上算法就是相对比较浪费了,那用现在介绍的这种方法。邻接表法

采用顶点用顺序结构 而边用链式结构存储


1670672848671.jpg


比如 咱们看一个有向图的例子:

kankan是怎么储存的

1670672959793.jpg

再看一个无向图的例子:

1670672969471.jpg

储存结构:

#define MaxVertNum 100
typedef struct ArcNode{
int adjvex;
struct ArcNode *next;
//InfoType info;//表示权重
}ArcNode;
typedef struct VNode{
  VertexType data;
  ArcNode *first;
}VNode,AdjList[MaxVertexNum];
typedef struct{
  Adjust vetices;//邻接表
int vexnum,arcnum;
}ALGraph;


特点:


1670672990222.jpg


比较邻接矩阵和邻接表的异同:

1670673000336.jpg


6.2.3十字链表


对于连接表而言 找到出边是相对来说比较容易的 但是想找到入边来说 就是比较难的 他需要遍历整个表。

那么我们我们引申出一个新的结构


1670673013679.jpg


存储结构


#define MaxVertexNum 100;
typedef struct ArcNode{
int tailvex,headvex;
struct ArcNode *hlink,*tlink;
//infotype info;
}ArcNode;
typedef struct VNode{
  VertexType data;
  ArcNode *firststin,*firstout;
}VNode;
typedef struct{
  VNode xlist[MaxVertexNum];
int vexnum,arcnum;
}GLGraph;


6.2.4邻接多重表


对于无向图,我们之前使用了邻接表的形式:


1670673147325.jpg


你看一个对于这两个储存空间,如果删除它的时候,需要遍历,而且要删除两个,这样的话会是很麻烦的。于是引用了咱们今天学习的。

1670673158194.jpg

#define MaxVertNum 100;
typedef struct ArcNode{
int ivex ,jvex;
struct ArcNode *ilink,*jlink;
//infotype info;
//bool mark;
}ArcNode;
typedef struct VNode{ 
  VertexType data;
  ArcNode *firstedge;
}VNode;
typedef struct{
  VNode adjmulist[MaxVertexnum];
int vexnum,arcnum;
}AMLGraph;


十字链表 邻接多重表

他们都是邻接表的优化;十字链表针对的是有向图,解决了有向图中无法快速找到某一顶点入边的这一弊端。 邻接多重表解决了无向图中每一个边要用两个边表结构来存放的弊端。

1670673175719.jpg


6.2.5图的基本操作


Adjacent(G,x,y) 判断图G是否存在边或(x,y).

1670673188121.jpg

1670673197136.jpg

Neighbour(G,x) 列出图G中与结点x相邻的边

1670673210839.jpg

1670673218304.jpg

InsertVertex(G,x);在图G中插入顶点x

1670673230478.jpg

右边更好;

DeleteVertex(G,x)从图G中删除顶点x;

1670673239655.jpg

右边更好;

AddEdge(G,x,y);若无向边(x,y)或者不存在,则向图中G中添加该边

1670673248737.jpg

左边更好

RemoveEdge(G,x,y)若无向边(x,y)或者有向边存在,则在图G中删除该边;

1670673259295.jpg

FirstNeighbor(G,x);求图G中顶点X的第一点邻接点,若有则返回顶点号。若没有邻接点或图不存在x,则返回-1;

NextNeighbor(G,x,y) 假设图G中顶点y是顶点x的一个邻接点,返回除了y之外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,则返回-1;


Get_edge_value(G,x,y);获取图G中边(x,y)或<x,y>对应的权值v;
Set_edge_value(G,x,y); 设置G中边(x,y)或<x,y>的权值为v;

1670673291475.jpg


6.3图的遍历


从图的某一点出发,按照某种算法,沿着图中的边,对图中所有的顶点进行一次访问(只访问一次)


6.3.1广度优先搜索


1670673318008.jpg

它和树的层次遍历很像,但是如果又按照层次遍历的算法来 ,一定会出现错误。如下

1670673332891.jpg

那么怎么改善呢

1670673467544.jpg

1670673478335.jpg

算法代码如下:

bool visited[MAX_TREE_SIZE];//定义了一个bool型的辅助标记数组
void BFSTraverse(Graph G){
for(int i=0;i<G.vexnum;++i)
  visited[i]=FALSE;
InitQueue(Q);
for(int i;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]){
    visited[w];
    visited[w]=TRUE;
Enqueue(Q,w);
}
}
}

1670673501255.jpg

1670673512479.jpg

BTS算法的性能分析:

1670673521755.jpg

1670674662556.jpg

关于广度优先搜索解决最短路径问题:(不懂)


==广度优先生成树:=

1670674705916.jpg

1670674717899.jpg


6.3.2深度优先算法


与树的深度优先遍历之间的联系&& 算法实现

树的优先遍历

void preorder(treenode *R ){
if(R!=NULL){
visit(R);
while(R还有下一个子树T)
Preorder(T);
}
}

1670674778497.jpg

1670674791702.jpg


图的深度优先遍历:

bool visited[MAX_VERTEX_NUM];
void DFS(Graph G,int v){
visit(v);
  visited[v]=TRUE;
for(w=FirstNeighbor(G,v);w>=0;w=NextNeihbor(G,v,w))
if(!visited[w]){
DFS(G,w);
} 
}


这辅助了一个函数调用栈:利用栈的栈进栈出来看目前正在执行的那个函数,调用了几层函数;

1670674813261.jpg

咱们看一看这是连通图用上面的算法就可以了,但是对于非连通图来说,无法遍历所有的结点;

优化:

1670674826139.jpg

复杂度分析

1670674843226.jpg

1670674851114.jpg


手动求一下

1670674859690.jpg

1670674867717.jpg

1670674875572.jpg

1670674882408.jpg


深度优先生成树

1670674892826.jpg

1670674901517.jpg

森林呢?

1670674914595.jpg

1670674923018.jpg

图的遍历和图的连通性

1670674935974.jpg

对于有向图具体问题具体分析

1670674945023.jpg



相关文章
|
5月前
|
存储 算法
数据结构===图
数据结构===图
|
4月前
|
算法 Python
逆袭之路!用 Python 玩转图的 DFS 与 BFS,让数据结构难题无处遁形
【7月更文挑战第12天】图的遍历利器:DFS 和 BFS。Python 中,图可表示为邻接表或矩阵。DFS 沿路径深入,回溯时遍历所有可达顶点,适合找路径和环。BFS 层次遍历,先近后远,解决最短路径问题。两者在迷宫、网络路由等场景各显神通。通过练习,掌握这些算法,图处理将游刃有余。
63 3
|
4月前
|
存储 算法 Python
“解锁Python高级数据结构新姿势:图的表示与遍历,让你的算法思维跃升新高度
【7月更文挑战第13天】Python中的图数据结构用于表示复杂关系,通过节点和边连接。常见的表示方法是邻接矩阵(适合稠密图)和邻接表(适合稀疏图)。图遍历包括DFS(深度优先搜索)和BFS(广度优先搜索):DFS深入探索分支,BFS逐层访问邻居。掌握这些技巧对优化算法和解决实际问题至关重要。**
40 1
|
5月前
|
存储
数据结构学习记录——如何建立图(邻接矩阵、邻接表-图节点的结构、创建并初始化、插入变、完整图的建立)
数据结构学习记录——如何建立图(邻接矩阵、邻接表-图节点的结构、创建并初始化、插入变、完整图的建立)
69 0
|
5月前
|
存储 算法
数据结构学习记录——图应用实例-六度空间(题目描述、算法思路、伪代码及解读、图解)
数据结构学习记录——图应用实例-六度空间(题目描述、算法思路、伪代码及解读、图解)
54 0
|
5月前
|
存储 算法 安全
数据结构学习记录——图应用实例-拯救007(问题描述、解题思路、伪代码解读、C语言算法实现)
数据结构学习记录——图应用实例-拯救007(问题描述、解题思路、伪代码解读、C语言算法实现)
39 0
|
5月前
|
存储 C语言
数据结构学习记录——图的遍历(深度优先搜索、广度优先搜索、为什么需要两种遍历、图不连通怎么办)
数据结构学习记录——图的遍历(深度优先搜索、广度优先搜索、为什么需要两种遍历、图不连通怎么办)
58 0
|
5月前
|
存储 机器学习/深度学习
数据结构学习记录——什么是图(抽象数据类型定义、常见术语、邻接矩阵表示法、邻接表表示法)
数据结构学习记录——什么是图(抽象数据类型定义、常见术语、邻接矩阵表示法、邻接表表示法)
62 0
|
6月前
|
算法
【高阶数据结构】图 -- 详解(下)
【高阶数据结构】图 -- 详解(下)
|
6月前
|
存储
【高阶数据结构】图 -- 详解(上)
【高阶数据结构】图 -- 详解(上)

热门文章

最新文章