BFS算法实现地图路线查询(JAVA编写附带界面)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

该代码为笔者算法课堂作业,要求实现BFS算法,并在UI界面上显示出来,笔者基于JAVA语言完成该任务,初始界面截图:

请添加图片描述
选择好两个地点后点击查询按钮截图:
请添加图片描述


实现思路及代码

1.绘制地图

先绘制一个简略版地图,笔者使用的是powerpoint,上面有一些好用的绘制工具,能满足简单的地图绘制要求

2.BFS算法部分

BFS全称为广度优先算法,CSDN上许多文章都有讲,这里不作赘述,首先在控制台能实现该算法,因为地点数目不大这里笔者使用的是邻接矩阵,如果地点数目庞大需要使用邻接链表
代码如下:

import java.util.*;

public class BFS {

    public static int[] edgeTo = new int[13];
    public static boolean[] marked = new boolean[13];
    public static int s;

    public static void bfsMethod(int[][] adjMatrix, int sourceNode){
        //利用队列
        Queue<Integer> queue = new LinkedList<Integer>();
        int numOfNodes = adjMatrix[sourceNode].length;
        int[] isVisited = new int[numOfNodes];//没访问过的初始化为0
        s = sourceNode;
        isVisited[sourceNode] = 1;
        queue.add(sourceNode);
        int i = 0;
        int element = 0;
        marked[i] = true;
        while(!queue.isEmpty()){
            element = queue.remove();
            System.out.print(element+" ");
            i = 0;
            while(i < numOfNodes){
                if(adjMatrix[element][i] == 1 && isVisited[i] == 0){
                    queue.add(i);//按照最先遍历到的1进入队列为原则, 如果有好几个1在一行,也就是一个顶点与多个顶点相连
                    isVisited[i] = 1;
                    edgeTo[i] = element;    //如果想要到i节点可以走element节点
                    marked[i] = true;
                }
                i++;
            }
        }
    }
    public static boolean hasPath(int v){
        return marked[v];
    }

    public static Iterable<Integer> pathTo(int v){
        if(!hasPath(v))
            return null;
        Stack<Integer> path = new Stack<Integer>();
        for(int x=v; x!=s; x=edgeTo[x])     //不停地往上一个节点找
            path.push(x);
        path.push(s);
        return path;
    }
/* 
    public static void main(String[] args){
                            //0 1 2 3 4 5 6 7 8 9 10 11 12
        int[][] adjMatrix = {{0,1,0,1,0,0,0,0,0,0,0,0,0},   //0 
                             {1,0,0,0,1,1,0,0,0,0,0,0,0},   //1
                             {0,0,0,1,0,0,1,1,0,0,0,0,0},   //2
                             {1,0,1,0,0,0,0,1,0,0,0,0,0},   //3
                             {0,1,0,0,0,1,0,0,0,0,0,0,0},   //4
                             {0,1,0,0,1,0,1,0,1,0,0,0,0},   //5
                             {0,0,1,0,0,1,0,0,1,0,0,0,0},   //6
                             {0,0,1,1,0,0,0,0,0,1,1,0,0},   //7 
                             {0,0,0,0,0,1,1,0,0,1,0,1,0},   //8
                             {0,0,0,0,0,0,0,1,1,0,0,1,1},   //9
                             {0,0,0,0,0,0,0,1,0,0,0,0,1},   //10
                             {0,0,0,0,0,0,0,0,1,1,0,0,1},   //11
                             {0,0,0,0,0,0,0,0,0,1,1,1,0}};  //12
        System.out.println("图的广度优先遍历(BFS)结果为(从0开始编号):");
        bfsMethod(adjMatrix, 0);
        System.out.println();
        Iterable<Integer> temp = pathTo(4);
        Iterator<Integer> iterator = temp.iterator();
        LinkedList<Integer> test = new LinkedList<>();
        while (iterator.hasNext()) {
            int x = iterator.next();
            test.add(x);
        }
        System.out.println(pathTo(4));
    }
*/
}

Tools类的作用是提供一个“路径”链表存放信息以便于UI界面的绘制,并在该类中调用BFS搜索算法
代码如下:

import java.util.Iterator;
import java.util.LinkedList;

public class Tools {
                                       //0 1 2 3 4 5 6 7 8 9 10 11 12
    public static  int[][] adjMatrix = {{0,1,0,1,0,0,0,0,0,0,0,0,0},   //0 
                                        {1,0,0,0,1,1,0,0,0,0,0,0,0},   //1
                                        {0,0,0,1,0,0,1,1,0,0,0,0,0},   //2
                                        {1,0,1,0,0,0,0,1,0,0,0,0,0},   //3
                                        {0,1,0,0,0,1,0,0,0,0,0,0,0},   //4
                                        {0,1,0,0,1,0,1,0,1,0,0,0,0},   //5
                                        {0,0,1,0,0,1,0,0,1,0,0,0,0},   //6
                                        {0,0,1,1,0,0,0,0,0,1,1,0,0},   //7 
                                        {0,0,0,0,0,1,1,0,0,1,0,1,0},   //8
                                        {0,0,0,0,0,0,0,1,1,0,0,1,1},   //9
                                        {0,0,0,0,0,0,0,1,0,0,0,0,1},   //10
                                        {0,0,0,0,0,0,0,0,1,1,0,0,1},   //11
                                        {0,0,0,0,0,0,0,0,0,1,1,1,0}};  //12
    //全局链表用于存放路径信息
    public static LinkedList<Integer> list = new LinkedList<>();

