插入排序


插入排序,一般也被称为直接插入排序。对于少量元素的排序,它是一个有效的算法。插入排序是一种最简单的排序方法,它的基本思想是将一个记录插入到已经排好序的有序表中,从而一个新的、记录数增1的有序表。在其实现过程使用双层循环,外层循环对除了第一个元素之外的所有元素,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动。

插入排序的核心思想就是:在一个有序数组中找到一个新加入的值在有序数组中的位置。

Java版

实现方式一(时间复杂度O(n^2) )

内层循环从有序数组的头部开始遍历,找到当前新加入值在这个有序数组中的下标,然后进行移动,将新加入的值插入。

public int[] insertSort(int[] arr){
    if (null== arr || arr.length==0){
        return arr;
    }
    int len = arr.length;
    for(int i=1; i<len; i++){
        if (arr[i-1] < arr[i]) {
            // 新进入的数字比当前有序数组的最后一个数字大,那么需要查找新加入数字的位置
            for (int j=0; j<i; j++){
                // 在有序数组里面找到这个新加入数字的位置
                if (arr[j] < arr[i]){
                    // 找到新加入数字的位置为j;此时将数字插入数数组里面
                    int temp = arr[i];
                    //将找到的位置处的数都向后移动
//                        for (int k=i; k>j; k--){
//                            arr[k] = arr[k-1];
//                        }
                    // 这个系统的函数的意思是从源数组的下标为j的地方开始,拷贝i-j个数字到目标数组中,从目标数组的j+1下标开放置
                    System.arraycopy(arr, j, arr, j + 1, i - j);
                    arr[j] = temp;
                    break;
                }
            }
        }
    }
    return arr;
}

实现方式二(时间复杂度O(nlgN))

这种方式是在第一种方式的基础上优化了的内层循环在查找新进入的值的位置的算法,下面采用的是二分查找算法

public int[] insertSort(int[] arr){
    int len = arr.length;

    for (int i=1; i<len; i++){
        if (arr[i]>arr[i-1]){
            // 查找当前值在有序数组中的位置;下面采用二分查找算法(lgN)进行处理
            int left = 0;
            int right = i-1;
            int tmp = arr[i];

            while (left<=right){
                int mid = (left+right) >> 1;
                if (tmp > arr[mid]){
                    right = mid-1;
                }else {
                    left = mid+1;
                }
            }
            // 将数组后移,腾出新加入数据的位置
            System.arraycopy(arr, left, arr, left+1, i-left);
            arr[left] = tmp;
        }
    }
    return arr;
}

实现方式三(时间复杂度O(n^2))

内层循环从有序数组的尾部开始遍历,当后一个比前一个大(从大到小排序)就交换顺序,直到前一个比后一个小。

public int[] insertSort(int[] arr){
    int len = arr.length;

    for (int i=1; i<len; i++){
        if (arr[i-1] < arr[i]) {
            // 使用从最后面开始比较;如果小于当前值就交换顺序
            for (int j=i; j>0; j--){
                // 这里做个优化:因为这个 0~~(i-1) 的数组是有序的;因此当这个值比前面小的时候那么就说明已经排序好了;
                if (arr[j] <= arr[j-1]){
                    break;
                }
                // 直接使用当前值从后面依次比较,如果当前值大于的话那么就进行值的交换
                if (arr[j] > arr[j-1]){
                    int tmp = arr[j];
                    arr[j] = arr[j-1];
                    arr[j-1] = tmp;
                }
            }
        }
    }
    return arr;
}

Golang版本

实现方式一

func insertSort(arr [6]int) [6]int {
	size := len(arr)
	for i:=1; i<size; i++ {
		if arr[i] > arr[i-1] {
			for j:=0; j<i; j++ {
				if arr[j]<arr[i] {
					tmp := arr[i]
					for k:=i-1; k>=j; k-- {
						arr[k+1] = arr[k]
					}
					arr[j] = tmp
					break
				}
			}
		}
	}
	return arr
}

实现方式二

func insertSort(arr [6]int) [6]int {
	size := len(arr)
	for i:=1; i<size; i++ {
		if arr[i] > arr[i-1] {
			left, right, mid := 0, i-1, 0
			tmp := arr[i]

			// 通过二分查找
			for left<=right {
				mid = (left+right)>>1
				if arr[mid] < tmp {
					right = mid-1
				}else {
					left = mid+1
				}
			}

			for k:=i-1; k>=left; k-- {
				arr[k+1] = arr[k]
			}
			arr[left] = tmp
		}
	}
	return arr
}

特别提醒:扫码关注微信订阅号'起岸星辰',实时掌握IT业界技术资讯! 转载请保留原文中的链接!
 上一篇
Docker搭建ELK日志系统 Docker搭建ELK日志系统
基于Docker搭建ELK日志系统,并在Spring Boot中集成Logstash实现微服务的日志收集;ELK是Elasticsearch、Logstash、Kibana的简称,这三者是核心套件实现日志采集、分析、展示,但并非全部。
2021-04-08
下一篇 
2021年4月资讯(一) 2021年4月资讯(一)
Nacos2.0正式发布,性能提升10倍;微软Edge浏览器新功能实现和原生应用相同的视觉;微信iOS更新8.0.3版本朋友圈可发30秒视频;深度操作系统20.2发布,系统性能进一步优化,只为给你更流畅的使用感受。
2021-04-01
  目录