可视化查找之二分查找

如果查找过程和程序执行能结合起来,那么这个过程会更加直观。

本文简单地实现了二分查找的可视化。界面很简单就包括两个部分:界面左侧是可视化查找部分,右侧是二分查找的代码。如下图所示:

[img]http://dl.iteye.com/upload/attachment/0084/4368/01c483be-9c75-3ca2-80bf-a2278b6d1fea.jpg[/img]

程序的关键点主要有两点:
1. 如何在页面上表示出查找程序的运行过程。
2. 如何将排序程序的运行过程和可视化查找结合起来,保持状态一致。

我的解决方法如下:
我采用了JList去模拟程序的执行,JList有一个setSelectedIndex的方法,能高亮显示指定的行。通过改变selectedIndex的值,能够达到模拟程序执行的效果。根据模拟程序中保存的状态值去修改可视化查找。

程序主要是随机产生10个数值,查找数字9.
[img]http://dl.iteye.com/upload/attachment/0084/4370/d1eb2bdb-7937-33b8-b18e-c512bcecfa7c.jpg[/img]

[b]可以找到的运行情况:[/b]


[img]http://dl.iteye.com/upload/attachment/0084/4372/9360f0b0-a11d-3020-bea8-e650e1fe9c50.jpg[/img]


[img]http://dl.iteye.com/upload/attachment/0084/4379/ebdf85dc-e5f6-3f68-b0f9-0afa38be6b1a.jpg[/img]


[img]http://dl.iteye.com/upload/attachment/0084/4384/6943b7b8-5ad6-3f98-b486-91a4096c98bb.jpg[/img]

[b]
找不到的运行情况:[/b]

[img]http://dl.iteye.com/upload/attachment/0084/4391/bcbb4ced-a082-3274-a145-6adb9f6e0ca2.jpg[/img]


[img]http://dl.iteye.com/upload/attachment/0084/4394/a9ed8115-779a-36eb-8843-abcbd5b1398e.jpg[/img]


[img]http://dl.iteye.com/upload/attachment/0084/4396/6b38985a-bb71-3da2-8575-89d849b7082b.jpg[/img]

程序代码如下:

package my.visualization.search.binary;

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

import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JRadioButtonMenuItem;

/**
*
* @author Eric
* @version 1.0
*
*/
public class BinarySearchVisualizationFrame extends JFrame {

private static final long serialVersionUID = -6725108659717827278L;

private Container contentPane;

/**
* 设置三个Menu Item,分别用于开始程序,调整运行的速度以及退出程序
*
*/
private JMenuItem startMI = new JMenuItem("Start");

private JMenu speedMenu = new JMenu("Speed");

private JMenuItem exitMI = new JMenuItem("Exit");

private JMenuItem aboutMI = new JMenuItem("About");

/**
* 设定5个速度级别
*/
private JRadioButtonMenuItem speedMI1 = new JRadioButtonMenuItem("Speed1",
true);

private JRadioButtonMenuItem speedMI2 = new JRadioButtonMenuItem("Speed2",
false);

private JRadioButtonMenuItem speedMI3 = new JRadioButtonMenuItem("Speed3",
false);

private JRadioButtonMenuItem speedMI4 = new JRadioButtonMenuItem("Speed4",
false);

private JRadioButtonMenuItem speedMI5 = new JRadioButtonMenuItem("Speed5",
false);

public int speedFlag = 1;

/**
* 冒泡排序可视化的Panel
*/
private BinarySearchPanel panel;

public BinarySearchVisualizationFrame(){

setTitle("可视化查找之二分查找");
setSize(700, 400);
setResizable(false);

JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);

JMenu setMenu = new JMenu("Set");
JMenu helpMenu = new JMenu("Help");

setMenu.setMnemonic('s');
setMenu.setMnemonic('H');

menuBar.add(setMenu);
menuBar.add(helpMenu);

setMenu.add(startMI);
setMenu.addSeparator();

setMenu.addSeparator();
setMenu.add(speedMenu);
setMenu.addSeparator();
setMenu.add(exitMI);

ButtonGroup group = new ButtonGroup();
group.add(speedMI1);
group.add(speedMI2);
group.add(speedMI3);
group.add(speedMI4);
group.add(speedMI5);

speedMenu.add(speedMI1);
speedMenu.add(speedMI2);
speedMenu.add(speedMI3);
speedMenu.add(speedMI4);
speedMenu.add(speedMI5);

startMI.addActionListener(new StartAction());
speedMI1.addActionListener(new SpeedAction());
speedMI2.addActionListener(new SpeedAction());
speedMI3.addActionListener(new SpeedAction());
speedMI4.addActionListener(new SpeedAction());
speedMI5.addActionListener(new SpeedAction());
exitMI.addActionListener(new ExitAction());
helpMenu.add(aboutMI);
aboutMI.addActionListener(new AboutAction());


contentPane = getContentPane();

panel = new BinarySearchPanel(this);
contentPane.add(panel);
startMI.setEnabled(true);
}

