八大排序之插入排序—直接插入排序

时间复杂度
当数据正序时,执行效率最好,每次插入都不用移动前面的元素,时间复杂度为O(N)。
当数据反序时,执行效率最差,每次插入都要前面的元素后移,时间复杂度为O(N2)。
所以,数据越接近正序,直接插入排序的算法性能越好。

空间复杂度
由直接插入排序算法可知,我们在排序过程中,需要一个临时变量存储要插入的值,所以空间复杂度为 1 。

算法稳定性
直接插入排序的过程中,不需要改变相等数值元素的位置,所以它是稳定的算法。

算法步骤:
1、将待排序的序列分为有序序列和未排序序列,第一个元素作为有序序列,其他的都作为未排序序列。
2、依次扫描未排序序列,将每个元素插入到有序序列的适当位置。应注意:
如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。
如果待插入的元素小于有序序列中的某个元素,则将待插入元素插入到相等元素的前面。

代码1:

public class Insert_sortTest {
	public static void main(String[] args) {
		int[] arr = {45,123,12,53,12};
		Insert_sortTest is = new Insert_sortTest();
		int[] array = is.Insert_sort(arr);
		System.out.println(Arrays.toString(array));
	}
	
	public int[] Insert_sort(int[] arr) {
		int j;
		//控制取的那个数
		for (int i = 1; i < arr.length; i++) {
			int temp = arr[i];
			//控制有序序列
			for (j = i; j > 0 && arr[j-1] > temp; j--) {
				arr[j] = arr[j-1];
			}
			arr[j] = temp;
		}
		return arr;
	}
}

代码2:

public class Insert_sortTest {
	public static void main(String[] args) {
		int[] arr = {45,123,12,53,12};
		Insert_sortTest is = new Insert_sortTest();
		is.Insert_sort(arr);
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i]+" ");
		}
	}
	
	public void Insert_sort(int[] arr) {
		int j;
		//控制取的那个数
		for (int i = 1; i < arr.length; i++) {
			int temp = arr[i];
			//控制有序序列
			for (j = i; j > 0 && arr[j-1] > temp; j--) {
				arr[j] = arr[j-1];
			}
			arr[j] = temp;
		}
	}
}

代码3:极力推荐

import java.util.Scanner;

public class Main {
	@SuppressWarnings("resource")
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String[] st = sc.nextLine().split(",");
		int[] a = new int[st.length];
		for (int i = 0; i < st.length; i++) {
			a[i] = Integer.parseInt(st[i]);
		}
		insert_sort(a);
		for (int i = 0; i < a.length; i++) {
			System.out.print(a[i]+" ");
		}
	}

	public static void insert_sort(int[] arr) {
		// 每次取的数
		for (int i = 1; i < arr.length; i++) {
			// 将取的数与有序序列的数分别进行对比
			for (int j = i; j > 0; j--) {
				if (arr[j] < arr[j - 1]) {
					int temp = arr[j];
					arr[j] = arr[j-1];
					arr[j-1] = temp;
				}
			}
		}
	}
}

总结:每一趟将一个待排序的关键字按照其值得大小插入到已经排序好的部分有序序列的适当位置上,直到所有待排序关键字都被插入到有序序列中为止。第一趟,把第一个关键字看做有序列的,从第二关键字开始插入。

改进的思想:使用二分法
二分法:二分插入排序主要是因为它采取的是折半搜索待插项的具体位置策略。
二分插入排序首先默认当前排序数列是有序的。然后,从第二项开始进行排序。
首先,折半法查找具体插入索引index;
再对数列进行必要的移动;
最后,将待插项赋给所求索引index;

代码1:

public class Binary_InsertSort {
	public static void main(String[] args) {
		int[] arr = {1,13,23,311,1,32,54,54,8765,23};
		Binary_InsertSort bis = new Binary_InsertSort();
		bis.binary_InsertSort(arr);
		System.out.print("arr: ");
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i]+" ");
		}
	}
	
	public void binary_InsertSort(int[] arr){
		for (int i = 1; i < arr.length; i++) {
			if(arr[i] < arr[i-1]){
				int left = 0;
				int right = i-1;
				int temp = arr[i];
				while(left <= right){
					int mid = (right - left)/2+left;
					if(arr[mid] > temp){
						right = mid - 1;
					}else{
						left = mid + 1;
					}
				}
				for (int j = i-1; j >= left; j--) {
					arr[j+1] = arr[j];
				}
				arr[left] = temp;
			}
		}
	}
}

当n较大时,即数组元素较多时,二分插入排序的比较次数比直接插入排序的最差情况好得多,但比直接插入排序的最好情况要差,所当以元素初始序列已经接近升序时,直接插入排序比二分插入排序比较次数少。二分插入排序元素移动次数与直接插入排序相同,依赖于元素初始序列。

代码2:

import java.util.Scanner;

public class Main {
	@SuppressWarnings("resource")
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String[] st = sc.nextLine().split(",");
		int[] a = new int[st.length];
		for (int i = 0; i < st.length; i++) {
			a[i] = Integer.parseInt(st[i]);
		}
		new Main().binary_InsertSort(a);
		for (int i = 0; i < a.length; i++) {
			System.out.print(a[i] + " ");
		}
	}

	public void binary_InsertSort(int[] arr) {
		// 每次取的数
		for (int i = 1; i < arr.length; i++) {
			// 将取的数与有序序列的数分别进行对比
			if (arr[i - 1] > arr[i]) {
				int left = 0;
				int right = i-1;
				int temp = arr[i];
				//利用二分法查找插入元素的下标
				while(left <= right){
					int mid = (right + left)/2;
					if(arr[mid] > temp){
						right = mid - 1;
					}else{
						left = mid + 1;
					}
				}
				//将嗲插入下标后的有序数组向右移动
				for (int j = i-1; j >= left; j--) {
					arr[j+1] = arr[j];
				}
				arr[left] = temp;
			}
		}
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值