图 遍历 java_java图形化实现图的遍历(DFS,BFS)

a4c26d1e5885305701be709a3d33442f.png

LinkedList的应用啊!!!!!只能说自己太大意了。。。

功能:可以双击一个节点从任意节点遍历,默认从头节点开始遍历,两种遍历方式,可以拖拽节点任意

移动节点的位置。

没有实现:删除功能,鼠标也可以实现,但是加入键盘监听想让D和delete键来删除,但是加完节点和关系

以后键盘监听就不好使了!!!求指导!!!!!

代码如下:

Graphic类:

import java.awt.BorderLayout;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.awt.event.ItemEvent;

import java.awt.event.ItemListener;

import javax.swing.JButton;

import javax.swing.JComboBox;

import javax.swing.JFrame;

import javax.swing.JLabel;

import javax.swing.JPanel;

public class Graphic extends JFrame implements ActionListener,

ItemListener {

MyPanel mp = null;

JPanel jp = null;

JButton add = null;

JButton add1 = null;

JButton tra = null;

JButton cancel = null;

JLabel jl = null;

JComboBox jList = null;// 下拉列表

String[] travel = { "DFS", "BFS" };

JLabel jlb = null;// 装饰标签

public Graphic() {

mp = new MyPanel();

jl = new JLabel("遍历方式");

jList = new

JComboBox(travel);

jList.addItemListener(this);

add = new

JButton("加节点");

add.addActionListener(this);

add.setActionCommand("a");

add1 = new

JButton("加关系");

add1.addActionListener(this);

add1.setActionCommand("aa");

jlb = new

JLabel(" ");// 让布局好看点!!

tra = new

JButton("确认遍历");

tra.addActionListener(this);

tra.setActionCommand("b");

cancel = new

JButton("取消");

cancel.addActionListener(this);

cancel.setActionCommand("c");

jp = new JPanel();

jp.add(add);

jp.add(add1);

jp.add(cancel);

jp.add(jlb);

jp.add(jl);

jp.add(jList);

jp.add(tra);

mp.addMouseListener(mp);

mp.addMouseMotionListener(mp);

mp.addKeyListener(mp);

jp.addKeyListener(mp);

this.setFocusable(true);

this.addKeyListener(mp);

this.add(mp);

this.addKeyListener(mp);

this.add(jp,

BorderLayout.SOUTH);

this.setSize(600,

500);

this.setLocation(350,

150);

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

this.setVisible(true);

}

public static void main(String[] args)

{

new Graphic();

}

@Override

public void actionPerformed(ActionEvent e)

{

if

(e.getActionCommand().equals("a")) {// 加节点

mp.isTravel =

false;

mp.isAdd1 =

false;

mp.isAdd =

true;

} else if

(e.getActionCommand().equals("aa")) {// 加关系

mp.isTravel =

false;

mp.isAdd =

false;

mp.isAdd1 =

true;

} else if

(e.getActionCommand().equals("c")) {// 取消

mp.isTravel =

true;

mp.isAdd =

false;

mp.isAdd1 =

false;

} else if

(e.getActionCommand().equals("b")) {// 确认遍历

mp.isTravel =

true;

String s =

jList.getSelectedItem().toString();// 得到选项

if (s ==

"DFS") {

mp.Dfs();

} else if (s

== "BFS") {

mp.Bfs();

}

for (int i =

0; i < mp.nodes.size(); i++) {//

遍历后把正在访问均重新变为空

Node

node = mp.nodes.get(i);

node.isVisit

= false;

}

}

}

@Override

public void itemStateChanged(ItemEvent e) {//

监听遍历状态改变时候,将正在遍历设置回假

for (int i = 0; i

< mp.nodes.size(); i++) {

Node node =

mp.nodes.get(i);

node.isVisit

= false;

}

mp.repaint();

}

}

MyPanel类:

import java.awt.*;

import javax.swing.*;

import java.awt.event.*;

import javax.swing.event.*;

import javax.tools.JavaCompiler;

import java.util.*;

class MyPanel extends JPanel implements MouseListener,

MouseMotionListener,