private class StartAction implements ActionListener {
public void actionPerformed(ActionEvent event) {
startMI.setEnabled(false);
panel.timer.start();
}
}

private class ExitAction implements ActionListener {
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
}

private class SpeedAction implements ActionListener {
public void actionPerformed(ActionEvent event) {
Object speed = event.getSource();
if (speed == speedMI1) {
speedFlag = 1;
} else if (speed == speedMI2) {
speedFlag = 2;
} else if (speed == speedMI3) {
speedFlag = 3;
} else if (speed == speedMI4) {
speedFlag = 4;
} else if (speed == speedMI5) {
speedFlag = 5;
}

panel.timer.setDelay(1000 - 200 * (speedFlag - 1));
}
}

private class AboutAction implements ActionListener {
public void actionPerformed(ActionEvent event) {
String string = "说明:\n1.本程序可视化二分查找的过程\n" + "2.查找的数字为9\n" + "3.low的颜色用PINK表示\n"
+ "4.high的颜色用CYAN表示\n" + "5.如果能找到,找到的数字用蓝色表示\n"+"6. 如果没有找到,颜色全部为绿色";
JOptionPane.showMessageDialog(BinarySearchVisualizationFrame.this, string);
}
}

}



package my.visualization.search.binary;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Timer;

public class BinarySearchPanel extends JPanel {

private static final long serialVersionUID = -9149581857139587792L;

private static final String[] code = {
"public int binarySearch0(int[] a, int key) {",
" int low = 0;",
" int high = a.length - 1;",
" while (low <= high) {",
" int mid = (low + high) >>> 1; ",
" int midVal = a[mid]; ",
" if (midVal < key)",
" low = mid + 1; ",
" else if (midVal > key) ",
" high = mid - 1; ",
" else ",
" return mid; ",
" }",
" return -1",
"}" };

/**
* 初始化10个数据
*/
private List<NumberRectangle> numbers = initialNumberRectangles();

private JList codeList = new JList(code);;

public TimerAction timerAction;

public Timer timer;

public BinarySearchVisualizationFrame frame;

public BinarySearchPanel(BinarySearchVisualizationFrame frame) {

timerAction = new TimerAction();
timer = new Timer(1000, timerAction);

codeList.setSelectedIndex(1);
JScrollPane scrollPane1 = new JScrollPane(codeList);
this.setLayout(new BorderLayout());
this.add(scrollPane1, BorderLayout.EAST);

this.frame = frame;
}

/**
* 判断排序是否已经结束
*/
private boolean completed = false;

public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;

drawNumberRectangles(g2);
}

private void drawNumberRectangles(Graphics2D g2) {
for (NumberRectangle rectangle : numbers) {
rectangle.draw(g2);
}
}

int low = 0;

int high = 9;

int selectedIndex = 1;

int mid = 0;

int key = 9;

int midVal = 0;

