图简介2- 邻接表实现无向图+深度/广度优先搜索

本文介绍了无向图的邻接表结构,详细阐述了如何添加和删除顶点、边,以及在删除顶点时注意的边链表调整。同时,讨论了深度优先搜索和广度优先搜索的实现,强调了两者仅在使用数据结构(栈与队列)上的区别,提供了完整的代码实现。
摘要由CSDN通过智能技术生成
用邻接表实现了一个无向图,在实现时,包含了添加和删除顶点,添加和删除边,size方法(顶点个数),isEmpty方法,广度和深度优先迭代器

1,成员变量,构造方法,数组扩展

复制代码
  
  
  
private VNode[] VNodes; // 将顶点放在数组中
private int nodeCount; // 顶点个数,也表示下一个可用的顶点数组下标
private int edgeCount; // 边个数

// int kind; // 图种类标识

public UnDirectedGraph() // 构造一个空图
{
VNodes
= new VNode[ 5 ];
nodeCount
= 0 ;
edgeCount
= 0 ;
}

private void expand() // 数组扩展
{
VNode[] larger
= new VNode[VNodes.length * 2 ];
for ( int i = 0 ;i < VNodes.length;i ++ )
{
larger[i]
= VNodes[i];
larger[i].setFirst(VNodes[i].getFirst());
// 注意还要把边链表拉起来
}
VNodes
= larger;
}
复制代码


当顶点数组不够用时,要扩展顶点数组,这个跟之前的差别在于将VNodes[i]赋给lager[i],后,还要把它的边链表拉过来,见注释



2,建图(顶点,边的添加删除方法)

1)添加一个顶点容易,直接在数组里添加一个元素即可(而且是添加到最后一个下标,所以很easy)

2)删除一个顶点要先删除跟这个顶点有关联的全部边,然后将这个顶点从数组里移除,为了保持数组的连续性,还要把数组里在该顶点之后的顶点前移,而且还要把边链表拉过来(之前我也就考虑到了这一步,写这个文章的时候忽然发现还有错,当后面的顶点都往前移动了,顶点在数组里的位置就变了,那么数组里所有顶点的边链表里的边信息(边的2个端点)就要变

3)添加一条边,在无向图里,添加一条从VNodes[i]到VNodes[i]的边和反过来添加是一样的,要在两个顶点的边链表里分别添加

4)删除一条边,同上,要在2个顶点的边链表里同时删除


从上面的分析可以看出,删除顶点的时候要调用删除边的方法,也就是说删除顶点包含了删除边。所以先来实现边的方法,再来实现顶点的方法

边的表示:

复制代码
  
  
  
package Graph;

public class Edge {

private int start,end; // 边指向两个节点的位置(如果用数组存放节点,就是下标,如果用链存放下标,就是位置索引)
private Edge next; // 边指向的下一条边

private int len; // 边的信息(长度)


public Edge( int start, int end) // 用起始顶点和结束顶点构造一条边
{
this .start = start;
this .end = end;
next
= null ;
}

public Edge( int start, int end, int len) // 用起始顶点和结束顶点构造一条边
{
this .start = start;
this .end = end;
this .len = len;
next
= null ;
}

// set get省略
}
复制代码


用了2种方法来构造边,一种要长度,一种不要长度。



1)public void addEdge(int start,int end,int len)   在指定2个顶点之间添加指定长度的边

复制代码
  
  
  
public void addEdge( int start, int end, int len){ // 在两个指定下标的节点之间添加一条边
if (start < 0 || start >= size() || end < 0 || end >= size() || start == end)
{
System.out.println(
" 节点选取非法!!! " );
return ;
}
if (hasEdge(start,end))
{
System.out.println(
" 这两点之间已经存在一条边!!! " );
return ;
}

// 写一个支持方法将某个边添加到一个顶点的边链表中,减少了许多注释中的重复代码
Edge edge = new Edge(start,end,len);
addEdgeToVNodeList(VNodes[start],edge);
// 将边添加到某个顶点边链表中的方法

edge
= new Edge(end,start,len);
addEdgeToVNodeList(VNodes[end],edge);

edgeCount
++ ;
}
复制代码

其中用到了2个支持方法,hasEdge(int start,int end)判断2个顶点之间是否有边,这个也可以当公有方法用;private void addEdgeToVNodeList(VNode node,Edge edge) 将条边添加到一个顶点的边链表中去的方法(前提是这个边肯定是这个顶点的边链表中的边),注意要调用2次这个方法

下面看一下这2个支持方法:

public boolean hasEdge(int start,int end):

复制代码
  
  
  
public boolean hasEdge( int start, int end){ // 判断2个顶点之间是否存在边
if (VNodes[start].getFirst() == null )
return false ;
else
{
Edge temp
= VNodes[start].getFirst();
while (temp != null )
{
if (temp.getEnd() == end)
return true ;
else temp = temp.getNext();
}
}
return false ;
}
复制代码


private void addEdgeToVNodeList(VNode node,Edge edge):

复制代码
  
  
  
private void addEdgeToVNodeList(VNode node,Edge edge){ // 将一条边添加到某个节点的边链表中

if (node.getFirst() == null ) // 将边添加到start顶点的边链表中去
node.setFirst(edge);
else {
Edge temp
= node.getFirst();
while (temp.getNext() != null )
temp
= temp.getNext(); // 最后一条边
temp.setNext(edge);
}
}
复制代码




2)public void removeEdge(int start,int end)    //删除两个指定下标顶点之间的边

复制代码
  
  
  
public void removeEdge( int start, int end){ // 删除两个指定下标顶点之间的边
if (start < 0 || start >= size() || end < 0 || end >= size() || start == end)
{
System.out.println(
" 节点选取非法!!! " );
return ;
}
if ( ! hasEdge(start,end))
{
System.out.println(
"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值