深度优先算法计算路径问题

        今天我们运用之前学过的深度优先算探索来求两点间路径问题,如果没有学习过深度优先探索的,快点点链接去学习吧!

点这里查看深度优先算法​​​​​​​z



 

 在解决该问题时,我们会使用到队列和栈这种数据结构,所以我们先用代码实现一下

队列: 

public class Queue<T> {
    private Node head;
    private Node last;
    int N;
    //定义节点内部类
    private class Node
    {
        T item; //节点存储的值
        Node next; //下一个节点
        public Node(T item,Node next) //构造方法
        {
            this.item=item;
            this.next=next;
        }
    }
    //Queue类的构造方法
    public  Queue()
    {
        this.head=new Node(null,null);
        this.N=0;
        this.last=null;
    }
    //判断队列是否为空
    public boolean isEmpty()
    {
        return N==0;
    }
    //返回队列的大小
    public int size()
    {
        return N;
    }
    //向队列尾部插入元素
    public void  enqueue(T item)
    {
        if(this.last==null)
        {
            this.last=new Node(item,null);
            head.next=last;
            N++;
            return;
        }
        Node newlast=new Node(item,null);
        this.last.next=newlast;
        last=newlast;
        N++;
    }
    //弹出队列头部的第一个元素,并返回该元素
    public T dequeue()
    {
        if(isEmpty())
        {
            return null;
        }
        Node oldfir = head.next;
        head.next=oldfir.next;
        N--;
        if(isEmpty())
        {
            this.last=null;
        }
        return oldfir.item;
    }
}

队列按进入队列的顺序弹出元素,先进先出,后进后出 

栈: 

public class Stack<T> implements Iterable<T>{
    private Node head;  //首节点
    private int N;  //栈的大小

    //使用链表来实现栈
    private class Node {
        T item;
        Node next;
        public Node(T item,Node node)
        {
            this.next=node;
            this.item=item;
        }
    }
        //对栈的初始化
        public Stack()
        {
            this.head=new Node(null,null);
            this.N=0;
        }
        //判断栈是否为空
        public boolean isEmpty()
        {
            return N==0;
        }
        //返回栈的大小
        public int size()
        {
            return N;
        }
        //向栈中添加元素(首节点不存储元素)
        public void push(T item)
        {
            Node old = head.next;
            Node node = new Node(item, old);
            head.next=node;
            N++;
        }
        //弹出栈中元素并返回该元素
        public T top()
        {
            Node top = head.next;
            if(top==null)
            {
                return null;
            }
            head.next=top.next;
            N--;
            return top.item;
        }

栈是一种存储元素的数据结构,与队列相反,栈先弹出后进入的元素

图的实现

public class Graph {
    private final int pointcount; //图中的点的数量
    private int linecount;  /图中的线的数量
    private Queue<Integer>[] adj; //队列数组,用于存储每一个点的相邻点
    
    //构造方法
    public Graph(int N) {
        this.pointcount = 0;
        this.linecount = N;
        //初始情况下每个点没有相邻点
        this.adj = new Queue[N];
        for (int i = 0; i < N; i++) {
            adj[i] = new Queue<Integer>();
        }
    }
     //返回图的点的数量
    public int pointcount() {
        return this.pointcount;
    }
    //返回图的线的数量
    public int linecount() {
        return this.linecount;
    }
    //使图中 v,w两点相连
    public void addEdge(int v, int w)
    {
        adj[v].enqueue(w); //在w的相邻点队列中加入v
        adj[w].enqueue(v); //在v的相邻点队列中加入w
        this.linecount++;  //线数目加1
    }
    //返回某个点的相邻点的队列
    public Queue<Integer> adj(int v)
    {
        return adj[v];
    }
}

        好的,万事俱备,只欠东风,我们可以开始对算法的实现了

public class DepthFirstPath {
        //布尔数组:用来确认节点是否被遍历过
        private boolean [] marked;
        //路径的起始点
        private int s;
        //用来存储路径的数组,每一个索引的值表示该节点,数组中索引处的值指向上一个节点,即确定从哪里来的
        private int [] edgeto;
        //构造方法
        public DepthFirstPath(Graph g,int s)
        {
                //外界输入确定图和起点
                this.s=s;
                //初始化布尔数组
                this.marked=new boolean[g.V()];
                //初始化
                this.edgeto=new int[g.V()];
                for(int i=0;i<g.V();i++)
                {
                        marked[i]=false;
                        edgeto[i]=-1;
                }
                //实现深度优先算法
                dfs(g,s);
        }
        public void dfs(Graph g,int s)
        {
                //标记节点s已遍历
                marked[s]=true;

                //获取相邻点的队列
                Queue<Integer> q = g.adj(s);
                //获取队列长度
                int size=g.adj(s).size();
                //对节点s的相邻节点遍历
                for(int i=0;i<size;i++)
                {

                        //弹出队列中一点
                        Integer dequeue = q.dequeue();
                        //判断是遍历过
                        if(!marked[dequeue])
                        {
                                //没有遍历过
                                //使该点处的值为指向它的点;
                                edgeto[dequeue]=s;
                                //再递归调用该方法,直到遍历完所有相通的点
                                dfs(g,dequeue);
                        }
                }
        }
        //判断初始点是否可以达到点point,如果marked[point]为真,则证明可以达到
        public boolean haspathto(int point)
        {
                return marked[point];
        }
        //返回存储到达点k路径的栈
        public Stack<Integer> path(int k)
        {
                //判断路线是否存在,不存在返回空
                if(haspathto(k))
                {
                        //存在则创建一个栈存储路径
                        Stack<Integer> stack=new Stack<>();
                        //从终点开始遍历,不断向栈中点,由于栈先进后出的特点,最后从栈中弹出的点顺序即为路径
                        for(int i=k;i!=this.s;i=edgeto[i])
                        {
                                stack.push(i);
                        }
                        //最后向栈中添加初始点
                        stack.push(this.s);
                        return stack;
                }
                return null;
        }
}

下面,让我们来进行测试

public class RoadPathTest {
    public static void main(String[] args) throws IOException {
        //创建一个有六个点的图
        Graph g=new Graph(6);
        //在图中建立点的联通关系
        g.addEdge(0,2);
        g.addEdge(0,1);
        g.addEdge(2,1);
        g.addEdge(2,3);
        g.addEdge(2,4);
        g.addEdge(3,5);
        g.addEdge(3,4);
        g.addEdge(0,5);
        DepthFirstPath path=new DepthFirstPath(g,0);
        //得到结果
        Stack<Integer> path1 = path.path(4);
        //遍历栈并输出
        while(!path1.isEmpty())
        {
            System.out.print(path1.top()+" ");
        }
    }
}

测试用图的结构为

 测试结果为

0 2 3 4 

 这样算法就实现了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值