Java实现广度优先搜索

Java实现广度优先搜索

基本思想

从出发节点开始访问,然后去访问该节点的所有相邻节点,访问完该节点的所有相邻节点后,以相邻节点中的第一个节点为起点,继续去访问其所有相邻节点,反复持续该过程直到图中所有节点均被访问过退出。这样一来,图的访问顺序就是一个横向的访问顺序。

和广度优先搜索一样,我们将要访问的节点称为头节点,相邻节点称为表节点;头节点中存储数据和第一个表节点,表节点中存储头节点的下标和头节点的下一个相邻节点;头节点使用顺序(链表)存储,表节点使用链表存储。

广度优先搜索和深度优先搜索的区别其实就是在于遍历策略的不同,广度优先搜索是访问完每一个节点,就去访问该节点的所有相邻节点;而深度优先遍历是每访问一个节点,就去访问该节点的第一个相邻节点

如下图,其广度优先搜索顺序就是 v1, v2, v3, v4, v5, v6, v7, v8,注意:广度优先搜索的顺序也不是唯一的,和深度优先搜索一样,取决于访问起点和表节点的顺序。

image-20221119211434508

实现思路

  • 访问头节点,并将该头节点标记为以访问过
  • 访问头节点的所有表节点,这里需要循环
  • 然后以第一个表节点为起点,继续以上两步操作直到访问完所有头节点,这里需要递归
  • 我们还需要使用到队列,来存储每次访问过程中所有表节点中的第一个表节点,也就是我们下一次访问的起点

代码实现

定义头节点和表节点

//头节点
public class HNode<T> {

    public T data; //数据域
    public boolean isVisit; //标识该头节点是否已经被访问过
    public TNode firstArc; //指针域,指向第一个表节点

    public HNode(T data) {
        this.data = data;
    }

    public HNode() {
    }

    @Override
    public String toString() {
        return "HNode{" +
                "data=" + data +
                ", isVisit=" + isVisit +
                ", firstArc=" + firstArc +
                '}';
    }
}

//表节点
class TNode {

    public int hNodeIndex;//存储头节点下标
    public TNode nextArc; //指针域,指向下一个相邻的表节点

    public TNode(int hNodeIndex) {
        this.hNodeIndex = hNodeIndex;
    }

}

定义一个 Graph 类,一个Graph类就表示一个图

public class Graph {

    private HNode[] vertices; //存储头节点

    //用于广度优先搜索
    private LinkedQueue<HNode> queue = new LinkedQueue();

    public Graph(HNode[] vertices) {
        this.vertices = vertices;
    }

    //构建图
    public void build(Object data) {

    }

    //广度优先搜索
    //index为遍历起点
    public void wfs(int index) {
        //访问头节点
        System.out.println(vertices[index].data);
        //设置当前头节点为已访问
        vertices[index].isVisit = true;
        //当前头节点入队列
        queue.enQueue(vertices[index]);
        //不断从队列中取出首节点,直到队列为空
        while (!queue.isEmpty()) {
            //开始遍历
            //获取第一个表节点
            TNode tNode = queue.outQueue().getData().firstArc;
            //只要当前表节点不为空,就说明该头节点的表节点没有遍历结束,我们就一直循环下去
            while (tNode != null) {
                //只要当前表节点对应的头节点没有被访问过,就进行访问
                if (!(vertices[tNode.hNodeIndex].isVisit)) {
                    System.out.println(vertices[tNode.hNodeIndex].data);
                    //设置当前头节点为已访问
                    vertices[tNode.hNodeIndex].isVisit = true;
                    //访问完节点后,将该节点入队列
                    queue.enQueue(vertices[tNode.hNodeIndex]);
                }
                //hNode后移
                tNode = tNode.nextArc;
            }
        }
   	}
}

再main方法中测试

public class WFSDemo {

    public static void main(String[] args) {

        HNode[] nodes = new HNode[5];

        for (int i = 0; i < nodes.length; i++) {
            HNode<String> node = new HNode<>("张三-" + (i + 1));
            nodes[i] = node;
        }

        TNode node1 = new TNode(2);
        node1.nextArc = new TNode(3);
        nodes[0].firstArc = node1;
        TNode node2 = new TNode(0);
        node2.nextArc = new TNode(4);
        nodes[1].firstArc = node2;
        TNode node3 = new TNode(1);
        node3.nextArc = new TNode(3);
        nodes[2].firstArc = node3;
        TNode node4 = new TNode(0);
        node4.nextArc = new TNode(1);
        nodes[3].firstArc = node4;
        TNode node5 = new TNode(3);
        node5.nextArc = new TNode(2);
        nodes[4].firstArc = node5;

        for (HNode node : nodes) {
            System.out.println(node);
        }

        Graph graph = new Graph(nodes);

        System.out.println("--------------广度优先搜索--------------");
        graph.wfs(0);
        
    }

}

测试结果

image-20221120211558568

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小嵌_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值