- 算法老师布置的一个小作业,在大哥的点拨下完成了这个实现,也是对Java链表的一种熟悉。如有不正确之处还请各位大神指教!
- 要求:生成一个随机图,(原则上是上限50个点,100条边),用链表进行存储,本次试验的结果作为下次试验的素材。
- 首先,自己是一个小白,对于链表只是只闻其名,不知其理,搞完这个之后,对于链表的结构以及用法都有了进一步的了解。实现这个功能的最主要之处就是弄清楚整个图存储方式的大体架构和各个数据结构变量属性之间的层次关系。
言归正传:
首先要了解一下Java中的链表类linkedList,是Java.util包下的一个类,大家可以下载一个JavaAPI去查看一下该类的具体构造函数和调用方法。下载中文版JavaAPI点击此处
实现的主要过程:创建一个链表类型的数组point[],数组的每一个元素都是一个链表,并且每个链表元素又是Node类的一个对象,弄清楚这个层次关系是实现的关键。
下边就是具体的代码实现了:
(1)创建Node类,用于保存图一条边的末节点(endPoint)还有权重(weight),还有其相应的构造方法。
(2)创建Random_Graph类的构造方法:
A:首先LinkedList类和Random类都在Java.util 包中,所以import java.util.*;
B:然后定义一个ListedList类型的数组point,在构造方法中实例化为new LinkedList[numPoint];
这就类似于定义一个int类型数组:int [] arr =new int [32];
C: Random_Graph类的构造方法中各个参数的意义:
numPoint:图节点的数目;
numEdge:图边的数目;
has_director:图为有向图(有向图一条边只需要存储一次,无向图一条边存储两次);
has_weight : 图为有权重的图(无权重的图默认权重为1)。
D:通过一个for循环将数组point初始化赋值
关于在定义数组和初始化数组的时候加上一个“《Node》”,目的是使数组元素为Node类型,以便于实现endPoint和weight属性。官方化的解释见JavaAPI中LinkedList的构造方法:
(3)添加一条边的前提以及需要注意的事项:
A:首先随机生成一条边的起始点(startPoint)和终止点(endPoint);
B:一条边的起始点和终止点为同一个点,则该边为一个自环,应该避免这种现象;
C:如果一条边已经创建了,那么就跳出该循环。(起始点和终止点相同的边视为同等边)
(4)判断是否有权重,是否为有向图,把边加到链表中
A :默认权重为1,如果存在权重,随机生成一个权重(范围为1-9);
B:判断是否为有向图,无向图需要添加两次。
这个地方用到了链表的库函数:add();参数类型是Node类型。
至此构造方法已经完毕。
下边再构造一个print方法:遍历打印出图的首节点和末尾节点以及权重。
main方法实现以下:
运行结果:
无向图对应的节点和相应的权重,同一条边添加两次的对应形式。
源码如下:
package algorithm;
import java.util.*;
public class Random_Graph {
LinkedList<Node> []point;
public Random_Graph(int numPoint,int numEdge,boolean has_director,boolean has_weight){
point =new LinkedList[numPoint];
for(int i=0;i<numPoint;i++){
point[i]=new LinkedList<Node>();
}
// 随机生成起始点和终止点
while (numEdge>0){
Random r=new Random();
int startPoint=r.nextInt(numPoint);
int endPoint=r.nextInt(numPoint);
// 如果起始点等于终止点,那么就在一点生成一条环,去除这种情况
while(startPoint==endPoint){
endPoint=r.nextInt(numPoint);
}
// 如果这条边已经有了,那么就跳过该次循环
boolean has_edge=false;
for(int j=0;j<point[startPoint].size();j++){
if(point[startPoint].get(j).endpoint==endPoint){
has_edge=true;
break;
}
}
if(has_edge){
continue;
}
// 如果有权重,加上随机生成的权重,否则默认为1
int weight=1;
if(has_weight){
weight=r.nextInt(9)+1;
}
// 如果是无向图,那么一条边需要加两次
if(has_director){
point[startPoint].add(new Node(weight,endPoint));
}
else{
point[startPoint].add(new Node(weight,endPoint));
point[endPoint].add(new Node (weight,startPoint));
}
numEdge--;
}
}
public void print_Graph(){
for(int i=0;i<point.length;i++){
System.out.print("the start_point is: "+i);
for(int j=0;j<point[i].size();j++){
System.out.print(" "+point[i].get(j).endpoint+" ("+point[i].get(j).weight+")");
}
System.out.println();
}
}
public static void main(String []args){
Random_Graph g=new Random_Graph(10,20,false,true);
g.print_Graph();
}
}
class Node{
int weight;
int endpoint;
public Node(int weight,int endpoint){
this.weight=weight;
this.endpoint=endpoint;
}
}
小白入手,如果有不妥当的地方,还望指教!