各种常用的插入排序(直接,折半,希尔)

    本来打算昨天发,结果竟然学了一个晚上,自认为大学数据结构学得还不错,重新翻一遍竟然看了这么久还没有理解透彻,更加坚定了我一天一算法的决心。昨天和今天的排序一块写出来一块总结道插入排序里好啦。

老样子,代码走起。

<pre name="code" class="csharp">using System;
/// <summary>
/// 插入排序
/// </summary>
namespace test
{
	class MainClass
	{
		public static void Main (string[] args)
		{
			int [] arr = {3, 1, 33, 4, 6, 2, 8, 14, 5};
			//DirectInsertSort (arr);
			//BinaryInsertSort (arr);
			ShellSort (arr);
			foreach (int i in arr) {
				Console.WriteLine (i);
			}
		}
		//直接插入排序,最简单的排序,从数组第二个数开始作为关键字向前面的数字组成的数组
		//一次对比,并将自己插入前面数组第一个比他大的数前面,前面数组后面的数依次后移一位
		private static void DirectInsertSort (int [] arr) {
			int temp = 0;									//存放作为关键字的元素的值
			int j = 0;
			for (int i = 1; i < arr.Length; i++) {			//从数组第二个数开始遍历
				temp = arr [i];
				for (j = i - 1; j >= 0 && arr [j] > temp; j--) {				//如果碰到一个比temp大的数,则temp索引位前比temp大的数
					arr [j + 1] = arr [j];												//的索引位大的数依次后移一位
				}
				arr [j + 1] = temp;							//由于for循环最后执行一次j--,所以将temp给j+1位的元素
			}
		}
		//折半插入排序,由于插入排序是对有序数列插入,前面已经排好的序列通过折半查找找到插入元素的位置
		private static void BinaryInsertSort (int [] arr) {
			for (int i = 1; i < arr.Length; i++) {
				int temp = arr [i];								//中间变量,存放对比的关键值
				int low = 0;
				int high = i - 1;
				while (low <= high) {
					int middle = (low + high) / 2;
					if (temp < arr [middle]) {					//若中间值大于temp说明temp的位置应该在middle后面,反之亦然
						high = middle - 1;
					} else {
						low = middle + 1;
					}
				}
				for (int j = i; j > high + 1; j--) {
					arr [j] = arr [j - 1];
				}
				arr [high + 1] = temp;
			}
		}
		//希尔排序,增量的规则一般是第一次取长度一半,第二次取一半的一半,一次递推,希尔排序不稳定
		//增量也可以根据实际情况写一个函数,增量是用来分割数组的,每组数字都具有增量的函数特性
		//好的增量序列的共同特征:
		//1.最后一个增量必须为1
		//2.应该尽量避免序列中的值(尤其是相邻的值)互为倍数的情况
		private static void ShellSort (int [] arr) {						
			int i, j, increment;												//increment表示增量
			int temp = 0;
			increment = arr.Length / 2;
			//根据increment分割的各组进行直接插入排序
			while (increment > 0) {
				for (i = increment; i < arr.Length; i++) {
					temp = arr [i];
					for (j = i - increment; j >= 0 && arr [j] > temp; j -= increment) {
						arr [j + increment] = arr [j];
					}
					arr [j + increment] = temp;
				}
				increment = increment / 2;							//每次循环increment取半,直到为1
			}
		}
	}
}

插入排序的根本思想在于每次对有序数列进行插入值,所以前两种排序都是稳定的,时间复杂度皆为n2,而希尔排序由于多次分成多个部分进行插入排序,是不稳定的,复杂度根据增量而定,好的增量会使希尔排序的效率很高。

点赞