希尔排序

希尔排序

个人理解

希尔排序的引入使得排序算法的时间复杂度突破了O(n2)

它巧妙的点在于事先让混乱的序列简单的趋于有序

具体做法为

让序列分层,只不过不是按顺序的分组,是跳跃的分组,比如,1,3,5,7,9是一个组,2,4,6,8,是一个。这样的话就打破了两两之间“排序”的关系。

分好组以后先进行组内排序,然后再次打乱进行分层,再次排序。

希尔排序的组内排序可以是冒泡排序,也可以是插入排序,本质都是组内先排好序,让整体快速趋于总体有序。(突然想起高中的熵增理论。。。)

但是冒泡排序的遍历起来并没有比冒泡排序要少,甚至还可能多,因此效率较差

对于插入排序来说,要方便很多,因为某些时候前面的交换能很快解决像{2,3,4,5,6,7,1}这种情况下的排序

希尔排序可以说是升级版的插入排序

代码写之

冒泡排序版(代码需优化,使用的是分组以后排序的思想):

package sort;

import java.util.Arrays;

public class ShellSort
{

	public static void main(String[] args)
	{
		int[] arr =
		{ 5, 3, 1, 2, 6, 4, 8 ,9,10,6,15,3,7};
		shellSort(arr, 3);
		System.out.println(Arrays.toString(arr));

	}

	// 从小到大
	public static void shellSort(int[] arr, int InitArrNum)
	{


		// 先分组
		int ArrNum = InitArrNum;// 子数组 的个数,一共有多少个序列 3
		int SubNum = arr.length / ArrNum;// 每组的个数 总数 / 组数
		// 排序的数

		// 排序的序号 1, 1+3*1,1+3*2,1+3*3,1+3*4....
		while (true)
		{
			for (int SubIndex = 0; SubIndex < ArrNum; SubIndex++)
			{
				// 冒泡排序,排序的是 1, 1+3*1,1+3*2,1+3*3,1+3*4....
				// SubIndex 1 ArrNum 3
				for (int i = 1; i < SubNum; i++)
				{
					for (int j = 0; j < SubNum - i; j++)
					{
						
						if (arr[SubIndex + ArrNum * j] > arr[SubIndex + ArrNum * (j + 1)])
						{
							dataSwap(arr, SubIndex + ArrNum * j, SubIndex + ArrNum * (j + 1));
						}
					}
				}
			}

			ArrNum /= 2;
			if (ArrNum==0)
			{
				break;
			}
			// 终止条件:分组为1
			SubNum = arr.length / ArrNum;
		}

		

		
	}

	/**
	 * 数组数据交换
	 * 
	 * @param arr
	 * @param first
	 * @param second
	 */

	public static void dataSwap(int[] arr, int first, int second)
	{

		int temp;
		temp = arr[first];
		arr[first] = arr[second];
		arr[second] = temp;

	}


}

插入排序版(代码参考了尚硅谷),发现他们的遍历和我一开始思考的先分组组内排序的思想略有差异,他们遍历的方法是按数组依次遍历,每次比较大自己increase的。

同冒泡算法不同的是,插入是寻找自己应该到的位置,其他的位置往后移动。因为冒泡的话每次比较,如果逆序的话,要进行三次赋值。然而插入只需要一次。只在最后一次进行了两次赋值

冒泡的思想是,一次比较,如果顺序反了,咱俩就换换

插入的思想是,前面的都是有序的。一次比较,如果没找到我想要的位置,那你们就往后挪个位置,腾个地方。

实现之

package sort;

import java.util.Arrays;

public class ShellInsertSort
{

	public static void main(String[] args)
	{
		int[] arr =
		{ 5, 3, 1, 2, 6, 4, 8 ,9,10,6,15,3,7};
		shellInsertSort(arr);
		System.out.println(Arrays.toString(arr));
	}

	/**
	 * 
	 * @param arr
	 */
	public static void shellInsertSort(int[] arr)
	{

		for (int increment = arr.length / 2; increment > 0; increment /= 2)
		{
			for (int i = increment; i < arr.length; i++)
			{
				int temp;
				int j;
				// 如果这个是逆序的,那么往前找吧
				if (arr[i] < arr[i - increment])
				{
					temp = arr[i];// 拿出这个值

					// 往前找
					for (j = i - increment; j >= 0 && arr[j] >= temp; j -= increment)
					{
						arr[j + increment] = arr[j];
					}
					arr[j + increment] = temp;// 找到了赋值

				}
			}

		}

	}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值