KeyListener {

int x, y;// 节点左上角坐标

int x1, y1;// 画直线时候另一个点

int width = 36;// 节点宽高

int height = 36;

int total = 1000;// 总的节点个数

int X[][] = new int[total][total];//

邻接矩阵,判断x方向是否相连

int Y[][] = new int[total][total];//

邻接矩阵,判断y方向是否相连

boolean visit[][] = new boolean[total][total];//

判断结点是否访问过

boolean isOther = false;//

画关系时候判断是否找另一个点

boolean isTravel = false;// 判断是否正在遍历

Vector

nodes = new Vector();//

节点集合

Vector

lines = new Vector();//

直线集合

LinkedList

lists = new LinkedList();//

bfs时候用

Node start = new Node(0, 0);// 遍历初始节点

boolean isAdd = false;// 判断是否为加节点

boolean isAdd1 = false;// 判断是否为加关系

boolean isFirst = true;// 拖拽时候用

boolean canDelete = false;// 双击才可删除

int xx, yy, ii;// 拖拽时候用

Vector

choose = new Vector();//

拖拽时候用,用来把所有与拖拽节点有关系的直线放进来

public MyPanel() {// 初始化

for (int i = 0; i

< total; i++) {

for (int j =

0; j < total; j++) {

X[i][j]

= 0;

Y[i][j]

= 0;

visit[i][j]

= false;

}

}

}

public void paint(Graphics g) {

super.paint(g);

g.setColor(Color.WHITE);

g.fillRect(0, 0, 600,

450);

for (int i = 0; i

< nodes.size(); i++) {// 画节点

Node node =

nodes.get(i);

this.draw(g,

node.x, node.y);

if

(node.isVisit) {// 如果节点正在访问,则图上黄色

g.setColor(Color.YELLOW);

g.fill3DRect(node.x,

node.y, width, height, false);

//

System.out.println("!!!!!!");

//

node.isVisit = false;

}

}

for (int i = 0; i

< lines.size(); i++) {// 画直线

LineNode line

= lines.get(i);

this.draw1(g,

line.x1, line.y1, line.x, line.y);

}

if (isAdd) { //

如果是加节点则不断绘制矩形

this.draw(g,

x, y);

}

if (isAdd1) {

if (isOther)

{// 如果是加关系,则当绘制直线第二个时候不断绘制这条直线

this.draw1(g,

x1, y1, x, y);

}

}

}

public void draw(Graphics g, int x, int y)

{// 画节点

g.setColor(Color.BLACK);

g.draw3DRect(x, y, width,

height, false);

}

public void draw1(Graphics g, int x1, int

y1, int x, int y) {// 画关系

g.setColor(Color.RED);

g.drawLine(x1, y1, x, y);

}

@Override

public void mouseClicked(MouseEvent e) {//

监听鼠标单击事件

// TODO Auto-generated method

stub

if (isAdd) { // 如果加节点

Node node =

new Node(e.getX(), e.getY());

nodes.add(node);

start =

nodes.get(0);// 初始节点默认赋值为第一个节点

} else if (isAdd1) {//

加关系

if (isOther

== false) {// 绘制直线第一个点的话

x1

= e.getX();

y1

= e.getY();

for

(int i = 0; i < nodes.size(); i++) {

Node

node = nodes.get(i);

if

((x1 >= node.x && x1

<= node.x + width)// 找到在哪个节点里

&&

(y1 >= node.y && y1

<= node.y + height)) {

x1

= node.x + width / 2;// 将关系直线的两个端点均赋值为节点的中心

y1

= node.y + height / 2;

break;

}

}

isOther

= true;

} else {//

绘制直线第二个点

x

= e.getX();

y

= e.getY();

for

(int i = 0; i < nodes.size(); i++) {

Node

node = nodes.get(i);

if

((x >= node.x && x

<= node.x + width)// 找到在哪个节点里

&&

(y >= node.y && y

<= node.y + height)) {

x

= node.x + width / 2;

y

= node.y + height / 2;

break;

}

}

LineNode

line = new LineNode(x1, y1, x, y);// 新建一条直线,并加入到直线集合中

lines.add(line);

X[x][x1]

= 1; // 用于表示两个节点之间有连接,用于后面遍历

X[x1][x]

= 1;

Y[y][y1]

= 1;

Y[y1][y]

= 1;

isOther

= false;

}

}

if (e.getClickCount() ==

2) {// 双击将该节点颜色变为黄色,可以从当前节点遍历

x =

e.getX();

y =

e.getY();

for (int i =

0; i < nodes.size(); i++) {

Node

node = nodes.get(i);

node.isVisit

= false;

if

((x >= node.x && x

<= node.x + width)// 找到在哪个节点里

&&

(y >= node.y && y

<= node.y + height)) {

node.isVisit

= true;

Graphics

g = this.getGraphics();// 这样得到画笔

g.setColor(Color.YELLOW);

g.fill3DRect(node.x,

node.y, width, height, false);

start

= node;// 将初始节点赋值为当前

break;

}

}

this.repaint();

}

}

@Override

public void mouseEntered(MouseEvent e) {

}

@Override

public void mouseExited(MouseEvent e) {

// TODO Auto-generated method

stub

}

@Override

public void mousePressed(MouseEvent e) {

// TODO Auto-generated method

stub

}

@Override

public void mouseReleased(MouseEvent e) {

// TODO Auto-generated method

stub

this.isFirst = true;//

设置回真

}

@Override

public void mouseDragged(MouseEvent e) {//

监听拖拽事件

// TODO Auto-generated method

stub

x = e.getX();

y = e.getY();

if (this.isFirst) {//

设置这个变量目的是完成一次整个拖拽过程只判断一次在哪个节点里

for (ii = 0;

ii < nodes.size(); ii++) {

Node

node = nodes.get(ii);

if

((x >= node.x && x

<= node.x + width)// 找到在哪个节点里

&&

(y >= node.y && y

<= node.y + height)) {

xx

= x - node.x;// 把当前间距分别算出来

yy

= y - node.y;

choose.clear();//

每一次判断节点的时候要新清空

for

(int jj = 0; jj < lines.size(); jj++) {

LineNode

l = lines.get(jj);

if

((node.x + width / 2) == l.x1

&&

(node.y + height / 2) == l.y1) {

Choose

c = new Choose(jj, false);// 如果该点是直线第一个定的点即为x1,y1,则为假

choose.add(c);

int

x4 = l.x;

int

y4 = l.y;

int

x5 = l.x1;

int

y5 = l.y1;

X[x4][x5]

= 0; // 重新刷新连接关系

X[x5][x4]

= 0;

Y[y4][y5]

= 0;

Y[y5][y4]

= 0;

}

if

((node.x + width / 2) == l.x

&&

(node.y + height / 2) == l.y) {// 如果该点是直线,第二个点

Choose

c = new Choose(jj, true);

choose.add(c);

int

x4 = l.x;

int

y4 = l.y;

int

x5 = l.x1;

int

y5 = l.y1;

X[x4][x5]

= 0; // 重新刷新连接关系

X[x5][x4]

= 0;

Y[y4][y5]

= 0;

Y[y5][y4]

= 0;

}

}

this.isFirst

= false;// 只判断一次在哪个节点里,知道松开以后再重新判断

break;

}

}

}

if (ii != nodes.size())

{// 拖动点再节点里才会考虑

nodes.get(ii).x

= x - xx;// 不断将node的坐标值重复成拖拽过后的坐标值

nodes.get(ii).y

= y - yy;

for (int

i = 0; i < choose.size(); i++) {//

将与节点有关系的直线也不断赋值,直线会跟着走

Choose

c = choose.get(i);

if

(c.isX) {

lines.get(c.index).x

= nodes.get(ii).x + width / 2;

lines.get(c.index).y

= nodes.get(ii).y + height / 2;

}

else {

lines.get(c.index).x1

= nodes.get(ii).x + width / 2;

lines.get(c.index).y1

= nodes.get(ii).y + height / 2;

}

int

x4 = lines.get(c.index).x;

int

y4 = lines.get(c.index).y;

int

x5 = lines.get(c.index).x1;

int

y5 = lines.get(c.index).y1;

X[x4][x5]

= 1; // 重新刷新连接关系

X[x5][x4]

= 1;

Y[y4][y5]

= 1;

Y[y5][y4]

= 1;

}

this.repaint();

}

}

@Override

public void mouseMoved(MouseEvent e) {//

监听鼠标移动事件,不断的重绘

if (this.isTravel == false)

{

x =

e.getX();

y =

e.getY();

this.repaint();

}

}

public void delete() {//

删除函数,目前监听进不来!!!

for (ii = 0; ii

< nodes.size(); ii++) {

Node node =

nodes.get(ii);

if ((x

>= node.x && x

<= node.x + width)// 找到在哪个节点里

&&

(y >= node.y && y

<= node.y + height)) {

for

(int jj = 0; jj < lines.size(); jj++) {

LineNode

l = lines.get(jj);

if

((node.x + width / 2) == l.x1

&&

(node.y + height / 2) == l.y1) {

lines.remove(l);

}

if

((node.x + width / 2) == l.x

&&

(node.y + height / 2) == l.y) {// 如果该点是直线,第二个点

lines.remove(l);

}

}

nodes.remove(node);

break;

}

}

this.repaint();

}

public void dfs(Node node) {// 深度优先搜索

int x2 = node.x + width / 2;//

都是判断中间点

int y2 = node.y + height /

2;

visit[x2][y2] = true;

node.isVisit = true;//

将正在访问的点变为黄色

this.repaint();//

不会起作用,会循环完一次重绘,因此要强制更新

this.update(this.getGraphics());//

循环里要强制更新。。画笔是this.getGraphics()得到

try { // 睡眠1.5秒

Thread.currentThread().sleep(1500);

} catch (Exception e) {

e.printStackTrace();

}

// System.out.println(x2 +

" " + y2);

for (int j = 0; j

< nodes.size(); j++) {

Node node1 =

nodes.get(j);

int x3 =

node1.x + width / 2;

int y3 =

node1.y + height / 2;

if

((X[x2][x3] != 0) && (Y[y2][y3] !=

0 && !visit[x3][y3])) {

dfs(node1);

}

}

}