private class TimerAction implements ActionListener, Serializable {

private static final long serialVersionUID = -8671813189049345697L;

public void actionPerformed(ActionEvent event) {
if (completed) {
return;
}
/**
* 为low 和 high着色
*/
switch (selectedIndex) {
case 1:
codeList.setSelectedIndex(selectedIndex++);
break;
case 2:
codeList.setSelectedIndex(selectedIndex++);
break;
case 3:
numbers.get(low).setColor(Color.PINK);
numbers.get(high).setColor(Color.CYAN);
//while(low <high)
codeList.setSelectedIndex(selectedIndex);
if (low <= high) {
selectedIndex++;
} else {
numbers.get(low).setColor(Color.GREEN);
numbers.get(high).setColor(Color.GREEN);
selectedIndex = 13;
}
break;
case 4:
codeList.setSelectedIndex(selectedIndex++);
mid = (low + high) >>> 1;

break;
case 5:
codeList.setSelectedIndex(selectedIndex++);
midVal = numbers.get(mid).getValue();

break;

case 6 :
codeList.setSelectedIndex(selectedIndex);
if(midVal < key){
selectedIndex = 7;
}else{
selectedIndex = 8;
}
break;

case 7:
codeList.setSelectedIndex(selectedIndex);
numbers.get(low).setColor(Color.GREEN);
low = mid+1;
selectedIndex = 3;
break;
case 8:
codeList.setSelectedIndex(selectedIndex);
if(midVal > key){
selectedIndex = 9;
}else{
selectedIndex = 10;
}
break;
case 9:
codeList.setSelectedIndex(selectedIndex);
numbers.get(high).setColor(Color.GREEN);
high = mid -1;
selectedIndex = 3;
break;
case 10:
codeList.setSelectedIndex(selectedIndex++);
break;
case 11:
codeList.setSelectedIndex(selectedIndex);
//mid的方格着色
completed = true;
numbers.get(low).setColor(Color.GREEN);
numbers.get(high).setColor(Color.GREEN);
numbers.get(mid).setColor(Color.BLUE);
break;
case 13:
codeList.setSelectedIndex(selectedIndex);
completed = true;
break;
default:
break;
}

repaint();

}
}

private List<NumberRectangle> initialNumberRectangles() {
List<NumberRectangle> list = new ArrayList<NumberRectangle>();
/**
* 随机产生10个数组
*/
Random random = new Random();
int[] values = new int[10];
for (int i = 1; i <= 10; i++) {
//list.add(new NumberRectangle(i,1,random.nextInt(15)+1, Color.GREEN));
values[i - 1] = random.nextInt(15) + 1;
}
Arrays.sort(values);
for (int i = 1; i <= 10; i++) {
list.add(new NumberRectangle(i, 1, values[i - 1], Color.GREEN));
}
return list;
}

}


package my.visualization.search.binary;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;

public class NumberRectangle {

private int x;

private int y;

private int value;

private Color color;

public NumberRectangle() {
}

public NumberRectangle(int x, int y, int value, Color color) {
this.x = x;
this.y = y;
this.color = color;
this.value = value;

}

public void draw(Graphics2D g2) {
int clientX = 30 + x * 30;
int clientY = 20 + y * 10;
Rectangle2D.Double rect = new Rectangle2D.Double(clientX, clientY, 20,
value * 20);
g2.setPaint(color);
g2.fill(rect);
g2.setPaint(Color.BLACK);
g2.draw(rect);
g2.drawString(String.valueOf(value), clientX, clientY - 10);
}

/**
* @return the color
*/
public Color getColor() {
return color;
}

/**
* @param color
* the color to set
*/
public void setColor(Color color) {
this.color = color;
}

/**
* @return the x
*/
public int getX() {
return x;
}

/**
* @param x
* the x to set
*/
public void setX(int x) {
this.x = x;
}

/**
* @return the y
*/
public int getY() {
return y;
}

/**
* @param y
* the y to set
*/
public void setY(int y) {
this.y = y;
}

/**
* @return the value
*/
public int getValue() {
return value;
}

/**
* @param value
* the value to set
*/
public void setValue(int value) {
this.value = value;
}

}


package my.visualization.search.binary;

import javax.swing.JFrame;

public class SortApplication {
@SuppressWarnings("deprecation")
public static void main(String[] args) {
BinarySearchVisualizationFrame frame = new BinarySearchVisualizationFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.show();
}
}


程序代码也没有优化过,注释也基本上没有加,不好意思。大家如果有其它好的想法,请共享一下哦。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值