用邻接表实现了一个无向图,在实现时,包含了添加和删除顶点,添加和删除边,size方法(顶点个数),isEmpty方法,广度和深度优先迭代器
1,成员变量,构造方法,数组扩展
用了2种方法来构造边,一种要长度,一种不要长度。
1)public void addEdge(int start,int end,int len) 在指定2个顶点之间添加指定长度的边
其中用到了2个支持方法,hasEdge(int start,int end)判断2个顶点之间是否有边,这个也可以当公有方法用;private void addEdgeToVNodeList(VNode node,Edge edge) 将条边添加到一个顶点的边链表中去的方法(前提是这个边肯定是这个顶点的边链表中的边),注意要调用2次这个方法
下面看一下这2个支持方法:
public boolean hasEdge(int start,int end):
private void addEdgeToVNodeList(VNode node,Edge edge):
2)public void removeEdge(int start,int end) //删除两个指定下标顶点之间的边
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( "