• Java GUI : 实现排序算法的动态演示


    0.用到的jar包

    jcommon-1.0.16.jar、jfreechart-1.0.13.jar

    1.实现思路

    自定义一个类---用于存放排序算法的操作状态--SortEntity

    定义一个方法类---定义一个List<SortEntity>,存放当前排序的算法所有的时刻的状态值---SortUtils

    定义一个工具类---传入一个SortEntity,根据SortEntity构建一个JPanel

    在UI中通过线程来循环遍历List<SortEntity>,实现动画

    3.SortEntity的定义

    package com.edusys.utils;
    
    import java.util.Arrays;
    
    public class SortEntity {
        public int[] dataList=new int[20];
        public int index_i;
        public int index_j;
        public int pivot=0;
        
        public int[] getDataList() {
            return dataList;
        }
        public void setDataList(int[] dataList) {
            for(int i=0;i<dataList.length;i++){
                this.dataList[i] = dataList[i];
            }
        }
        public int getIndex_i() {
            return index_i;
        }
        public void setIndex_i(int index_i) {
            this.index_i = index_i;
        }
        public int getIndex_j() {
            return index_j;
        }
        public void setIndex_j(int index_j) {
            this.index_j = index_j;
        }
        public int getPivot() {
            return pivot;
        }
        public void setPivot(int pivot) {
            this.pivot = pivot;
        }
        
        public SortEntity() {
        }
        public SortEntity(int[] dataList, int index_i, int index_j, int pivot) {
            for(int i=0;i<dataList.length;i++){
                this.dataList[i] = dataList[i];
            }
            this.index_i = index_i;
            this.index_j = index_j;
            this.pivot = pivot;
        }
        
        @Override
        public String toString() {
            return "SortEntity [dataList=" + Arrays.toString(dataList) + ", index_i=" + index_i + ", index_j=" + index_j
                    + ", pivot=" + pivot + "]";
        }
        
    }

    PS:这里填个坑,数组赋值时不能直接赋值,必须进行拷贝

    this.dataList=dataList;
    替换为:
    for(int i=0;i<dataList.length;i++){
        this.dataList[i] = dataList[i];
    }

    否则拷贝出的只是一个长度为传入长度的有序数组:[1,2,3,4,5......]

    4.SortUtils的定义

    package com.edusys.utils;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class SortUtils {
        private static int length=20;
        private int[] dataList;
        private List<SortEntity> quickList=new ArrayList<SortEntity>();;
        private List<SortEntity> bubbleList=new ArrayList<SortEntity>();;
        private List<SortEntity> shellList=new ArrayList<SortEntity>();;
        
        public int[] getDataList() {
            return dataList;
        }
        
        public void setDataList() {
            dataList = new int[length];
            
            boolean flag=false;
            int temp;
            int index = 0;
            while(index < length){
                temp = (int)(Math.random()*length)+1;
                //Check the same element
                for(int j=0;j<index;j++){
                    if(temp == dataList[j]){
                        flag=true;
                        break;
                    }
                    else{
                        flag = false;
                    }
                }
                if(!flag ){
                    dataList[index++] = temp;
                }
            }
        }
    
        /**
         * 对初始数组进行赋值
         */
        public SortUtils(){
            setDataList();
        }
        /**
         * 得到快速排序的结果集
         * @return
         */
        public List<SortEntity> getQuickList(){
            quickSort(getDataList(),0,length-1);
            return quickList;
        }
        
        /**
         * 得到冒泡排序结果集
         * @return
         */
        public List<SortEntity> getBubbleList() {
            bubbleList.add(new SortEntity(getDataList(), 0, 1, 0));
            bubbleSort(getDataList());
            
            return bubbleList;
        }
        
        /**
         * 得到希尔排序的结果集
         * @return
         */
        public List<SortEntity> getShellList() {
            shellList.add(new SortEntity(getDataList(), 0, 1, 0));
            shellSort(getDataList());
            return shellList;
        }
        
        /**
         * 快速排序
         * @param a
         * @param left
         * @param right
         */
        public void quickSort(int[] arr,int left,int right) {
            if(left>right){
                return; 
            }
            int pivot=arr[left];
            quickList.add(new SortEntity(arr, left, right, pivot));
            
            //定义基准值为数组第一个数 
            int i=left; 
            int j=right; 
            while(i<j) {
                //从右往左找比基准值小的数 
                while(pivot<=arr[j]&&i<j){
                    j--; 
                    quickList.add(new SortEntity(arr, left, right, pivot));
                }
                //从左往右找比基准值大的数
                while(pivot>=arr[i]&&i<j){
                    i++;
                    quickList.add(new SortEntity(arr, left, right, pivot));
                }
                //如果i<j,交换它们
                if(i<j){
                    int temp=arr[i];
                    arr[i]=arr[j]; 
                    arr[j]=temp;
                    quickList.add(new SortEntity(arr, left, right, pivot));
                } 
            } 
            //把基准值放到合适的位置 
            arr[left]=arr[i];
            arr[i]=pivot;
            //对左边的子数组进行快速排序 
            quickSort(arr,left,i-1);
            //对右边的子数组进行快速排序 
            quickSort(arr,i+1,right);
        }
        /**
         * 冒泡排序
         * @param arr
         */
        public void bubbleSort(int[] arr){
            for(int i=0;i<arr.length-1;i++){//外层循环控制排序趟数
                for(int j=0;j<arr.length-1-i;j++){//内层循环控制每一趟排序多少次
                    if(arr[j]>arr[j+1]){
                        int temp=arr[j];
                        arr[j]=arr[j+1];
                        arr[j+1]=temp;
                    }
                    bubbleList.add(new SortEntity(arr, i, j, 0));
                } 
            }
        }
        /**
         * 希尔排序
         * @param arr
         */
        public void shellSort(int[] arr){
            //增量
            int incrementNum = arr.length/2;
            while(incrementNum >=1){
                for(int i=0;i<arr.length;i++){
                    //进行插入排序
                    for(int j=i;j<arr.length-incrementNum;j=j+incrementNum){
                        if(arr[j]>arr[j+incrementNum]){
                            int temple = arr[j];
                            arr[j] = arr[j+incrementNum];
                            arr[j+incrementNum] = temple;
                        }
                        shellList.add(new SortEntity(arr, i, j, 0));
                    }
                }
                //设置新的增量
                incrementNum = incrementNum/2;
            }
        }
    }

    此方法可以定义多个List<SortEntity>,实现各种不同的算法排序

    5.HistogramUtils的实现

    package com.edusys.utils;
    
    import java.awt.Font;
    
    import javax.swing.JPanel;
    
    import org.jfree.chart.ChartFactory;
    import org.jfree.chart.ChartPanel;
    import org.jfree.chart.JFreeChart;
    import org.jfree.chart.annotations.CategoryTextAnnotation;
    import org.jfree.chart.axis.CategoryAnchor;
    import org.jfree.chart.axis.CategoryAxis;
    import org.jfree.chart.axis.CategoryLabelPositions;
    import org.jfree.chart.plot.CategoryPlot;
    import org.jfree.chart.plot.PlotOrientation;
    import org.jfree.chart.renderer.category.BarRenderer;
    import org.jfree.chart.title.TextTitle;
    import org.jfree.data.category.CategoryDataset;
    import org.jfree.data.category.DefaultCategoryDataset;
    import org.jfree.ui.TextAnchor;
    
    public class HistogramUtils {
        
        private SortEntity sortEntity;
    
        public HistogramUtils(SortEntity sortEntity) {
            this.sortEntity=sortEntity;
        }
         /**
         * 创建柱状图数据集
         * @return
         */
        public CategoryDataset createDataset(){ 
            DefaultCategoryDataset dataset=new DefaultCategoryDataset();
            int[] dataList=sortEntity.getDataList();
            for(int i=0;i<dataList.length;i++){
                if(sortEntity.getIndex_i()==i){
                    dataset.setValue(sortEntity.getDataList()[i],"", sortEntity.getDataList()[i]+"  i");
                }else if(sortEntity.getIndex_j()==i){
                    dataset.setValue(sortEntity.getDataList()[i],"", sortEntity.getDataList()[i]+"  j");
                }else{
                    dataset.setValue(sortEntity.getDataList()[i],"", sortEntity.getDataList()[i]+"");
                }
            }
      
            return dataset;
        }
        /**
         * 用数据集创建一个图表
         * @param dataset
         * @return
         */
        public JFreeChart createChart(CategoryDataset dataset){ 
            JFreeChart chart=ChartFactory.createBarChart("", "","", dataset, PlotOrientation.VERTICAL, true, true, false); //创建一个JFreeChart
            chart.setTitle(new TextTitle("",new Font("宋体",Font.BOLD+Font.ITALIC,40)));//可以重新设置标题,替换“hi”标题
            CategoryPlot plot=(CategoryPlot)chart.getPlot();//获得图标中间部分,即plot
            CategoryAxis categoryAxis=plot.getDomainAxis();//获得横坐标
            categoryAxis.setLabelFont(new Font("微软雅黑",Font.BOLD,10));//设置横坐标字体
            categoryAxis.setMaximumCategoryLabelWidthRatio(2f);
            categoryAxis.setCategoryLabelPositions(CategoryLabelPositions.DOWN_90);
            return chart;
        }
        /**
         * 生成一个Jpanel
         * @return
         */
        public JPanel createPanel(){
            JFreeChart chart =createChart(createDataset());
            CategoryPlot categoryplot =(CategoryPlot)chart.getCategoryPlot();
            BarRenderer renderer = new CustomRenderer(sortEntity.getIndex_i(), sortEntity.getIndex_j());
            //在柱子上显示相应信息 
            renderer.setBaseItemLabelsVisible(true);  
            CategoryTextAnnotation a = new CategoryTextAnnotation("_________________________________________________________", "", sortEntity.getPivot());   
            a.setCategoryAnchor(CategoryAnchor.START);   
            a.setFont(new Font("SansSerif", Font.PLAIN, 12)); 
            a.setTextAnchor(TextAnchor.BOTTOM_LEFT);   
            categoryplot.addAnnotation(a);  
            categoryplot.setRenderer(renderer);
            return new ChartPanel(chart); //将chart对象放入Panel面板中去,ChartPanel类已继承Jpanel
        }
    }

    这个使用的是JFreeChart 来进行构图的,具体的百度参考,需要的jar在文章的开头处

    5.1自定义的BarRenderer

    package com.edusys.utils;
    
    import java.awt.Color;
    import java.awt.Paint;
    
    import org.jfree.chart.renderer.category.IntervalBarRenderer;
    
    public class CustomRenderer extends IntervalBarRenderer  {
        private int index_i,index_j;
        private Paint[] colors;
        
        public CustomRenderer(int index_i,int index_j) {
            this.index_i=index_i;
            this.index_j=index_j;
            colors = new Paint[3];
            colors[0]=Color.RED;
            colors[1]=Color.RED;
            colors[2]=Color.GREEN;
        }
        
        public CustomRenderer() {
            super();
        }
    
        //对i,j赋予不同于其他柱子的颜色
        public Paint getItemPaint(int i, int j) {
            if(j==index_i){
                return colors[0];
            }else if(j==index_j){
                return colors[1];
            }else {
                return colors[2];
            }
        }
    }

    这里重写BarRenderer 类是为了对每次状态中的i,j进行特殊颜色处理,并规范JFreeChart 构图中的颜色

    6.实现类

    package com.edusys.ui;
    
    import java.awt.Dimension;
    import java.awt.Font;
    import java.awt.Toolkit;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.List;
    
    import javax.swing.ButtonGroup;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JOptionPane;
    import javax.swing.JPanel;
    import javax.swing.JPasswordField;
    import javax.swing.JRadioButton;
    import javax.swing.JScrollPane;
    import javax.swing.JSlider;
    import javax.swing.JTable;
    import javax.swing.JTextArea;
    import javax.swing.JTextField;
    import javax.swing.ScrollPaneConstants;
    import javax.swing.event.ChangeEvent;
    import javax.swing.event.ChangeListener;
    
    
    import com.edusys.utils.FileUtils;
    import com.edusys.utils.HistogramUtils;
    import com.edusys.utils.SortEntity;
    import com.edusys.utils.SortUtils;
    import com.edusys.utils.TimeUtils;
    
    
    public class MainUI {
        
        private static int sort_type=0;
        private static int speed=1;
        private static int sleeptime=100;
        private static int count=0;
        private static boolean play_flag=false;
        private static boolean start_flag=false;
        private static List<SortEntity> sortList;
        
        public static void main(String[] args) {
            MainUI.animation();
        }
        /**
         * 算法动画演示
         */
        public static void animation(){
            final JFrame frame=new JFrame();
            
            frame.setSize(1000,620);
            frame.setVisible(true);
            frame.setResizable(false);
            frame.setLocation((Toolkit.getDefaultToolkit().getScreenSize().width-1000)/2,
                    (Toolkit.getDefaultToolkit().getScreenSize().height-620)/2);
            frame.setTitle("Algorithm Teaching System");
            frame.setLayout(null);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            
            sleeptime=100/speed;
            final SortUtils sortUtils=new SortUtils();
            if(sort_type==0){
                sortList=sortUtils.getQuickList();
            }else if(sort_type==1){
                sortList=sortUtils.getBubbleList();
            }else{
                sortList=sortUtils.getShellList();
            }
            int len=sortList.size();
            
            JPanel jPanel_sort=new JPanel();
            HistogramUtils histogramUtils=new HistogramUtils(sortList.get(count));
            jPanel_sort=histogramUtils.createPanel();
            frame.add(jPanel_sort);
            jPanel_sort.setBounds(0, 0, 450, 600);
            
            JLabel jLabel_title=new JLabel("Sort Algorithm");
            frame.add(jLabel_title);
            jLabel_title.setBounds(500, 20, 120, 30);
            JRadioButton jRadioButton_quick=new JRadioButton("Qucik Sort");
            frame.add(jRadioButton_quick);
            if(sort_type==0){
                jRadioButton_quick.setSelected(true);
            }
            jRadioButton_quick.setBounds(500, 50, 120, 30);
            jRadioButton_quick.addActionListener(new ActionListener() {
                
                @Override
                public void actionPerformed(ActionEvent e) {
                    sort_type=0;
                    frame.dispose();
                    MainUI.animation();
                }
            });
            JRadioButton jRadioButton_bubble=new JRadioButton("Bubble Sort");
            frame.add(jRadioButton_bubble);
            jRadioButton_bubble.setBounds(500, 80, 120, 30);
            if(sort_type==1){
                jRadioButton_bubble.setSelected(true);
            }
            jRadioButton_bubble.addActionListener(new ActionListener() {
                
                @Override
                public void actionPerformed(ActionEvent e) {
                    sort_type=1;
                    frame.dispose();
                    MainUI.animation();
                }
            });
            JRadioButton jRadioButton_shell=new JRadioButton("Shell Sort");
            frame.add(jRadioButton_shell);
            jRadioButton_shell.setBounds(500, 110, 120, 30);
            if(sort_type==2){
                jRadioButton_shell.setSelected(true);
            }
            jRadioButton_shell.addActionListener(new ActionListener() {
                
                @Override
                public void actionPerformed(ActionEvent e) {
                    sort_type=2;
                    frame.dispose();
                    MainUI.animation();
                }
            });
            ButtonGroup buttonGroup_sort=new ButtonGroup();
            buttonGroup_sort.add(jRadioButton_shell);
            buttonGroup_sort.add(jRadioButton_bubble);
            buttonGroup_sort.add(jRadioButton_quick);
            
            JLabel jLabel_speed=new JLabel("Speed");
            frame.add(jLabel_speed);
            jLabel_speed.setBounds(620, 160, 120, 30);
            
            JSlider jSlider_speed = new JSlider(1, 5, 1);
            frame.add(jSlider_speed);
            jSlider_speed.setBounds(500, 190, 300, 40);
            jSlider_speed.setMajorTickSpacing(1);
            jSlider_speed.setPaintTicks(true);
            jSlider_speed.setPaintLabels(true);
            jSlider_speed.addChangeListener(new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                    speed=jSlider_speed.getValue();
                    sleeptime=100/speed;
                }
            });
            
            JButton jButton_start=new JButton("Start");
            frame.add(jButton_start);
            jButton_start.setBounds(500, 320, 80, 30);
            jButton_start.addActionListener(new ActionListener() {
                
                @Override
                public void actionPerformed(ActionEvent e) {
                    start_flag=true;
                    new Thread(){
                        @Override
                        public void run(){
                            while (count<len&&start_flag){
                                //休眠
                                try {
                                    Thread.sleep(sleeptime);
                                } catch (InterruptedException e1) {
                                    e1.printStackTrace();
                                }
    
                                JPanel jPanel_sort=new JPanel();
                                HistogramUtils histogramUtils=new HistogramUtils(sortList.get(count));
                                jPanel_sort=histogramUtils.createPanel();
                                frame.add(jPanel_sort);
                                jPanel_sort.setBounds(0, 0, 450, 600);
                                count++;
                            }
                        }
                    }.start();
                    jButton_start.setEnabled(false);
                }
            });
            
            JButton jButton_restart=new JButton("Restart");
            frame.add(jButton_restart);
            jButton_restart.setBounds(600, 320, 80, 30);
            jButton_restart.addActionListener(new ActionListener() {
                
                @Override
                public void actionPerformed(ActionEvent e) {
                    frame.dispose();
                    MainUI.animation();
                }
            });
            
            JButton jButton_pause=new JButton("Pause");
            frame.add(jButton_pause);
            jButton_pause.setBounds(700, 320, 80, 30);
            jButton_pause.addActionListener(new ActionListener() {
                
                @Override
                public void actionPerformed(ActionEvent e) {
                    if(!play_flag){
                        start_flag=false;
                        jButton_pause.setText("Play");
                        play_flag=true;
                    }else{
                        start_flag=true;
                        jButton_pause.setText("Pause");
                        play_flag=false;
                        new Thread(){
                            @Override
                            public void run(){
                                while (count<len&&start_flag){
                                    //休眠
                                    try {
                                        Thread.sleep(sleeptime);
                                    } catch (InterruptedException e1) {
                                        e1.printStackTrace();
                                    }
    
                                    JPanel jPanel_sort=new JPanel();
                                    HistogramUtils histogramUtils=new HistogramUtils(sortList.get(count));
                                    jPanel_sort=histogramUtils.createPanel();
                                    frame.add(jPanel_sort);
                                    jPanel_sort.setBounds(0, 0, 450, 600);
                                    count++;
                                }
                            }
                        }.start();
                    }
                }
            });
            
            JButton jButton_forward=new JButton("Forward");
            frame.add(jButton_forward);
            jButton_forward.setBounds(800, 320, 80, 30);
            jButton_forward.addActionListener(new ActionListener() {
                
                @Override
                public void actionPerformed(ActionEvent e) {
                    if(count<len-1){
                        count++;
                        JPanel jPanel_sort=new JPanel();
                        HistogramUtils histogramUtils=new HistogramUtils(sortList.get(count));
                        jPanel_sort=histogramUtils.createPanel();
                        frame.add(jPanel_sort);
                        jPanel_sort.setBounds(0, 0, 450, 600);
                    }
                }
            });
            
            JButton jButton_back=new JButton("Back");
            frame.add(jButton_back);
            jButton_back.setBounds(900, 320, 80, 30);
            jButton_back.addActionListener(new ActionListener() {
                
                @Override
                public void actionPerformed(ActionEvent e) {
                    if(count>0){
                        count--;
                        JPanel jPanel_sort=new JPanel();
                        HistogramUtils histogramUtils=new HistogramUtils(sortList.get(count));
                        jPanel_sort=histogramUtils.createPanel();
                        frame.add(jPanel_sort);
                        jPanel_sort.setBounds(0, 0, 450, 600);
                    }
                }
            });
            
            JButton jButton_back2menu=new JButton("Back To Menu");
            frame.add(jButton_back2menu);
            jButton_back2menu.setBounds(700, 360, 120, 30);
            jButton_back2menu.addActionListener(new ActionListener() {
                
                @Override
                public void actionPerformed(ActionEvent e) {
                    frame.dispose();
                    MainUI.explanation();
                }
            });
            
            new Thread(){
                @Override
                public void run(){
                    while (count<len&&start_flag){
                        //休眠
                        try {
                            Thread.sleep(sleeptime);
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        }
    
                        JPanel jPanel_sort=new JPanel();
                        HistogramUtils histogramUtils=new HistogramUtils(sortList.get(count));
                        jPanel_sort=histogramUtils.createPanel();
                        frame.add(jPanel_sort);
                        jPanel_sort.setBounds(0, 0, 450, 600);
                        count++;
                    }
                }
            }.start();
        }
    }

    这里是实现类,线程上做的不是很好,因为对线程不是很了解,这里我也尝试过用while循环的,但是跳出去之后就不行了,重新打开另外的页面时,会卡死

    因此这个线程虽然写的不是很好,但是刚刚能用

    代码冗余,见谅!

    效果图如下:

  • 相关阅读:
    六、order set结构及命令详解
    五、set结构及命令详解
    四、redis的link结构及命令详解
    三、redis对字符串类型的操作
    二、redis对于key的操作命令
    一、redis的特点以及安装使用
    Mysql5.7以上版本group by报错问题
    1.4 java高并发程序设计-无锁
    sysbench工具和mysql的基准测试
    sqli-labs(29-31关)
  • 原文地址:https://www.cnblogs.com/fdzang/p/9631866.html
Copyright © 2020-2023  润新知