java实现 基于邻接链表的BFS 和 (递归/非递归) DFS

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]);  //递归深度优先搜索

        }   
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值