鱼C论坛

 找回密码
 立即注册
查看: 2293|回复: 2

[技术交流] 动手写冒泡排序图形演示程序,你也可以

[复制链接]
发表于 2016-2-27 17:01:02 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
各位朋友你们好,今天教大家写冒泡排序演示程序,使用语言为Java,不会Java也没关系,其他语言一样可以举一反三。

写演示程序有什么好处,第一是加深对编程语言的理解与应用;第二就是加深对数据结构和算法的理解,防遗忘;第三就是通过这个演示程序出一套视频,教大家。

先看程序运行最终截图:
BubbleSort.png

新建按钮可以新建要排序的元素;单步按钮可以观察排序全过程;运行按钮相当于自动点击单步按钮。

代码如下,已经有很多注释,不解释。

Bar.java
package com.algorithm.sort;

import java.awt.Color;

public class Bar {
        //方块的宽、方块与方块的距离、方块的最大宽度
        public static final int WIDTH = 20, INTERVAL = 10, MAX_HEIGHT = 200;
        //方块的高
        private int height;
        //方块的颜色
        private Color color;

        public Bar(int height, Color color) {
                this.height = height;
                this.color = color;
        }

        public int getHeight() {
                return height;
        }

        public void setHeight(int height) {
                this.height = height;
        }

        public Color getColor() {
                return color;
        }

        public void setColor(Color color) {
                this.color = color;
        }
}

BarGroup.java
package com.algorithm.sort;

import java.awt.*;

public abstract class BarGroup {
        //进行相应排序界面绘制,需要子类重写
        public abstract void draw(Graphics g);
        //单步进行相应排序,需要子类重写
        public abstract void sortStep();
        //判断是否完成排序
        public abstract boolean isDone();
        
        /**
         * 初始化方块
         * @param size 创建方块的大小
         * @param isRandom 如果为ture,表示随机生成方块;否则逆序生成方块
         * @return 生成的方块
         */
        public Bar[] initBarArray(int size, boolean isRandom) {
                Bar[] barArray = new Bar[size];
                if (isRandom) {
                        for (int i = 0; i < size; i++) {
                                int height = (int) (Math.random() * Bar.MAX_HEIGHT);
                                int r = (int) (Math.random() * 255);
                                int g = (int) (Math.random() * 255);
                                int b = (int) (Math.random() * 255);
                                barArray[i] = new Bar(height, new Color(r, g, b));
                        }
                } else {
                        for (int i = 0; i < size; i++) {
                                int height = Bar.MAX_HEIGHT - (Bar.MAX_HEIGHT * i) / size;
                                int r = (int) (Math.random() * 255);
                                int g = (int) (Math.random() * 255);
                                int b = (int) (Math.random() * 255);
                                barArray[i] = new Bar(height, new Color(r, g, b));
                        }
                }
                return barArray;
        }
        
        /**
         * 绘制一个方块
         * @param g 画笔
         * @param barArray 方块数组(根当于要排序的元素)
         * @param index 欲绘制方块的索引号
         */
        public void drawOneBar(Graphics g, Bar[] barArray, int index) {
                int height = barArray[index].getHeight();
                Color color = barArray[index].getColor();
                int x = 35 + index * (Bar.WIDTH + Bar.INTERVAL);
                int y = 250 - height;
                
                g.setColor(color);
                g.fill3DRect(x, y, Bar.WIDTH, height, true);
        }
        
        /**
         * 绘制一个箭头
         * @param g 画笔
         * @param color 箭头的颜色
         * @param str 箭头下面的文本
         * @param index 箭头上方对应的方块索引
         * @param arrowLength 箭头的长度
         */
        public void arrowText(Graphics g, Color color, String str, int index, int arrowLength) {
                int x = 35 + index * (Bar.WIDTH + Bar.INTERVAL);
                int y = 250 + 15 * arrowLength;
                g.setColor(color);
                g.drawString(str, x, y);
                g.drawLine(x + Bar.WIDTH / 2, 252, x + Bar.WIDTH / 2, y - 15);
                g.drawLine(x + Bar.WIDTH / 2, 252, x + Bar.WIDTH / 2 - 3, 257);
                g.drawLine(x + Bar.WIDTH / 2, 252, x + Bar.WIDTH / 2 + 3, 257);
        }
        
        /**
         * 交换两个方块的位置
         * @param barArray 方块数组
         * @param i 第一个要交换的方块
         * @param j 第二个要交换的方块
         */
        public void swap(Bar[] barArray, int i, int j) {
                Bar tmp = barArray[i];
                barArray[i] = barArray[j];
                barArray[j] = tmp;
        }
}

BubbleSort.java
package com.algorithm.sort;

import java.awt.*;

/**
 * 冒泡排序类
 * @author Focus100
 *
 */
public class BubbleSort extends BarGroup {
        //方块数组的大小
        private static final int ARRAY_SIZE = 10;
        //方块数组
        private Bar barArray[];
        //方块的inner、outer指针
        private int inner, outer;
        //比较次数、交换次数
        private int comps, swaps;
        //是否完成排序
        private boolean isDone;
        