public void Dfs() {

for (int i = 0; i

< total; i++) {

for (int j =

0; j < total; j++) {

visit[i][j]

= false;

}

}

dfs(start);//

从当前选中节点开始遍历

for (int i = 0; i

< nodes.size(); i++) {

Node node =

nodes.get(i);

if (node !=

start) {// 选中节点就不用遍历了

if

(!visit[node.x + width / 2][node.y + height / 2]) {

dfs(node);

}

}

}

}

public void bfs(Node node) {// 广度优先搜索

int x2 = node.x + width /

2;

int y2 = node.y + height /

2;

visit[x2][y2] = true;

node.isVisit = true;

lists.push(node);

this.repaint();

this.update(this.getGraphics());//

循环里要强制更新。。画笔是this.getGraphics()得到

try {

Thread.currentThread().sleep(1500);

} catch (Exception e) {

e.printStackTrace();

}

while (lists.size()

> 0) {

Node node1 =

lists.peekFirst();

lists.poll();//

这句才是删除队首元素

int x3 =

node1.x + width / 2;

int y3 =

node1.y + height / 2;

for (int

k = 0; k < nodes.size(); k++) {

Node

node2 = nodes.get(k);

int

x4 = node2.x + width / 2;

int

y4 = node2.y + height / 2;

if

((X[x3][x4] != 0) && (Y[y3][y4] !=

0 && !visit[x4][y4])) {

node2.isVisit

= true;

visit[x4][y4]

= true;

lists.addLast(node2);//

这才是放到队尾

//

lists.push(node2);//LinkedList的push函数默认放在队首!!!!!

this.repaint();

this.update(this.getGraphics());//

循环里要强制更新。。画笔是this.getGraphics()得到

try

{

Thread.currentThread().sleep(1500);

}

catch (Exception e) {

e.printStackTrace();

}

}

}

}

this.repaint();

}

