1. 效果
(清除原有内容时会有闪屏 后面看看怎么搞)
1. gif
(录到结束的)
2. 开始
3. 结束
2. 代码
2.1 定制数组 (会触发数组元素变更的事件)
继承自ArrayList 重载 set 方法 当调用 set 函数时 释放 set事件
public class MyArray<T> extends ArrayList<T> {
private List<OnChange<T>> listeners;
public MyArray (List<OnChange<T>> listeners, List<T> ori) {
super(ori);
this.listeners = listeners;
doNotify(l -> l.onInit(ori));
}
@Override
public T set(int i, T ele) {
T old = super.set(i, ele);
doNotify(l -> l.onSet(i, old, ele));
return old;
}
private void doNotify(Consumer<OnChange<T>> consumer) {
listeners.forEach(consumer);
}
public static interface OnChange<T> {
void onSet(int i, T old, T news);
void onInit(List<T> ele);
}
}
2. 绘图程序
实现上述数组的 onChange 接口 监听元素变更 以重新绘制
public class VisualArray extends JPanel implements MyArray.OnChange<Integer> {
private List<Integer> data;
private volatile Graphics graphics;
private int rectWidth;
private int totalHeight = 800;
private int totalWidth = 1006;
public VisualArray() {
// 窗口初始化
JFrame jFrame = new JFrame();
jFrame.setContentPane(this);
jFrame.setTitle("可视化数组");
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.setSize(totalWidth, this.totalHeight);
jFrame.setVisible(true);
}
@Override
public void paint(Graphics graphics) {
super.paint(graphics);
this.graphics = graphics;
this.drawAll();
}
@Override
public void onSet(int i, Integer old, Integer news) {
this.data.set(i , news);
this.paint(this.graphics);
// 等待一段时间 方便观察效果
try {
Thread.sleep(200);
} catch (Exception e) {
e.printStackTrace();
}
}
private double rectHeightRate;
private final int xStart = 73;
@Override
public void onInit(List<Integer> ele) {
this.data = new ArrayList<>(ele);
int size = this.data.size();
int leftWidth = totalWidth - (int)(this.xStart * 2.2);
this.rectWidth = leftWidth / size;
int maxVal = this.data.stream().max(Comparator.comparing(Integer::intValue)).get();
this.rectHeightRate = (this.totalHeight * 0.85) / maxVal;
this.paint(this.graphics);
}
// 绘制数组所有的元素
private void drawAll() {
graphics.clearRect(0, 0, this.totalWidth, this.totalHeight);
if (null == this.data || this.data.size() == 0) {
return;
}
BasicStroke basicStroke = new BasicStroke(10.1f,BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL);
((Graphics2D)this.graphics).setStroke(basicStroke);
int startColor = 0x00ff00;
for (int i = 0; i < this.data.size(); i++) {
this.graphics.setColor(new Color(startColor));
int height = (int) (this.data.get(i) * this.rectHeightRate);
this.graphics.fillRect(this.xStart + i * this.rectWidth, totalHeight - height, this.rectWidth, height);
startColor += 16;
}
this.updateUI();
}
}
3. 主方法
public class MainVisualSort {
private boolean needSwap(int i, int j) {
return i < j;
}
// 冒泡排序
public void bubbleSort(List<Integer> list) {
for (int i = 0; i < list.size(); i++) {
for (int j = i + 1; j < list.size(); j++) {
if (needSwap(list.get(j), list.get(i))) {
list.set(j, list.set(i, list.get(j)));
}
}
}
}
public static void main(String[] args) {
MainVisualSort mainVisualSort = new MainVisualSort();
VisualArray visualArray = new VisualArray();
// 等待 swing 初始化好
try{
Thread.sleep(200);
} catch (Exception e) {
e.printStackTrace();
}
// 随机40个元素
List<Integer> toDeal = new ArrayList<>();
for (int i = 0; i < 40; i++) {
toDeal.add(Math.abs(new Random().nextInt(71)) + 30);
}
List<Integer> list = new MyArray<>(Collections.singletonList(visualArray), toDeal);
mainVisualSort.bubbleSort(list);
}
}
如果要观察快排效果 再实现一个 main 类中再加一个 quickSort方法即可
其余不需要改动