看的见的算法系列——插入排序
插入排序
原始数据
①选择2,比较前一个数字8,小于8,交换;
由于交换后2前面没有数字,结束,数字2有序。
②选择1,比较前一个数字8,小于8,交换;前面还有大于1的数字2,交换;
③选择7,比较前一个数字8,小于8,交换;
由于7大于2,比较停止。
以此类推最终我们会得到一个有序的数据。
为可视化服务的工具类
AlgoVisHelper
为其他的工具类提供绘制相关方法。
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.lang.InterruptedException;public class AlgoVisHelper {private AlgoVisHelper(){}//为画笔提供的颜色public static final Color Red = new Color(0xF44336);public static final Color Pink = new Color(0xE91E63);public static final Color Purple = new Color(0x9C27B0);public static final Color DeepPurple = new Color(0x673AB7);public static final Color Indigo = new Color(0x3F51B5);public static final Color Blue = new Color(0x2196F3);public static final Color LightBlue = new Color(0x03A9F4);public static final Color Cyan = new Color(0x00BCD4);public static final Color Teal = new Color(0x009688);public static final Color Green = new Color(0x4CAF50);public static final Color LightGreen = new Color(0x8BC34A);public static final Color Lime = new Color(0xCDDC39);public static final Color Yellow = new Color(0xFFEB3B);public static final Color Amber = new Color(0xFFC107);public static final Color Orange = new Color(0xFF9800);public static final Color DeepOrange = new Color(0xFF5722);public static final Color Brown = new Color(0x795548);public static final Color Grey = new Color(0x9E9E9E);public static final Color BlueGrey = new Color(0x607D8B);public static final Color Black = new Color(0x000000);public static final Color White = new Color(0xFFFFFF);//绘制圆形public static void strokeCircle(Graphics2D g, int x, int y, int r){Ellipse2D circle = new Ellipse2D.Double(x-r, y-r, 2*r, 2*r);g.draw(circle);}//填充圆形public static void fillCircle(Graphics2D g, int x, int y, int r){Ellipse2D circle = new Ellipse2D.Double(x-r, y-r, 2*r, 2*r);g.fill(circle);}//绘制矩形public static void strokeRectangle(Graphics2D g, int x, int y, int w, int h){Rectangle2D rectangle = new Rectangle2D.Double(x, y, w, h);g.draw(rectangle);}//填充矩形public static void fillRectangle(Graphics2D g, int x, int y, int w, int h){Rectangle2D rectangle = new Rectangle2D.Double(x, y, w, h);g.fill(rectangle);}//为画笔设置颜色public static void setColor(Graphics2D g, Color color){g.setColor(color);}//设置画笔的宽度public static void setStrokeWidth(Graphics2D g, int w){int strokeWidth = w;g.setStroke(new BasicStroke(strokeWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));}//绘制时的间隔,传入t进行设置public static void pause(int t) {try {Thread.sleep(t);}catch (InterruptedException e) {System.out.println("Error sleeping");}}//绘制图片public static void putImage(Graphics2D g, int x, int y, String imageURL){ImageIcon icon = new ImageIcon(imageURL);Image image = icon.getImage();g.drawImage(image, x, y, null);}//绘制文字public static void drawText(Graphics2D g, String text, int centerx, int centery){if(text == null)throw new IllegalArgumentException("Text is null in drawText function!");FontMetrics metrics = g.getFontMetrics();int w = metrics.stringWidth(text);int h = metrics.getDescent();g.drawString(text, centerx - w/2, centery + h);}
}
AlgoFrame
import java.awt.Graphics2D;
import java.awt.Graphics;
import java.awt.Dimension;
import java.awt.Color;
import java.awt.RenderingHints;
import javax.swing.*;public class AlgoFrame extends JFrame{private int canvasWidth;private int canvasHeight;public AlgoFrame(String title, int canvasWidth, int canvasHeight){super(title);this.canvasWidth = canvasWidth;this.canvasHeight = canvasHeight;AlgoCanvas canvas = new AlgoCanvas();setContentPane(canvas);pack();setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setResizable(false);setVisible(true);}public AlgoFrame(String title){this(title, 1024, 768);}public int getCanvasWidth(){return canvasWidth;}public int getCanvasHeight(){return canvasHeight;}// TODO: 设置自己的数据private Object data;public void render(Object data){this.data = data;repaint();}private class AlgoCanvas extends JPanel{public AlgoCanvas(){// 双缓存super(true);}@Overridepublic void paintComponent(Graphics g) {super.paintComponent(g);Graphics2D g2d = (Graphics2D)g;// 抗锯齿RenderingHints hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);hints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);g2d.addRenderingHints(hints);// 具体绘制// TODO: 绘制自己的数据data}@Overridepublic Dimension getPreferredSize(){return new Dimension(canvasWidth, canvasHeight);}}
}
AlgoVisualizer
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;public class AlgoVisualizer {// TODO: 创建自己的数据private Object data; // 数据private AlgoFrame frame; // 视图public AlgoVisualizer(int sceneWidth, int sceneHeight){// 初始化数据// TODO: 初始化数据// 初始化视图EventQueue.invokeLater(() -> {frame = new AlgoFrame("Welcome", sceneWidth, sceneHeight);// TODO: 根据情况决定是否加入键盘鼠标事件监听器frame.addKeyListener(new AlgoKeyListener());frame.addMouseListener(new AlgoMouseListener());new Thread(() -> {run();}).start();});}// 动画逻辑private void run(){// TODO: 编写自己的动画逻辑}// TODO: 根据情况决定是否实现键盘鼠标等交互事件监听器类private class AlgoKeyListener extends KeyAdapter{ }private class AlgoMouseListener extends MouseAdapter{ }public static void main(String[] args) {int sceneWidth = 800;int sceneHeight = 800;// TODO: 根据需要设置其他参数,初始化visualizerAlgoVisualizer visualizer = new AlgoVisualizer(sceneWidth, sceneHeight);}
}
创建带排序数据
public class InsertSortData {private int[] numbers;//带排序数据datapublic int sortedIndex = -1;//已排序的边界public int currIndex = -1;//当前比较的边界/*** @param N {numbers数组的长度}* @param randomBound {生成的随机数的上限}*/public InsertSortData(int N, int randomBound){numbers = new int[N];for(int i=0;i<N;i++)numbers[i] = (int) (Math.random()*randomBound)+1;//往numbers数组中添加随机数}public int size(){return numbers.length;}public int get(int index){if( index < 0 || index >= numbers.length)throw new IllegalArgumentException("Invalid index to access Sort Data.");return numbers[index];}public void swap(int i, int j) {if( i < 0 || i >= numbers.length || j < 0 || j >= numbers.length)throw new IllegalArgumentException("Invalid index to access Sort Data.");int t = numbers[i];numbers[i] = numbers[j];numbers[j] = t;}
}
插入排序代码
//插入排序算法代码
for( int i = 0 ; i < data.size() ; i ++ ){for(int j = i ; j > 0 && data.get(j) < data.get(j-1) ; j --){data.swap(j,j-1);//比前一个数字小,进行交换}
}
使用可视化工具类
AlgoVisualizer
// TODO: 创建自己的数据
private InsertSortData data;
private final int DELAY = 40;//设置每次绘制暂停的时间//修改构造函数相关代码
public AlgoVisualizer(int sceneWidth, int sceneHeight,int size,int randomBound){// 初始化数据// TODO: 初始化数据data = new InsertSortData(size,randomBound);//其他代码
}// 动画逻辑
private void run(){// TODO: 编写自己的动画逻辑setData(-1,-1);//还没排序之前已排序边界和当前比较位置索引都为-1//插入排序算法代码for( int i = 0 ; i < data.size() ; i ++ ){setData(i, i);for(int j = i ; j > 0 && data.get(j) < data.get(j-1) ; j --){data.swap(j,j-1);setData(i+1, j-1);}}setData(data.size(),-1);//排序之后全部都有序,当前比较位置索引都为-1
}
//使用setData设置边界,同时进行数据的绘制
private void setData(int sortedIndex,int currIndex){data.sortedIndex = sortedIndex;data.currIndex = currIndex;frame.render(data);//根据数据绘图AlgoVisHelper.pause(DELAY);
}public static void main(String[] args) {int sceneWidth = 800;int sceneHeight = 800;// TODO: 根据需要设置其他参数,初始化visualizer//设置数组数据为50,最大上限就是设置为窗口的高度AlgoVisualizer visualizer = new AlgoVisualizer(sceneWidth, sceneHeight,50,sceneHeight);
}
AlgoFrame
// TODO: 设置自己的数据
private InsertSortData data;@Override
public void paintComponent(Graphics g) {// 具体绘制// TODO: 绘制自己的数据dataint w = canvasWidth/data.size();//每个矩形的宽度for(int i=0;i<data.size();i++){if(i<=data.sortedIndex){AlgoVisHelper.setColor(g2d,AlgoVisHelper.Red);//将已排序部分绘制成红色}elseAlgoVisHelper.setColor(g2d, AlgoVisHelper.Grey);//将未排序部分绘制成灰色if( i == data.currIndex )AlgoVisHelper.setColor(g2d, AlgoVisHelper.LightBlue);//当前元素绘制成浅蓝色AlgoVisHelper.fillRectangle(g2d, i * w, canvasHeight - data.get(i), w - 1, data.get(i));}
}
可视化结果
从图中我们可以更加清晰的了解插入排序的工作过程。
进化
如果我们对近乎有序的数据使用插入排序,那么插入排序算法时间复杂度将进化至O(n)。我们对代码进行一下修改产生近乎有序的数据。
InsertSortData
public enum Type{//数据类型Default,//默认随机数据NearlyOrdered//近乎有序的数据
}
public InsertSortData(int N, int randomBound,Type type){numbers = new int[N];for(int i=0;i<N;i++)numbers[i] = (int) (Math.random()*randomBound)+1;//往numbers数组中添加随机数if(type == Type.NearlyOrdered){Arrays.sort(numbers);//首先对数据进行排序int swapTime = (int)(0.02*N);//打乱数字的个数for(int i = 0 ; i < swapTime; i ++){//随机选择数据进行交换int a = (int)(Math.random()*N);int b = (int)(Math.random()*N);swap(a, b);}}
}
AlgoVisualizer
public AlgoVisualizer(int sceneWidth, int sceneHeight,int size,int randomBound,InsertSortData.Type type){// TODO: 初始化数据data = new InsertSortData(size,randomBound,type);
}public static void main(String[] args) {// TODO: 根据需要设置其他参数,初始化visualizer//设置数组数据为50,最大上限就是设置为窗口的高度AlgoVisualizer visualizer = new AlgoVisualizer(sceneWidth, sceneHeight,50,sceneHeight,InsertSortData.Type.NearlyOrdered);//对近乎有序的数据使用插入排序
}
可视化结果
对近乎有序的数据可以看见插入排序的速度十分快。
本文代码已发布至GitHub,下载地址为:https://github.com/WingedCat/AlgoVisualizerPro/tree/master/src/InsertSortVisualizer
看的见的算法系列——插入排序相关推荐
- Swift 进阶 | 看得见的算法
GitHub Repo:coderZsq.target.swift Follow: coderZsq · GitHub Resume: coderzsq.github.io/coderZsq.we- ...
- 看得见的算法蒙特卡洛问题——使用蒙特卡洛算法求PI值
看得见的算法蒙特卡洛问题--使用蒙特卡洛算法求PI值 1.什么是蒙特卡洛问题 蒙特卡洛方法(Monte Carlo method),也称统计模拟方法,是二十世纪四十年代中期由于科学技术的发展和电子计算 ...
- 插入排序 php,常用的排序算法(二)--插入排序(PHP实现)
常用的排序算法系列 插入排序 插入排序是一种逻辑上非常好理解的排序方式,整个排序的核心就是不断在当前已经排好部分数据的数组里,找到合适的位置插入新数据.就像抓扑克牌,抓一张,然后再手里已经部分已经排好 ...
- 内部排序算法系列---快速排序
2019独角兽企业重金招聘Python工程师标准>>> 实现思路:从待排序的数据序列中任取一个数据作为分界值,所有比它小的数据元素一律放在左边,所有比它大的数据元素一律放在右边.经过 ...
- 2018看得见的未来:超融合六大趋势
"2018看得见的未来"系列报道现在继续.本期重磅推出由云报和SmartX共同策划的2018超融合发展趋势. 本系列报道将邀请内业的重量级厂商.专家.大咖,一起畅想2018年IT领 ...
- C++两个函数可以相互递归吗_[算法系列] 搞懂递归, 看这篇就够了 !! 递归设计思路 + 经典例题层层递进
[算法系列] 搞懂递归, 看这篇就够了 !! 递归设计思路 + 经典例题层层递进 从学习写代码伊始, 总有个坎不好迈过去, 那就是遇上一些有关递归的东西时, 看着简短的代码, 怎么稀里糊涂就出来了. ...
- [算法系列] 搞懂递归, 看这篇就够了 !! 递归设计思路 + 经典例题层层递进
[算法系列] 搞懂递归, 看这篇就够了 !! 递归设计思路 + 经典例题层层递进 从学习写代码伊始, 总有个坎不好迈过去, 那就是遇上一些有关递归的东西时, 看着简短的代码, 怎么稀里糊涂就出来了. ...
- 数据结构与算法系列——排序(3)_折半插入排序
1. 工作原理(定义) 二分插入排序(Binary Insertion Sort,折半插入排序 OR 拆半插入排序),采用折半查找方法. 二分查找插入排序的原理:是直接插入排序的一个变种:区别是:在有 ...
- 【算法系列 | 2】深入解析排序算法之——插入排序
序言 你只管努力,其他交给时间,时间会证明一切. 文章标记颜色说明: 黄色:重要标题 红色:用来标记结论 绿色:用来标记一级论点 蓝色:用来标记二级论点 决定开一个算法专栏,希望能帮助大家很好的了解算 ...
最新文章
- oracle 学习小结1
- wxWidgets搜索事件处理函数顺序
- arduino nano 蓝牙_用Arduino玩转掌控板(ESP32):ESP32概述与Arduino软件准备
- windows下 sbulime text 安装less2css踩的几个坑
- Html百分比设宽偏差大,absolute和relative元素 设置百分比宽高的差异
- C++ 从文件夹中读取文件
- 【新冠疫情】5G到底能为抗疫做点啥,这篇文章终于讲清楚了
- linux环型共享内存,Linux system v 共享内存
- JavaPoet 开源项目使用
- 细述 wxWindows
- 机器学习基石 作业一
- 微信支付SDK使用总结
- Xcode6 安装 IOS7.1 Simulator
- Dynamic Programming(1)
- 飞塔防火墙VOIP ALG参数导致SIP外呼无声音的坑
- 坐标西安 面试中电后端Java岗 被面试官狂问mybatis
- Win11找不到DNS地址怎么办?Win11找不到DNS无法访问网页解决方法
- 教你快速配置wordpress由http变成https访问
- 网格搜索法调参神经网络
- gohead 嵌入式服务器
热门文章
- 简单的Android程序多少钱,Android简单程序利息计算器
- [python]用爬虫下载某站小说并生成epub格式电子书(用mkepub库)
- canvas在PC端实现振幅大小可变的动态波浪图
- html图片水波浪,css 实现水波纹,波浪动画效果
- [Python图像处理] 合成微缩效果
- Oracle建表时弹出 ORA-00955: 名称已由现有对象使用
- 物料科目组设置和分配-OVK5/SM30(V_TVKM)/VKOA
- grub.cfg使用说明
- python开发“小迪安全课堂笔记”
- html国庆节代码,小程序10行代码实现微信头像挂红旗,国庆节个性化头像