    public static void search(int source, int target){
        BFS.bfsMethod(adjMatrix, source);
        Iterable<Integer> temp = BFS.pathTo(target);
        Iterator<Integer> iterator = temp.iterator();
        while (iterator.hasNext()) {
            int x = iterator.next();
            list.add(x);
        }
        System.out.println(BFS.pathTo(target));
    }
}

3.UI界面

笔者使用的是Eclipse中的windowbuilder插件,为控件加上需要的监听器,其中refresh类是为了刷新路径的显示,图片中地点的坐标需要调试
代码如下:

import javax.swing.DefaultComboBoxModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class GUI {
	
    public JFrame jf;
    public static JPanel drawJP;
	public JPanel toolJP;
    public JLabel jlpic = new JLabel();
    JPanel jPanel = new JPanel();
    JFrame jframe = new JFrame();
	static JComboBox comboBoxFrom = new JComboBox();
	static JComboBox comboBoxTo = new JComboBox();

    public void showUI() {
    	// new一个JFrame窗体
        jf = new JFrame("路线查询");
        // 设置窗体大小
        jf.setSize(600,600);
        // 设置窗体的布局为边界布局,分为东南西北中五个方位,可以将组件添加到指定的地方
        jf.setLayout(new BorderLayout());
        // 设置窗体居中显示
        jf.setLocationRelativeTo(null);
        // 给窗体设置退出按钮 关掉即退出程序
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // new一个区域JPanel
        drawJP = new JPanel();
		
        ImageIcon icon = new ImageIcon(getClass().getResource("MAP.jpg"));
        jlpic.setIcon(icon);
        drawJP.add(jlpic);
        jf.add(drawJP);
        jf.pack();
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // 定制操作模块
        toolJP = new JPanel();
        toolJP.setBackground(Color.WHITE);
        // 除了窗体使用setSize(),其他组件的大小设置都需要使用setPreferredSize()方法
        toolJP.setPreferredSize(new Dimension(0,70));
        jf.add(toolJP, BorderLayout.SOUTH);

		comboBoxTo.setModel(new DefaultComboBoxModel(new String[] {"西门","校医院","食堂",
		"西苑","美术楼","体育馆","图书馆","教学楼","运动场","实验楼","南门","东苑","音乐楼"}));
		comboBoxTo.setPreferredSize(new Dimension(80,30));
		toolJP.add(comboBoxTo);
		comboBoxFrom.setModel(new DefaultComboBoxModel(new String[] {"西门","校医院","食堂",
		"西苑","美术楼","体育馆","图书馆","教学楼","运动场","实验楼","南门","东苑","音乐楼"}));
		comboBoxFrom.setPreferredSize(new Dimension(80,30));
		toolJP.add(comboBoxFrom);
		//查询按钮
		JButton jbt = new JButton("查询");
		jbt.setPreferredSize(new Dimension(80,30));
		toolJP.add(jbt);
		//按钮监听事件
		btnListener check = new btnListener();
		jbt.addActionListener(check);

		//清除按钮
		JButton jbtClear = new JButton("清除");
		jbtClear.setPreferredSize(new Dimension(80,30));
		toolJP.add(jbtClear);
		//按钮监听事件
		btnListenerClear clear = new btnListenerClear();
		jbtClear.addActionListener(clear);		
		// 设置窗体为可见,不然看不见窗体以及窗体中的内容
        jf.setVisible(true);
    }
}

//查询事件
class btnListener implements ActionListener{
	@Override
	public void actionPerformed(ActionEvent e) {
		System.out.println("查询事件");
		refresh.draw();
	}
}

//清除事件
class btnListenerClear implements ActionListener{
	@Override
	public void actionPerformed(ActionEvent e) {
		System.out.println("清除事件");
		refresh.clear();
	}
}

//刷新界面
class refresh extends GUI{
	private static int[][] location = {{0,130,220},
										{1,400,100},
										{2,380,250}, 
										{3,240,400}, 
										{4,630,50},
										{5,630,150}, 
										{6,630,275}, 
										{7,450,385},
										{8,890,205}, 
										{9,870,385}, 
										{10,625,525}, 
										{11,1135,350}, 
										{12,870,470}};

	public static void draw(){
		Tools.search(comboBoxTo.getSelectedIndex(),comboBoxFrom.getSelectedIndex());
		drawRoad();
	}
	
	public static void clear(){
		drawJP.repaint();
		Tools.list.clear();
	}

	public static void drawRoad(){
		Graphics g =  drawJP.getGraphics();
		g.setColor(Color.red);
		int head = Tools.list.poll();
		int len = Tools.list.size();
		for(int i=0; i<len; i++){
			int tail = Tools.list.peek();
			g.drawLine(location[head][1],location[head][2], location[tail][1],location[tail][2]);
			head = Tools.list.poll();
		}
	}
}

4.main函数

代码如下:

/*
 * 广度优先搜索算法BFS
 */
public class App {
    public static void main(String[] args) throws Exception {
        GUI ui = new GUI();
        ui.showUI();
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值