![68e5cc32efec9831c0b8497de8d69b91.png](https://i-blog.csdnimg.cn/blog_migrate/8a767ed29a774e7b91edbc6a7eceac0c.jpeg)
本文介绍插入排序的原理,制作可视化插入排序的蓝图BP_Sort_Insertion,继承蓝图BP_Sort。
引擎版本UE4.25,项目github:https://github.com/tiax615/UE4_Sort
插入排序的可视化效果如下:
知乎视频www.zhihu.com1. 算法原理
![d63461923ecacb3f21bae2ee07ad28d0.png](https://i-blog.csdnimg.cn/blog_migrate/40c30f1167b219a278a1ad02d561f688.jpeg)
插入排序,一般也被称为直接插入排序。对于少量元素的排序,它是一个有效的算法。插入排序是一种最简单的排序方法,它的基本思想是将一个记录插入到已经排好序的有序表中,从而一个新的、记录数增1的有序表。在其实现过程使用双层循环,外层循环对除了第一个元素之外的所有元素,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动。
插入排序的工作方式像许多人排序一手扑克牌。开始时,我们的左手为空并且桌子上的牌面向下。然后,我们每次从桌子上拿走一张牌并将它插入左手中正确的位置。为了找到一张牌的正确位置,我们从右到左将它与已在手中的每张牌进行比较。拿在左手上的牌总是排序好的,原来这些牌是桌子上牌堆中顶部的牌 。
插入排序是指在待排序的元素中,假设前面n-1(其中n>=2)个数已经是排好顺序的,现将第n个数插到前面已经排好的序列中,然后找到合适自己的位置,使得插入第n个数的这个序列也是排好顺序的。按照此法对所有元素进行插入,直到整个序列排为有序的过程,称为插入排序。
1.1. 时间复杂度
最好情况是O(n)。在插入排序中,当待排序数组是有序时,是最优的情况,只需当前数跟前一个数比较一下就可以了,这时一共需要比较N- 1次,时间复杂度为O(n)。
最坏情况是O(n^2)。最坏的情况是待排序数组是逆序的,此时需要比较次数最多,总次数记为:1+2+3+…+N-1,所以,插入排序最坏情况下的时间复杂度为O(n^2)。
平均时间复杂度O(n^2)。平均来说,A[1..j-1]中的一半元素小于A[j],一半元素大于A[j]。插入排序在平均情况运行时间与最坏情况运行时间一样,是输入规模的二次函数。
1.2. 稳定性
关键词相同的数据元素将保持原有位置不变,所以该算法是稳定的。
2. 代码实现
- 将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
- 从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)
插入排序和冒泡排序一样,也有一种优化算法,叫做拆半插入(这里不讨论)。
public
3. 创建BP_Sort_Insertion
和选择排序有点像,有比较和交换的过程。区别在于,选择排序是进行比较,完成这轮比较后,才进行交换。而插入排序,是在比较过程中,只要当前值小于比较值,就和它交换。
所以这里的可视化,我们需要将当前元素拿出来,和已排序的元素进行比较。将当前元素往后(x负方向)移动一段距离。
未排序元素用默认的蓝色柱子表示,已排序元素用绿色,当前元素用红色,排序序列中和当前元素进行比较后发生了移动的用黄色。
下面介绍如何实现选择排序的可视化蓝图BP_Sort_Insertion,同样继承自BP_Sort,实现DoSort()。
3.1. 变量
双层循环用整数I和J控制,ItemTemp暂存交换的元素。布尔值IsFirstJ将会用在J循环开始时,将当前元素变红和x轴移动。
![43bfa7a150911efc7c5cd01a939ed7f0.png](https://i-blog.csdnimg.cn/blog_migrate/b2a495e30b887c9eec6a8eb352f9660a.png)
3.2. 初始化Init()
初始化I=0,J=1,ItemTemp=null,IsFirstJ=True。
![0f702626413f22c22f9e8834f95d365d.png](https://i-blog.csdnimg.cn/blog_migrate/1115f0ebc5d854b0a8783f7338702736.jpeg)
3.3. 柱子移动MoveX()和MoveY()
MoveX()使当前元素往x负方向移出柱状图,或往x正方向移入柱状图。只需传入索引,如果刚开始J循环(IsFirstJ==True),就移出;否则移入。移动量是2*Width。
![ed482c2f924fa387f94997c0f6167876.png](https://i-blog.csdnimg.cn/blog_migrate/7e9e8bcc1ab423e769b04c7491daf438.jpeg)
MoveY()使传入索引对应位置的元素y方向移动。传入起始位置索引InLastIndex,目标位置索引InTargetIndex,X轴偏移量InOffsetX。
如果是柱状图里的其他元素,X轴偏移量为0。如果是当前要插入的元素,X轴偏移量为2*Width。
![a3655623bf1b5f83bf4e988a2652ce0d.png](https://i-blog.csdnimg.cn/blog_migrate/7b30d10152b4d914a4b8f2bab88b8ac6.jpeg)
3.4. 排序逻辑DoSort()
两层循环,I<Length-1时,进入I循环。J>0时,进入J循环。进入J循环中,先判断是不是第一次进入。
若是第一次进入,则J元素标红,IsFirstJ=False,J元素移出柱状图。
![dc8da98f545277df3f225aca499d7bd9.png](https://i-blog.csdnimg.cn/blog_migrate/6f5aa8b6b3cfab1e8a084d555889a7c3.png)
不是第一次进入,执行比较和交换的逻辑。执行排序逻辑前SetInfo,之后将J-1元素标黄,比较J-1值和J值大小。
![1f4ecad4bba8303cb349e7ba169e40fa.png](https://i-blog.csdnimg.cn/blog_migrate/00ac7908aac78e7250ba24fb2cd7d219.jpeg)
如果J-1值>J值,则需要交换。可视化将J-1右移,J左移。再将J元素和J-1元素索引交换。做完之后J++。
![421981139a4940cbb9ffb7af3f8497ed.png](https://i-blog.csdnimg.cn/blog_migrate/e7bca4132e93a2f1aa3cc618ba3e730e.jpeg)
如果J-1值<=J值,则此轮排序J循环结束,J元素移入柱状图,将当前已排序的元素标绿。
之后I++,J=I+1,IsFirstJ=True。下次DoSort()时判断是否进入下轮J循环或者完成I循环。
![7d5ce7bccac3a621dc32740c3db93e3d.png](https://i-blog.csdnimg.cn/blog_migrate/7607016d86c2e97fab30bf83ac92c91b.jpeg)
4. 总结
BP_Sort_InSertion完整的事件图表如下。做好后,将BP_Sort_InSertion拖入场景中,Play,就可以观察到选择排序的可视化效果了。
![9970e3263cee24c29025f302db4f322d.png](https://i-blog.csdnimg.cn/blog_migrate/d16cf2a4a87baeab7030d6e0b3cd6744.jpeg)
将当前元素插入到已排序的序列中,从后往前(从大到小)挨个比较往前移动,直到所有元素插入完。
感谢阅读,下一篇将带来希尔排序的可视化。
5. 参考资料
上篇《UE4_排序算法可视化_纯蓝图4:选择排序》
天剑行风:UE4_排序算法可视化_纯蓝图4:选择排序zhuanlan.zhihu.com![cda2ee05c4c6d1f00ed4733509925011.png](https://i-blog.csdnimg.cn/blog_migrate/4524c31831acf77a815a69750a531622.jpeg)
- 示例项目:https://github.com/tiax615/UE4_Sort
- 演示视频:https://www.bilibili.com/video/BV1sp4y1e71x/
- 插入排序_百度百科:https://baike.baidu.com/item/插入排序/7214992
- 排序算法总结|菜鸟教程:https://www.runoob.com/w3cnote/sort-algorithm-summary.html
本文原创,如需转载,请注明出处。欢迎讨论,谢谢!