插入排序

一、定义

1.1 说明

图解:

描述:

​ 对N个元素的数组进行插入排序,它将有N-1次排序完成。其原理也很简单:从第二个元素开始对每一个元素进行排序,即p=1开始,对每一位置p上的元素与前0到p上的元素对比,将p放入合适的位置。所以第p趟排序时,位置p前面的元素已经排序好了。只需要将p上的元素插入到一个已经排序的合适的位置。

做法:将p上的元素向左移动到x,直到位置x-1的元素比它小,x+1上的元素比它大。

例如数组a[]={34,8,64,51,32,21}。我们从p=1开始进行排序,将a[p]元素左移,直到它在合适的位置。

p=1时,对8进行排序:8,34,64,51,32,21;

p=2时,对64进行排序:8,34,64,51,32,21;

p=3时,对51进行排序:8,34,51,64,32,21;

p=4时,对32进行排序:8,32,34,51,64,21;

p=5时,对21进行排序:8,21,32,34,51,64;

1.2 算法分析

很明显,根据前面的描述,定义p为索引位置,当p=1时,最多需要用到1次比较,p=2时,最多需要2次比较。一直到p=N-1。所以总的比较次数最多:

[sum_{i=2}^{N}i=1+3+···+(N-1)=Theta(N^2) ]

由于插入排序的性质:将p放入前面已经排序的数组片段中。所以,输入几乎被排序的数组,插入排序会运行得很快。

Java代码

/**
 * 插入排序
 *
 * @Author: dhcao
 * @Version: 1.0
 */
public class InsertionSortEx<T extends Comparable<? super T>> {

	/**
	 * 直接对数组a进行排序
	 *
	 * @param a   需要排序数组
	 * @param <T> 实现Comparable接口对类型
	 */
	public static <T extends Comparable<? super T>> void insertionSort1(T[] a) {

		// 技巧1:在循环中重复定义的函数,可以放到循环外定义。
		int j;

		/**
		 * 从位置p=1开始,对所有对数组元素进行排序
		 */
		for (int p = 1; p < a.length; p++) {

			// 提前将排序的元素a[p]准备好
			T tmp = a[p];

			// 将位置p上的元素向左边移动(即p左边的元素向右移动)(由于左边从0到p-1的元素已经在排序状态)
			for (j = p; j > 0 && tmp.compareTo(a[j - 1]) < 0; j--) {
				
				// 技巧2:将必须的操作留在循环中,不需要的操作可以移到循环外
				a[j] = a[j - 1];
			}
			a[j] = tmp;
		}

	}

	/**
	 * 将数组中的某一段进行排序。
	 * @param a 数组
	 * @param left 需要排序的左界
	 * @param right 需要排序的右界
	 * @param <T> 实现Comparable接口对类型
	 */
	public static <T extends Comparable<? super T>> void insertionSort2(T[] a,int left,int right){
		
		int j;
		for (int p = left + 1; p <= right; p++) {
			T tmp = a[p];
			for (j = p; j > 0 && tmp.compareTo(a[j - 1]) < 0; j--) {
				a[j] = a[j - 1];
			}
			a[j] = tmp;
		}
	}

}

原文地址:https://www.cnblogs.com/dhcao/p/10693286.html