        public BubbleSort(boolean isRandom) {
                //初始化方块数组,大小为10个
                barArray = initBarArray(ARRAY_SIZE, isRandom);
                //inner一开始指向第一个元素
                inner = comps = swaps = 0;
                //outer一开始指向最后一个元素
                outer = ARRAY_SIZE - 1;
                isDone = false;
        }
        
        /**
         * 完成冒泡排序界面的绘制
         */
        public void draw(Graphics g) {
                for (int i = 0; i < barArray.length; i++)
                        drawOneBar(g, barArray, i);
        g.setColor(Color.BLACK);
        g.drawString("比较次数 = " + comps, 10, 30);
        g.drawString("交换次数 = " + swaps, 10, 15);
        
        arrowText(g, Color.BLUE, "inner", inner, 3);
        arrowText(g, Color.BLUE, "inner+1", inner + 1, 3);
        arrowText(g, Color.RED, "outer", outer, 4);
        if (isDone) {
                g.drawString("状态:排序完毕", 10, 45);
                return;
        }
        if (barArray[inner].getHeight() > barArray[inner + 1].getHeight())
                g.drawString("状态:需交换", 10, 45);
        else
                g.drawString("状态:不需交换", 10, 45);
        }
        
        /**
         * 单步进行冒泡排序
         */
        public void sortStep() {
                if (isDone)
                        return;
                //比较次数加1
                comps++;
                //如果前面的元素大于后面的元素,则交换
                if (barArray[inner].getHeight() > barArray[inner + 1].getHeight()) {
                        swap(barArray, inner, inner + 1);
                        swaps++;  //交换次数加1
                }
                inner++;
                //inner最多到达outer-1的位置,outer后面的元素是排好的元素
                if (inner > outer - 1) {
                        inner = 0;
                        outer--;
                        //outer最多>=1,如果等于0表示排序完成
                        if (outer == 0)
                                isDone = true;
                }
        }
        
        /**
         * 判断是否完成排序
         */
        public boolean isDone() {
                return isDone;
        }
}

SortPanel.java
package com.algorithm.sort;

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

public class SortPanel extends JPanel implements ActionListener, Runnable {
        private JButton btnNew, btnStep, btnRun;
        private BarGroup barSort;  //排序方块类
        private final int WIDTH = 370, HEIGHT = 320;
        private boolean isRun = false, isRandom = true;  //是否用线程排序、是否随机排序

        public SortPanel() {
                //设置宽和高
                setPreferredSize(new Dimension(WIDTH, HEIGHT));
                //设置为流式布局,右对齐
                setLayout(new FlowLayout(FlowLayout.RIGHT));
                //添加三个按钮,并添加监听
                btnNew = new JButton("新建");
                btnNew.addActionListener(this);
                add(btnNew);
                btnStep = new JButton("单步");
                btnStep.addActionListener(this);
                add(btnStep);
                btnRun = new JButton("运行");
                btnRun.addActionListener(this);
                add(btnRun);
                //创建方块类
                barSort = new BubbleSort(isRandom);
                //启动线程
                new Thread(this).start();
        }

        @Override
        public void paint(Graphics g) {
                super.paint(g);
                //绘制排序界面
                barSort.draw(g);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
                switch (e.getActionCommand()) {
                case "新建":
                        //点一次随机排序,再点一次逆序排序
                        isRandom = isRandom ? false : true;
                        barSort = new BubbleSort(isRandom);
                        isRun = false;
                        break;
                case "单步":
                        barSort.sortStep();
                        isRun = false;
                        break;
                case "运行":
                        isRun = true;
                        break;
                }
                repaint();
        }
        
        /**
         * 用线程自动完成排序
         */
        @Override
        public void run() {
                while (true) {
                        if (isRun && barSort.isDone()) {
                                isRun = false;
                                return;
                        }
                        
                        if (isRun) {
                                barSort.sortStep();
                                repaint();
                                try {
                                        Thread.sleep(350);
                                } catch (InterruptedException e) {
                                        e.printStackTrace();
                                }
                        }
                }
        }
}

SoftFrame.java
package com.algorithm.sort;

import javax.swing.*;

public class SoftFrame extends JFrame {
        
        public SoftFrame() {
                this.add(new SortPanel());
                this.setTitle("冒泡排序");  //设置窗口标题
                this.setLocation(50, 100);  //设置窗口显示位置
                this.pack(); //适应子窗口大小
                this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  //设置窗口关闭方式
        }
        
        public static void main(String[] args) {
                SoftFrame frame = new SoftFrame();
                frame.setVisible(true);
        }
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-2-27 17:29:42 | 显示全部楼层
版主能对程序运行最终截图进行一下说明吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-2-27 18:19:26 | 显示全部楼层
西电图图 发表于 2016-2-27 17:29
版主能对程序运行最终截图进行一下说明吗

命令行代码:
public void BubbleSort() {
        int arr[] = {5, 4, 3, 2, 1};
        
        for (int outer = arr.length - 1; outer >= 1; outer--) {
                for (int inner = 0; inner < outer; inner++) {
                        if (arr[inner] > arr[inner + 1]) {
                                int tmp = arr[inner];
                                arr[inner] = arr[inner + 1];
                                arr[inner + 1] = tmp;
                        }
                }
        }
        
        for (int i: arr) {
                System.out.println(i);
        }
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-23 01:48

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表