插入排序

原始数据

①选择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

看的见的算法系列——插入排序相关推荐

  1. Swift 进阶 | 看得见的算法

    GitHub Repo:coderZsq.target.swift Follow: coderZsq · GitHub Resume: coderzsq.github.io/coderZsq.we- ...

  2. 看得见的算法蒙特卡洛问题——使用蒙特卡洛算法求PI值

    看得见的算法蒙特卡洛问题--使用蒙特卡洛算法求PI值 1.什么是蒙特卡洛问题 蒙特卡洛方法(Monte Carlo method),也称统计模拟方法,是二十世纪四十年代中期由于科学技术的发展和电子计算 ...

  3. 插入排序 php,常用的排序算法(二)--插入排序(PHP实现)

    常用的排序算法系列 插入排序 插入排序是一种逻辑上非常好理解的排序方式,整个排序的核心就是不断在当前已经排好部分数据的数组里,找到合适的位置插入新数据.就像抓扑克牌,抓一张,然后再手里已经部分已经排好 ...

  4. 内部排序算法系列---快速排序

    2019独角兽企业重金招聘Python工程师标准>>> 实现思路:从待排序的数据序列中任取一个数据作为分界值,所有比它小的数据元素一律放在左边,所有比它大的数据元素一律放在右边.经过 ...

  5. 2018看得见的未来:超融合六大趋势

    "2018看得见的未来"系列报道现在继续.本期重磅推出由云报和SmartX共同策划的2018超融合发展趋势. 本系列报道将邀请内业的重量级厂商.专家.大咖,一起畅想2018年IT领 ...

  6. C++两个函数可以相互递归吗_[算法系列] 搞懂递归, 看这篇就够了 !! 递归设计思路 + 经典例题层层递进

    [算法系列] 搞懂递归, 看这篇就够了 !! 递归设计思路 + 经典例题层层递进 从学习写代码伊始, 总有个坎不好迈过去, 那就是遇上一些有关递归的东西时, 看着简短的代码, 怎么稀里糊涂就出来了. ...

  7. [算法系列] 搞懂递归, 看这篇就够了 !! 递归设计思路 + 经典例题层层递进

    [算法系列] 搞懂递归, 看这篇就够了 !! 递归设计思路 + 经典例题层层递进 从学习写代码伊始, 总有个坎不好迈过去, 那就是遇上一些有关递归的东西时, 看着简短的代码, 怎么稀里糊涂就出来了. ...

  8. 数据结构与算法系列——排序(3)_折半插入排序

    1. 工作原理(定义) 二分插入排序(Binary Insertion Sort,折半插入排序 OR 拆半插入排序),采用折半查找方法. 二分查找插入排序的原理:是直接插入排序的一个变种:区别是:在有 ...

  9. 【算法系列 | 2】深入解析排序算法之——插入排序

    序言 你只管努力,其他交给时间,时间会证明一切. 文章标记颜色说明: 黄色:重要标题 红色:用来标记结论 绿色:用来标记一级论点 蓝色:用来标记二级论点 决定开一个算法专栏,希望能帮助大家很好的了解算 ...

最新文章

  1. oracle 学习小结1
  2. wxWidgets搜索事件处理函数顺序
  3. arduino nano 蓝牙_用Arduino玩转掌控板(ESP32):ESP32概述与Arduino软件准备
  4. windows下 sbulime text 安装less2css踩的几个坑
  5. Html百分比设宽偏差大,absolute和relative元素 设置百分比宽高的差异
  6. C++ 从文件夹中读取文件
  7. 【新冠疫情】5G到底能为抗疫做点啥,这篇文章终于讲清楚了
  8. linux环型共享内存,Linux system v 共享内存
  9. JavaPoet 开源项目使用
  10. 细述 wxWindows
  11. 机器学习基石 作业一
  12. 微信支付SDK使用总结
  13. Xcode6 安装 IOS7.1 Simulator
  14. Dynamic Programming(1)
  15. 飞塔防火墙VOIP ALG参数导致SIP外呼无声音的坑
  16. 坐标西安 面试中电后端Java岗 被面试官狂问mybatis
  17. Win11找不到DNS地址怎么办?Win11找不到DNS无法访问网页解决方法
  18. 教你快速配置wordpress由http变成https访问
  19. 网格搜索法调参神经网络
  20. gohead 嵌入式服务器

热门文章

  1. 简单的Android程序多少钱,Android简单程序利息计算器
  2. [python]用爬虫下载某站小说并生成epub格式电子书(用mkepub库)
  3. canvas在PC端实现振幅大小可变的动态波浪图
  4. html图片水波浪,css 实现水波纹,波浪动画效果
  5. [Python图像处理] 合成微缩效果
  6. Oracle建表时弹出 ORA-00955: 名称已由现有对象使用
  7. 物料科目组设置和分配-OVK5/SM30(V_TVKM)/VKOA
  8. grub.cfg使用说明
  9. python开发“小迪安全课堂笔记”
  10. html国庆节代码,小程序10行代码实现微信头像挂红旗,国庆节个性化头像