学习笔记-数据结构与算法-插入排序

插入排序

插入排序的原理:

在一个已经有序的数组中,在插入一个数据后,如何继续让数据继续保持有序?

这个很容易解决,先在有序的数组中找到待插入数据的位置,然后将其插入即可。

 

也来画个图

这就是插入排序的原理。

 

插入是如何借助上面的原理来实现排序。

将数据分为两个区间,已排序区间和未排序区间。初始已经排序数据仅一个数据。然后在未排序的数据中取一个元素在已经排序区间中查找插入位置,将其插入,重复这个过程。直到未排序区间为空,排序结束。

 

以5、3、8、2、7、1为例

插入排序包含两种操作,元素的比较,元素的移动,当插入一个数据a在已排序区间时,就拿a在已排序区间的数据依次比较,找到插入点的位置,再将插入点位置后面的数据依次

向后移动一位,最后将数据a放入到插入点。就完成了一个数据的插入排序,重复n次,就完成了一组数据的插入排序。

对于一个给定的初始序列,移动操作的次数总是固定的,就等于逆序度。

那为什么移动次数就等于逆序度?

还是刚刚的数据,来确定下移动的次数,(5、3、8、2、7、1)

对于这组数据,有序元素对是(5、8) (5、7) (3、8) (3、7) (2、7)

初始的有序度是5,逆序度是10,插入排序中,移动个数的总和也是10,(1+3+1+5)

插入排序的实现

我的插入排序的算法实现

public class InsertSort<T> implements SortInf<T> {

 
@Override
 
public void sort(T[] data) {
   
// 1,进行数据的检查
   
if (null == data || data.length <= 1) {
     
return;
   
}
   
// 进行数据的检查
   
if (!(data[0] instanceof Comparable)) {
     
throw new IllegalArgumentException("data not implement compator interface");
   
}

   
int dataLen = data.length;
   
T insertData;

    for
(int i = 1; i <= dataLen - 1; i++) {

     
int insertPos = i;
     
insertData = data[i];

     
// 1,查找插入位置
     
for (int j = 0; j < i; j++) {
       
// 按从小到大,x < j ? -1
       
if ((((Comparable) data[j]).compareTo(insertData)) > 0) {
          insertPos = j
;
          break;
       
}
      }
     
// 将数据依次向后移动一位
     
for (int j = i; j > insertPos; j--) {
        data[j] = data[j -
1];
     
}

     
// 将数据放入
     
data[insertPos] = insertData;

     
System.out.println("当前前第:" + i + "次:" + Arrays.toString(data));
   
}
  }
}

 

老师的标准实现

 

public class InsertSort<T> implements SortInf<T> {

 
@Override
 
public void sort(T[] data) {
   
// 插入排序,a 表示数组,n表示数组大小

   
if (data.length <= 1) return;

    int
dataLen = data.length;

    for
(int i = 1; i < dataLen; ++i) {
     
T value = data[i];
      int
j = i - 1;
     
// 查找插入的位置,并进行数据移动
     
for (; j >= 0; --j) {
       
if (((Comparable) data[j]).compareTo(value) > 0) {
         
// 数据移动
         
data[j + 1] = data[j];
       
} else {
         
break;
       
}
      }
     
// 插入数据
     
data[j + 1] = value;
     
// 打印相关的值
     
System.out.println("当前第" + i + "次的值为:" + Arrays.toString(data));
   
}
  }
}

 

 

自己与老师标准实现的区别:

不同点在于查找插入位置的方法,我的查找插入位置是从前向后查找,先找到插入点,然后将插入点的位置之后的数据,依次向后移动一位。而老师的则是直接从后向前查找,仅移动插入点后需要移动的数据,当数据不再需要移动,则说明是插入点。文字描述不够直观,还是用图下说明吧。

我的查找插入点移动数据操作

老师的查找插入点移动数据操作

通过对比发现,老师的标准插入排序,比我的更为高效,

高效的原因在于:仅遍历了需要移动的数据数据,则我的查找,无需移动的数据也进行了遍历,属于浪费。

 

插入排序总结

算法名称

最好情况时间复杂度

最好情况的原始数据

最坏情况时间复杂度

最坏情况的原始数据

平均情况时间复杂度

是否基于比较

空间复杂度

是否稳定排序算法

插入排序

O(N)

原始数据已经是有序,无需移动动插入

O( )

 

原始数据倒序排列

O( )

O(1)

原地排序算法

(在相等情况下,插入元素后面的位置)

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值