算法入门---java语言实现的插入排序小结

本文详细介绍了插入排序的基本原理和实现步骤,并给出了两种不同的实现方式:原始版本和改进版本。通过具体的代码示例,展示了如何使数组变得有序。同时,还讨论了插入排序的时间复杂度以及在不同情况下的表现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. public class InsertSort {
  2. /**
  3. *你想啊,每个的前面都是比它小的,这样的组合肯定是有序的啊,细分到最小,每一个都需要遵守规则,
  4. * 这样就保证了前面的所有的,即使没和我挨着那么也是都比我小的。
  5. * 插入排序的思想:
  6. * 元素从前往后,第一个元素排在它应该排的位置,然后去遍历第二个元素插入到它合适的位置,
  7. * 然后依次这样,那么怎么算是它合适的位置那?就是前面要么它是第一个了,要么前面的数比它小了
  8. * 这就证明它已经找好自己的位置可以退出查找了,每个数都按照这样来,直到最后排好序
  9. * @param src 数据源.
  10. */
  11. public static void sort(int[] src){
  12. int len = src.length;
  13. //第一个数认为有序不需要比较,所以从第一个开始
  14. //此时的索引是将要插入的元素.
  15. for(int i = 1;i<len;i++){
  16. //j索引应该是i后面的哪一个,依次和前一个比较找到自己合适的位置就可以退出这个循环,或者走到了最前面.
  17. //当发现前面的比自己大的时候就需要交换位置(个人感觉是不是可以吧选择排序合入?)
  18. /*for(int j = i;j>0;j--){
  19. if(src[j]<src[j-1]){
  20. int temp = src[j-1];
  21. src[j-1] = src[j];
  22. src[j] = temp;
  23. }else{
  24. break;
  25. }
  26. }*/
  27. //可以简化成这样,注意是从i开始,而不是i+1.不要到最后一个i+1越界。
  28. for(int j = i;j>0 && (src[j]<src[j-1]);j--){
  29. int temp = src[j-1];
  30. src[j-1] = src[j];
  31. src[j] = temp;
  32. }
  33. }
  34. }
  35. }
          插入排序的一个特性就是,中途可能会退出,不许要完全比较完未排序的序列。
          时间复杂度:
          最坏的情况就是到序的时候,插入第2个元素时要比较前1个元素,插入第3个元素时,要比较前2个元素,……,插
入第N个元素,要比较前 N - 1 个元素。因此,最坏情况下的比较次数是 1 + 2 + 3 + ... + (N - 1)也就是 N^2 / 2,所以最坏
情况下的复杂度为 O(N^2)。
          最好情况下,数组已经是有序的,每插入一个元素,只需要比较前一个元素,(比较完就退出了)因此最好情况下,
插入排序的时间复杂度为O(N)
          实测平均用时:
  1. 10000
  2. name: 冒泡排序1 花费了 = 73ms
  3. name: 冒泡排序2 花费了 = 67ms
  4. name: 冒泡排序3 花费了 = 58ms
  5. name: 冒泡排序4 花费了 = 58ms
  6. name: 冒泡排序5 花费了 = 60ms
  7. 平均:51
  8. 50000
  9. name: 冒泡排序1 花费了 = 1684ms
  10. name: 冒泡排序2 花费了 = 1660ms
  11. name: 冒泡排序3 花费了 = 1486ms
  12. name: 冒泡排序4 花费了 = 1436ms
  13. name: 冒泡排序5 花费了 = 1482ms
  14. 平均:1549
  15. 100000
  16. name: 冒泡排序1 花费了 = 6742ms
  17. name: 冒泡排序2 花费了 = 6700ms
  18. name: 冒泡排序3 花费了 = 5880ms
  19. name: 冒泡排序4 花费了 = 5888ms
  20. name: 冒泡排序5 花费了 = 5848ms
  21. 平均:6211
        总的看起来还是比选择排序用时长,比冒泡排序用时短。它能中断所以比冒泡短,但是即使它可以中断,但交换的
次数相对于选择排序还是非常的多的,而一次的交换就意味着三次的赋值。
但是它可以改进,对插入排序进行改进,核心是利用每次需要交换元素时换成赋值的,把前面比较大的元素复制到它的后
一个索引所在的位置(这个位置最开始的是要插入的那个元素,拿出来保留住),一直到最后,再把前面保留住的元素存入
到最后空出来的这个合适的位置。
       改进后的代码如下:
  1. /**
  2. * 改进后的插入排序。
  3. * 核心改进思想:当发现比前面数据小的时候不是每次都要交换,而是通过赋值。
  4. * 先把最初的元素的值取出来保存,把当前位置往后赋值。循环到最后,再把取出来的数放入空出的位置。
  5. * @param src 数据源
  6. */
  7. public static void betterInsertSort(int[] src){
  8. int len = src.length;
  9. for(int i = 1;i<len;i++){
  10. //先把需要插入到指定序列的元素拿出来,用于最后确定位置的时候进行插入。
  11. int e = src[i];
  12. int j;//为了方便最后出来的时候最后的赋值。
  13. //比较拿出来的那个元素和前面各个元素的大小。注意从j-1开始。
  14. for(j=i;j>0&&(e<src[j-1]);j--){
  15. //由于e小于j-1索引对应的数,那么把j-1索引对应的数赋值到j上,向后移动而不是交换。
  16. src[j] = src[j-1];
  17. }
  18. //循环完毕后,此时e>j或者j == 0了。一直比较的是j是当前索引,不符合的时候j-1赋值给j,然后j往前动1。
  19. //此时还是比较当前所以,不符合那么直接把拿出来的放这即可。
  20. src[j] = e;
  21. }
  22. }
        改进后的实测时间:
  1. 10000
  2. name: 冒泡排序1 花费了 = 47ms
  3. name: 冒泡排序2 花费了 = 39ms
  4. name: 冒泡排序3 花费了 = 17ms
  5. name: 冒泡排序4 花费了 = 17ms
  6. name: 冒泡排序5 花费了 = 20ms
  7. 平均:28
  8. 50000
  9. name: 冒泡排序1 花费了 = 949ms
  10. name: 冒泡排序2 花费了 = 934ms
  11. name: 冒泡排序3 花费了 = 414ms
  12. name: 冒泡排序4 花费了 = 418ms
  13. name: 冒泡排序5 花费了 = 421ms
  14. 平均:627
  15. 100000
  16. name: 冒泡排序1 花费了 = 3892ms
  17. name: 冒泡排序2 花费了 = 3824ms
  18. name: 冒泡排序3 花费了 = 1708ms
  19. name: 冒泡排序4 花费了 = 1674ms
  20. name: 冒泡排序5 花费了 = 1710ms
  21. 平均:2561
         对比别的博客的数据值可以看出来平均来说已经比插入快了,就是因为它有可能会中断,不需要每次都查询到未排
序序列的最后。
稳定性:稳定。
      你想啊,只有小于的时候才进行插入,不然直接就break了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值