public void Bfs() {

lists.clear();

for (int i = 0; i

< total; i++) {

for (int j =

0; j < total; j++) {

visit[i][j]

= false;

}

}

bfs(start);

}

@Override

public void keyPressed(KeyEvent ee) {//

加完节点就会失去焦点!!!键盘不监听!!!

int temp =

ee.getKeyCode();

if (temp == KeyEvent.VK_D ||

temp == KeyEvent.VK_DELETE) {

this.delete();

}

}

@Override

public void keyReleased(KeyEvent e) {

// TODO Auto-generated method

stub

}

@Override

public void keyTyped(KeyEvent e) {

// TODO Auto-generated method

stub

}

}

Node类:

import javax.swing.*;

public class Node {

int x, y;// 节点左上角坐标

String s = "";// 节点信息

boolean isVisit = false;

Node(int x, int y) {

this.x = x;

this.y = y;

}

}

class LineNode {// 直线节点

int x, y, x1, y1;

LineNode(int x, int y, int x1, int y1)

{

this.x = x;

this.y = y;

this.x1 = x1;

this.y1 = y1;

}

}

class Choose {// 拖拽时候用,用来把一个节点内所有关联直线放进来

int index;

boolean isX;

public Choose(int index, boolean isX)

{

this.index = index;

this.isX = isX;

}

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值