八大排序之希尔排序

目录

希尔排序:

 希尔排序是插入排序的更高效版本

 希尔排序示意图:

​ 交换法:(效率低)

一步步演示

效果:

合并:

测试效率:

移位法:

效率:

 结论:移动法的效率远高于交换法


希尔排序:

 希尔排序是插入排序的更高效版本

 希尔排序示意图:

 交换法:(效率低)

一步步演示

public class ShellSort {
	public static void main(String[] args) {
		int[] arr = {8,9,1,7,2,3,5,4,6,0};
		System.out.println("原始数组:");
		System.out.println(Arrays.toString(arr));
		//分步骤
		shellSort(arr);

	}
	// 使用逐步推到的方式编写希尔排序(交换法)
	public static void shellSort(int[] arr){
		// 希尔数组的第一轮排序
		// 因为第一轮排序 将10个数据分成10/2=5组
		int temp = 0;
		for (int i = 5; i < arr.length; i++){
			// 遍历各组中 所有的元素(共五组,每组2个元素) 步场为5 如第一个数字和第5个数字比较
		for(int j = i - 5; j >= 0; j -= 5){
				// 如果当前的元素大于加上步长的元素,说明交换
		if (arr[j] > arr[j + 5]) {
			temp = arr[j];
			arr[j] = arr[j + 5];
			arr[j + 5] = temp;
		}
	}
}
	System.out.println("希尔数组的第一轮排序后");
	System.out.println(Arrays.toString(arr));

	// 希尔数组的第二轮排序
	// 因为第二轮排序 将10个数据分成5/2=2组
	for (int i = 2; i < arr.length; i++){
		for(int j = i - 2; j >= 0; j -= 2){
		if (arr[j] > arr[j + 2]) {
			temp = arr[j];
			arr[j] = arr[j + 2];
				arr[j + 2] = temp;
			}
		}
	}
		System.out.println("希尔数组的第2轮排序后");
		System.out.println(Arrays.toString(arr));

		// 希尔数组的第三轮排序
		// 因为第三轮排序 将10个数据分成2/2=1组
		for (int i = 1; i < arr.length; i++){
		for(int j = i - 1; j >= 0; j -= 1){
			if (arr[j] > arr[j + 1]) {
				temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
	    }
	}
		System.out.println("希尔数组的第3轮排序后");
		System.out.println(Arrays.toString(arr));

	}
}

效果:

合并:


	public static void shellSort(int[] arr) {
		// 希尔数组的第一轮排序
		// 因为第一轮排序 将10个数据分成10/2=5组
		int temp = 0;
		for (int gap = arr.length / 2; gap > 0; gap /= 2) {
			for (int i = gap; i < arr.length; i++) {
			// 遍历各组中 所有的元素(共五组,每组2个元素) 步场为5 如第一个数字和第5个数字比较
			for (int j = i - gap; j >= 0; j -= gap) {
					// 如果当前的元素大于加上步长的元素,说明交换
			  if (arr[j] > arr[j + gap]) {
				temp = arr[j];
				arr[j] = arr[j + gap];
				arr[j + gap] = temp;
				}
			}
	    }
	}

}


测试效率:

public class ShellSort {
	public static void main(String[] args) {
		int arr[]=new int[80000];
		for (int i=0;i<80000;i++){
			arr[i]=(int) (Math.random()*8000000);
		}
		Date date1 = new Date();
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String date1Str = simpleDateFormat.format(date1);
		System.out.println("排序前的时间是="+date1Str);
		//测试冒泡排序的性能
		shellSort(arr);
		Date date2 = new Date();
		String date2Str = simpleDateFormat.format(date2);
		System.out.println("排序后的时间是="+date2Str);


	}
	// 使用逐步推到的方式编写希尔排序(交换法)
	public static void shellSort(int[] arr) {
		// 希尔数组的第一轮排序
		// 因为第一轮排序 将10个数据分成10/2=5组
		int temp = 0;
		for (int gap = arr.length / 2; gap > 0; gap /= 2) {
			for (int i = gap; i < arr.length; i++) {
		// 遍历各组中 所有的元素(共五组,每组2个元素) 步场为5 如第一个数字和第5个数字比较
				for (int j = i - gap; j >= 0; j -= gap) {
					// 如果当前的元素大于加上步长的元素,说明交换
					if (arr[j] > arr[j + gap]) {
						temp = arr[j];
						arr[j] = arr[j + gap];
						arr[j + gap] = temp;
					}
				}
			}
		}

	}
}

发现比插入排序效率低很多。而希尔排序本身就是用来优化插入排序的,那么上面的希尔排序将没有意义!!!所以改进一下(移位法)

移位法:

public class ShellSort {
	public static void main(String[] args) {
		int arr[]=new int[80000];
		for (int i=0;i<80000;i++){
			arr[i]=(int) (Math.random()*8000000);
		}
		Date date1 = new Date();
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String date1Str = simpleDateFormat.format(date1);
		System.out.println("排序前的时间是="+date1Str);
		//测试冒泡排序的性能
		shellSort2(arr);
		Date date2 = new Date();
		String date2Str = simpleDateFormat.format(date2);
		System.out.println("排序后的时间是="+date2Str);


	}


	//移位法
	public static void shellSort2(int[] arr) {

		//增量gap,并且逐步缩小增量
		for (int gap = arr.length / 2; gap > 0; gap /= 2) {
			//从第gap个元素,逐个对其所在的组进行直接插入排序
			for (int i = gap; i < arr.length; i++) {
		    	int j=i;
				int temp=arr[j];
				if (arr[j]<arr[j-gap]){
				while (j-gap>=0&&temp<arr[j-gap]){
					      //移动
			        	arr[j]=arr[j-gap];
						j-=gap;
					}
					//当退出while后,就给temp找到插入位置
					arr[j]=temp;
				}
			}
		}

	}


}

效率:

 结论:移动法的效率远高于交换法

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值