package 算法;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.Stack;
public class First_Search {
static int len_v=20; //点的个数
static int len_e=30; //边的个数
private static boolean visited[]=new boolean[len_v]; //BFS中被访问的点
private static boolean visited2[]=new boolean[len_v]; //DFS中被访问的点
static Vertex ver[]=new Vertex[len_v]; //存放点
static int distance[]=new int[len_v]; //存放BFS距离
static int num[]=new int[len_v];
static int len[]=new int[len_v];
static Queue<Vertex> q=new LinkedList<Vertex>(); //广度优先搜索中存放点的队列
static Stack<Vertex> s=new Stack<Vertex>(); //非递归DFS的栈
static class Vertex
{
int n;//邻接链表的点
List<Integer> list=new LinkedList<Integer>();
//点的构造方法
public Vertex(int n)
{
this.n=n;
}
//向该点的链表中增加点
public void add(int value)
{
list.add(value);
}
}
static class Edge
{
int u;//该点
int v;//下一个点
//构造方法
public Edge(int u,int v)
{
this.u=u;
this.v=v;
}
@Override
//重写hashcode方法
public int hashCode() {
return v;
}
@Override
//重写equals方法
public boolean equals(Object obj) {
if(!(obj instanceof Edge)){
return false;
}
if(obj == this){
return true;
}
return this.v==((Edge)obj).v&&this.u==((Edge)obj).u;
}
}
//csh即初始化
public static void csh()
{
//构建100个点
for(int i=0;i<len_v;i++)
{
ver[i]=create(i+1);
//ver[i].list.add(i+1);
visited[i]=false;
visited2[i]=false;
}
//构建500条边
Edge e;
Set<Edge> s=new HashSet<Edge>();//存储所有的边
while(s.size()<len_e)
{
int u=random();
int v=random();
while(u==v||s.contains(new Edge(u,v)))
v=random();
e=new Edge(u,v);
if(!s.contains(e))
s.add(e);
}
//将500条边加到对应的起始点的链表中
Iterator<Edge> it=s.iterator();
while(it.hasNext())
{
Edge ee=(Edge) it.next();
ver[ee.u-1].list.add(ee.v);
//System.out.println(ee.u+" * "+ee.v);
}
}
//重新初始化BFS和DFS标注点
public static void csh1()
{
for(int i=0;i<len_v;i++)
{
visited[i]=false;
visited2[i]=false;
}
}
public static void print(Vertex ver[])
{
System.out.println("打印所有点的邻接链表:");
//打印所有的邻接链表
for(int i=0;i<len_v;i++)
{
int len=ver[i].list.size();
System.out.print(ver[i].n+"-->");
for(int j=0;j<len;j++)
System.out.print(ver[i].list.get(j)+"-->");
System.out.println("");
}
}
public static int random()
{
//生成随机数1-100
int i=(int) (Math.random()*len_v+1);
return i;
}
//构造100个点的邻接链表
public static Vertex create(int n)
{
return new Vertex(n);
}
public static void BFS(Vertex v)
{
visited[v.n-1]=true; //将参数对应的点标记为已读
q.add(v); //队列中增加该点
System.out.print(v.n+"-->");
while(!q.isEmpty())
{
Iterator<Integer> i=q.poll().list.iterator(); //遍历队列头结点对应的邻接链表
while(i.hasNext())
{
int n=i.next();
//将该点邻接链表中所有未读的点放入队列
if(visited[n-1]==false)
{
q.add(ver[n-1]);
visited[n-1]=true;
System.out.print(n+"-->");
}
}
}
}
public static void BFS_distance(Vertex v)
{
for(int i=0;i<len_v;i++)
distance[i]=0;
visited[v.n-1]=true; //将参数对应的点标记为已读
q.add(v); //队列中增加该点
System.out.print(v.n+"-->");
distance[v.n-1]=0;
while(!q.isEmpty())
{
int tem=distance[q.peek().n-1];
Iterator<Integer> i=q.poll().list.iterator(); //遍历队列头结点对应的邻接链表
while(i.hasNext())
{
int n=i.next();
//将该点邻接链表中所有未读的点放入队列
if(visited[n-1]==false)
{
distance[n-1]=tem+1;
q.add(ver[n-1]);
visited[n-1]=true;
System.out.print("("+n+","+distance[n-1]+")"+"-->");
}
}
}
}
public static void DFS(Vertex v)
{
visited2[v.n-1]=true; //将参数中对应点标为已读
System.out.print(v.n+"-->");
//接下来的操作针对的是该点的邻接链表中的点(除自身)
int i=0;
while(i<v.list.size())
{
//System.out.println(v.n+" * ");
Vertex tem=ver[(int)v.list.get(i)-1]; //定义为该点的下一个点
//System.out.println(tem.n+" * ");
//当tem点未读,则对该点递归进行深度优先搜索
if(visited2[tem.n-1]==false)
DFS(tem);
i++;
}
}
//非递归DFS
public static void DFS2(Vertex v)
{
visited2[v.n-1]=true; //将参数中对应点标为已读
s.add(v); //将初始点加入栈中
System.out.print(v.n+"-->"); //打印该点
while(!s.empty())
{
int i=0; //现在搜寻点邻接链表中的第一个邻接点
while(i<v.list.size())
{
Vertex tem=ver[(int)v.list.get(i)-1]; //定义为该点的下一个点
if(visited2[tem.n-1]==false)
{
s.add(tem); //将该点邻接表中第一个(未读)邻接点放入栈中
System.out.print(tem.n+"-->");
i=0;
visited2[tem.n-1]=true; //把刚才放入的点标记为已读
}
else
i++; //若第i个点已读,继续寻找未读邻接点
v=s.peek(); // v=刚才放入的那个点(即继续向下一层进行while寻找)
}
s.pop(); //这一条深度搜寻链已到底,将最底下的那个点从栈中删除
if(!s.empty())
v=s.peek(); //回溯到上一个点
}
}
//非递归DFS求最大长度路径 (max为边的长度,也就是最长路径中点的个数为max+1)
public static void topolongiest(Vertex v,Stack<Integer> s)
{
int max=0;
Stack<Integer> ss=new Stack<Integer>(); //存放节点
int length=s.size();
for(int i=0;i<len_v;i++)
{
len[i]=0; //初始化所有点的最大长度为0
}
for(int j=0;j<length;j++)
{
Vertex ve=ver[s.get(j)-1]; //当前节点
int n=ve.n; //当前节点的值
int l=ve.list.size(); //当前节点邻接链表的长度
int t=0; //存放动态规划最大长度点
//如果该点的邻接链表中有除了自己以外的点,即该点非叶子结点
if(l>0)
{
if(l==1)
{
len[n-1]=len[(int) ve.list.get(0)-1]+1; //如果l=1(除自己外只有一个邻接点) 即无分支 直接加一
//System.out.println((int) ve.list.get(1));
ss.add((int) ve.list.get(0));
if(len[n-1]>=max)
{
max=len[n-1];
//System.out.println(n+"*"+max);
}
}
else
{
//若有分支,则动态规划找出路径最长的分支
int temp_max=len[(int) ve.list.get(0)-1]; //初始最大值为第一个点
//动态规划法,找出该点邻接链表中各点的最大路径长度temp_max 和具有最大长度的点的值t
for(int k=1;k<=l-1;k++)
{
if(len[(int) ve.list.get(k)-1]>temp_max)
{
temp_max=len[(int) ve.list.get(k)-1];
//System.out.println((int) ve.list.get(k));
t=(int) ve.list.get(k);
}
}
//System.out.println(t);
ss.add(t); //把该点放入栈中,最终输出该栈即为最长路径
len[n-1]=temp_max+1; //加上自己,+1
//最大长度
if(len[n-1]>=max)
{
max=len[n-1];
//System.out.println(n+"*"+max);
}
}
}
}
System.out.println("");
System.out.println(max+"*"); //输出最终的最大长度
}
public static void main(String args[])
{
csh(); //初始化
print(ver); //打印邻接链表
System.out.println("");
System.out.println("BFS:");
BFS(ver[0]); //广度优先搜索
csh1();
System.out.println("");
System.out.println("BFS距离:");
BFS_distance(ver[0]);
System.out.println("");
csh1();
System.out.println("非递归DFS:");
DFS2(ver[0]); //非递归深度优先搜索
System.out.println("");
csh1();
System.out.println("递归DFS:");
DFS(ver[0]); //递归深度优先搜索
}
}
java实现 基于邻接链表的BFS 和 (递归/非递归) DFS
最新推荐文章于 2024-08-17 08:59:42 发布