算法入门---java语言实现的插入排序小结
2017-04-08 11:50
435 查看
public class InsertSort {
/**
*你想啊,每个的前面都是比它小的,这样的组合肯定是有序的啊,细分到最小,每一个都需要遵守规则,
* 这样就保证了前面的所有的,即使没和我挨着那么也是都比我小的。
* 插入排序的思想:
* 元素从前往后,第一个元素排在它应该排的位置,然后去遍历第二个元素插入到它合适的位置,
* 然后依次这样,那么怎么算是它合适的位置那?就是前面要么它是第一个了,要么前面的数比它小了
* 这就证明它已经找好自己的位置可以退出查找了,每个数都按照这样来,直到最后排好序
* @param src 数据源.
*/
public static void sort(int[] src){
int len = src.length;
//第一个数认为有序不需要比较,所以从第一个开始
//此时的索引是将要插入的元素.
for(int i = 1;i<len;i++){
//j索引应该是i后面的哪一个,依次和前一个比较找到自己合适的位置就可以退出这个循环,或者走到了最前面.
//当发现前面的比自己大的时候就需要交换位置(个人感觉是不是可以吧选择排序合入?)
/*for(int j = i;j>0;j--){
if(src[j]<src[j-1]){
int temp = src[j-1];
src[j-1] = src[j];
src[j] = temp;
}else{
break;
}
}*/
//可以简化成这样,注意是从i开始,而不是i+1.不要到最后一个i+1越界。
for(int j = i;j>0 && (src[j]<src[j-1]);j--){
int temp = src[j-1];
src[j-1] = src[j];
src[j] = temp;
}
}
}
}
插入排序的一个特性就是,中途可能会退出,不许要完全比较完未排序的序列。
时间复杂度:
最坏的情况就是到序的时候,插入第2个元素时要比较前1个元素,插入第3个元素时,要比较前2个元素,……,插
入第N个元素,要比较前 N - 1 个元素。因此,最坏情况下的比较次数是 1 + 2 + 3 + ... + (N - 1)也就是 N^2 / 2,所以最坏
情况下的复杂度为 O(N^2)。
最好情况下,数组已经是有序的,每插入一个元素,只需要比较前一个元素,(比较完就退出了)因此最好情况下,
插入排序的时间复杂度为O(N)
实测平均用时:
10000
name: 冒泡排序1 花费了 = 73ms
name: 冒泡排序2 花费了 = 67ms
name: 冒泡排序3 花费了 = 58ms
name: 冒泡排序4 花费了 = 58ms
name: 冒泡排序5 花费了 = 60ms
平均:51
50000
name: 冒泡排序1 花费了 = 1684ms
name: 冒泡排序2 花费了 = 1660ms
name: 冒泡排序3 花费了 = 1486ms
name: 冒泡排序4 花费了 = 1436ms
name: 冒泡排序5 花费了 = 1482ms
平均:1549
100000
name: 冒泡排序1 花费了 = 6742ms
name: 冒泡排序2 花费了 = 6700ms
name: 冒泡排序3 花费了 = 5880ms
name: 冒泡排序4 花费了 = 5888ms
name: 冒泡排序5 花费了 = 5848ms
平均:6211
总的看起来还是比选择排序用时长,比冒泡排序用时短。它能中断所以比冒泡短,但是即使它可以中断,但交换的
次数相对于选择排序还是非常的多的,而一次的交换就意味着三次的赋值。
但是它可以改进,对插入排序进行改进,核心是利用每次需要交换元素时换成赋值的,把前面比较大的元素复制到它的后
一个索引所在的位置(这个位置最开始的是要插入的那个元素,拿出来保留住),一直到最后,再把前面保留住的元素存入
到最后空出来的这个合适的位置。
改进后的代码如下:
/**
* 改进后的插入排序。
* 核心改进思想:当发现比前面数据小的时候不是每次都要交换,而是通过赋值。
* 先把最初的元素的值取出来保存,把当前位置往后赋值。循环到最后,再把取出来的数放入空出的位置。
* @param src 数据源
*/
public static void betterInsertSort(int[] src){
int len = src.length;
for(int i = 1;i<len;i++){
//先把需要插入到指定序列的元素拿出来,用于最后确定位置的时候进行插入。
int e = src[i];
int j;//为了方便最后出来的时候最后的赋值。
//比较拿出来的那个元素和前面各个元素的大小。注意从j-1开始。
for(j=i;j>0&&(e<src[j-1]);j--){
//由于e小于j-1索引对应的数,那么把j-1索引对应的数赋值到j上,向后移动而不是交换。
src[j] = src[j-1];
}
//循环完毕后,此时e>j或者j == 0了。一直比较的是j是当前索引,不符合的时候j-1赋值给j,然后j往前动1。
//此时还是比较当前所以,不符合那么直接把拿出来的放这即可。
src[j] = e;
}
}
改进后的实测时间:
10000
name: 冒泡排序1 花费了 = 47ms
name: 冒泡排序2 花费了 = 39ms
name: 冒泡排序3 花费了 = 17ms
name: 冒泡排序4 花费了 = 17ms
name: 冒泡排序5 花费了 = 20ms
平均:28
50000
name: 冒泡排序1 花费了 = 949ms
name: 冒泡排序2 花费了 = 934ms
name: 冒泡排序3 花费了 = 414ms
name: 冒泡排序4 花费了 = 418ms
name: 冒泡排序5 花费了 = 421ms
平均:627
100000
name: 冒泡排序1 花费了 = 3892ms
name: 冒泡排序2 花费了 = 3824ms
name: 冒泡排序3 花费了 = 1708ms
name: 冒泡排序4 花费了 = 1674ms
name: 冒泡排序5 花费了 = 1710ms
平均:2561
对比别的博客的数据值可以看出来平均来说已经比插入快了,就是因为它有可能会中断,不需要每次都查询到未排
序序列的最后。
稳定性:稳定。
你想啊,只有小于的时候才进行插入,不然直接就break了。
相关文章推荐
- 算法入门---java语言实现的冒泡排序小结
- 算法入门---java语言实现的希尔排序小结
- 算法入门---java语言实现的快速排序小结
- 算法入门---java语言实现的选择排序小结
- 算法入门---java语言实现的归并排序小结
- 算法入门---java语言实现的二分搜索树小结
- 算法入门---java语言实现的堆排序小结
- 算法入门---java语言实现的二分查找小结
- 算法入门---java语言实现的并查集(Union-Find)小结
- Java语言中Object对象的hashCode()取值的底层算法是怎样实现的?
- “插入排序”算法Java语言的实现与详解
- 算法竞赛入门经典java实现第一章--语言入门篇
- (算法入门)基本图论-广度优先搜索之JAVA实现
- 【算法】超大数组去重(Java语言实现)
- java语言实现常用算法(排序和查找)
- SVM分类算法,libsvm的Java语言实现-根据语料和测试语料判断准确率的
- Java语言中Object对象的hashCode()取值的底层算法是怎样实现的?,object hashcode
- 【算法】求多个数组中的交集(Java语言实现)
- java 语言实现的随机数生成算法
- [Java基础要义] Java语言中Object对象的hashCode()取值的底层算法是怎样实现的?