排序算法——插入排序与希尔排序

最近一直在看《算法》,正好复习到了排序这部分,就都总结一下。


插入排序

插入排序和选择排序都属于非常简单而且容易理解的排序算法。插入排序就像我们平时玩的纸牌,在排顺序的时候,会按照顺序一张一张插入。在一个乱序数组中,同样如此,我们会在遍历中,将数据按照升序或降序方式向之前已经排列好的数据中进行插入。插入排序优势在于对于一个大部分数据已经有序,只有少数无序数据分布其中的模型有着很好的性能。但同样,插入排序并不适合大规模数组排序,因为其内部遍历是对数据挪动是一位一位移动,假如有一个非常大的数组,恰巧最小的数据在最后几位,这样一位一位移动将是非常低效方式。

结论

对于随机排列长度为N且主键不重复的数组,平均情况下插入排序需要N²/4次比较和N²/4 交换,最坏的情况下需要N²/2次比较和N²/2次交换。最好的情况下需要N-1次比较和0次交换。

下面是代码实现

package SORT;

public class InsertSort {
	public static void sort(int[] temp) {
		// 插入排序
		
		for (int i = 1; i < temp.length; i++) {
			for(int j = i;j>0;j--) {
				if (temp[j-1] > temp[j]) {
					// 插入排序开始顺序
					int t = temp[j];
					temp[j] = temp[j-1];
					temp[j-1] = temp[j];
				}
			}
		}
	}
}

插入排序原理简单易懂,就不进行过多阐述,下面主要来看下希尔排序。


希尔排序

希尔排序是首批突破时间复杂度为平方级的算法,在排序算法进化史中占有非常重要的地位。但同样遗憾的是,后来经过证明,其时间复杂度为亚平方级,所以其性能与之后出现的归并排序,快速排序等算法仍有较大差距。

希尔排序我们可以简单理解为加强的插入排序,其思想和插入排序有很大相思的程度,其主要应对情况便是之前我们提出的在一个无序数组中,最小的数据在数组最末端,应用插入排序时,我们需要一位一位交换,这个数值如果是数组长度,那么将是非常高昂的消费。针对这种情况,希尔排序提出了一种新的解决办法,我们可以设置一增量。我们用H来表示该增量。首先我们将数组内间隔为H的数据进行排序,保证间隔为H的数据有序,通过这样处理后,数据实际上就成为了H个有序数组的组合,通过将H缩小,我们遍能进行更加精细化的排序,当H=1时,排序完成。通过这种方法,我们开始便能将位置太过靠后的数据大幅度向前移动,减小花费。

希尔排序更加高效的原因在于它权衡了数组的规模和有序性。排序初,各个数组都很短,排序后数组都是部分有序,这两种情况很适合插入排序。自数组部分有序的成都取决于递增序列的选择。

下面我们结合代码来具体分析。

package SORT;

public class ShellSort {
	// 希尔排序
	public static void sort(int[] temp) {
		// 数组长度
		int length = temp.length;
		// 初始增量
		int N = 1;
		// 根据数组长度进行增量设置
		while (N < length / 3) {
			N = N * 3 + 1;
		}
		// 循环
		while (N >= 1) {
			// 将数组变为H有序
			for (int i = N; i < length; i++) {
				// 将temp[i]插入到temp[i-N],temp[i-2*N],temp[i-3*N]
				for (int j = i; j >= N; j = j - N) {
					int t = temp[j];
					temp[j] = temp[j - N];
					temp[j - N] = t;
				}
				N = N / 3;
			}
		}
	}
}

由代码可以看到,我们最开始取得的增量N为输入数组的长度三分之一,有人会问,这个值是怎么来的。实际上,关于增量如何取值,不同的人有着不同的说法,有按照8,5,3,2,1进行增量取值,也有按照数组长度不断与一个常数进行相乘取值。至于我选择的数组长度的三分之一,因为经过多次时间测试,相对来说比较稳定,在各方面都不具备短板的一个值。

当我们将相差为N的数组进行排序后,再将N/3进行排序,这样每轮排序实际上将事大部分数据变的有序,这样的模型非常适合插入排序进行计算。

希尔排序同样适合大型数组。它对任意排序数组表现都很好,何况它不需要开辟额外的内存空间。而且,数组越大,希尔排序的优势将越加明显。对于越大的N,有些快速排序的方法也许只能笔希尔排序快两倍,而且更加复杂。我们可以在排序时先使用希尔排序,再进行优化,考虑更加复杂的排序算法。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

猜你喜欢

转载自blog.csdn.net/weixin_41582192/article/details/81215572
今日推荐