java 数据结构 无向图_数据结构之无向图 - osc_b4qlyocq的个人空间 - OSCHINA - 中文开源技术交流社区...

本文介绍了无向图的概念,包括自环和平行边,并提供了相关术语的定义。通过图的基本操作API,如添加边、获取顶点度数、计算自环数量等,展示了如何在Java中实现无向图数据结构。文章还讨论了图的不同表示方法,如邻接矩阵、边的数组和邻接表数组,并给出了邻接表数组的Java代码实现。
摘要由CSDN通过智能技术生成

前言:

我们所讨论的图模型中,边仅仅是两个顶点之间的连接。一般使用0-(V-1)来表示一张含有V个顶点的图中的各个顶点。用v-w的记法表示v点和w点之间的边(又可以写成w-v)。

特殊的两种图:

自环:  一条连接一个顶点和其自身的边。

平行边: 连接同一对顶点的两条边。

以下所说的图两个顶点之间仅含有一条边。

相关术语:

当边连接两个顶点时,我们说顶点彼此 相邻。

顶点的度数为依附于他的边的总数。

子图是一幅图所有被边的一个子集(包括他们所依附的顶点)。

路径是由边连接的顶点序列,没有重复的边。

简单路径是没有重复顶点的路径。

环是一条至少含有一条边且起点和终点相同的路径。

简单环是一条(除了起点和终点必须相同之外)不含重复顶点和边的环。

路径或环的长度为其包含的边数。

如果从任意一个顶点都存在一条路径到达另一个任意顶点,则称这幅图是连通图。

一个非连通图由若干连通图组成,它们都是极大连通子图。

无环图是一个不包含环的图。

树是一副无环连通图。互不相连的树组成森林。连通图的生成树是他的一副子图,它含有图中的所有顶点且是一颗树。图的生成森林是他的所有连通子图的生成树的集合。

300cd9e257f338ddd7480dce2a097e60.png

7ccc11db4e563ac460b76f35134d6a86.png

25d87925f4567ceeb0f032d6c79e5e70.png

关于树的定义,以下五种说法是等价的:(一副含有V个顶点的图G)

1:G有V-1条边并且不含环。

2:G有V-1条边并且是联通的

3:G是连通的且删除任意一条边都会使他不连通。

4:G是无环图且添加任意一条边都会使他产生一条环。

5:G中任意一对顶点间仅存在一条简单路径。

我们定义以下图的基本操作API:

Public  class   Graph

Graph(int V)   //创建一个含有V个顶点但不含边的图

Graph(InputStream in) //从标准输入流中读取一个图

int     V()    //顶点数

int     E()    //边数

void addEdge(int v,int w)  //添加边V-W

Iterable adj(int v)   //遍历与v相邻的顶点

String toString()      // @Override

相关实现:

计算V的度数:

public static int degree(Graph g,int v)

{    int  degree=0;

for(int w: g.adj(v)) degree++;

return degree;

}

计算所有顶点的最大度数:

public static int maxDegree(Graph g)

{    int  max=0;

for(int v=0;v

if(degree(g,v)>max)

max=degree(g,v);

return  max;   }

计算自环的个数:

public static int numberOfSefLoops(Graph g)

{   int count=0;

for(int v=0;v

for(int w:g.adj(v))

if(w==v)  count++;

return count/2;

}

//覆写toString方法@Override

public String toString()

{

String s=V+”vertices”+E+” edges\n”;//建议你用StringBuilder

for(int v=0;v

{   s+=v+”:  ”;

for(int w:this.adj(v))

s+=“\n”;

}

return  s;

}

图的几种表示方法:

要求:  1、必须为各种情况下遇到的图预留足够空间。

2、快。

邻接矩阵:

用一个V * V的Boolean矩阵表示,1代表相连。

//不满足第一种要求。

边的数组:

使用一个Edge类,含有两个int变量。

/不满足第二个要求,比如调用adj方法。

邻接表数组:(推荐)

使用以顶点为索引的列表数组,其中每个元素都是和该顶点相连的顶点列表。如下图:

f63fffdbb7ab11e13e58a9a99ff19c65.png

要连接一条v到w的边,我们要将w添加到v的邻接表中并把v添加到w的临界表中。因此这种结构中每条边都会出现两次。

代码实现:

//我们使用前面介绍过的Bag,Stack实现,相关代码请看数据结构之队列、栈。

09fd0d95399f436b8372693225e4d371f72.jpg

8c080ac01ec725f8259b2358bd6ecca76ae.jpg

1 public classGraph {2

3 private final intV;4 private intE;5 private Bagadj[];6

7 @SuppressWarnings("unchecked")8 public Graph(intV)9 { if (V < 0) throw new IllegalArgumentException("Number of vertices must be nonnegative");10 this.V=V;11 this.E=0;12 adj= (Bag[])newBag[V];13 for(int i=0;i();16 }17 }18

19 publicGraph(Graph G) {20 this(G.V());21 this.E =G.E();22 for (int v = 0; v < G.V(); v++) {23

24 Stack reverse = new Stack();25 for (intw : G.adj[v]) {26 reverse.push(w);27 }28 for (intw : reverse) {29 adj[v].add(w);30 }31 }32 }33

34 public intV()35 {36 return this.V;37 }38

39 public intE()40 {41 return this.E;42 }43

44 private void validateVertex(intv) {45 if (v < 0 || v >=V)46 throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1));47 }48

49 public void addEdge(int v,intw)50 { validateVertex(v);51 validateVertex(w);52 adj[v].add(w);53 adj[w].add(v);54 E++;55 }56

57 public Iterable adj(intv) {58 validateVertex(v);59 returnadj[v];60 }61

62 public int degree(intv) {63 validateVertex(v);64 returnadj[v].size();65 }66

67 publicString toString() {68 StringBuilder s = newStringBuilder();69 s.append(V + " vertices, " + E + " edges ");70 for (int v = 0; v < V; v++) {71 s.append(v + ": ");72 for (intw : adj[v]) {73 s.append(w + " ");74 }75 s.append("\r");76 }77 returns.toString();78 }79

80 }

View Code

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值