希尔排序(解析及代码实现 结合冒泡,选择,二分插入)

希尔排序并非是一种单纯的排序方法,而是一种对其他排序方法进行优化处理
对于冒泡,选择,插入三种排序方法,所用的时间复杂度都是O(n^2)
这对于大量数据来说太慢,希尔排序,排序方法用的是这三类,但降低了n,这使得排序速度大大加快
希尔是将整个数据划分成gap组,分别对这gap组进行排序
一次排序后,虽然整体还是无序的,但在各组是有序的,其整体相对之前较有序
并再对整体划分gap-组,使之整体更加有序,直到gap=1时(实际就是其他排序法)
但是因为数据经过几轮分组排序后,是较为有序的,而对冒泡,选择,插入来说
一个较为有序的序列排序起来比无序 效率要高得多,因此降低了时间

gap一般以二分递减




//希尔分组

public void shellSort(double[] a,int type){
		//希尔优化的分组次数,以gap=a.length/2开始,每次半分
		for (int gap = a.length/2; gap >= 1;gap=gap/2) {
			//开始组内排序
			
			//1冒泡排序
			//bubbleSort(a, type, gap);
			//2选择排序
			//selectSort(a, type, gap);
			//3插入排序
			insertSort(a, type, gap);
			
		}
	}

//希尔-二分插入

private void insertSort(double[] a, int type, int gap) {
		//gap组要插入多少次?
		//对插入来说,一次插一数,整体为一组的话即a.length-1次,但对于分组来说,每一组要冒a.length/gap-1次
		//所以共选(a.length/gap-1)*gap次,及a.length-gap次
		for (int i = 0; i < a.length-gap; i++) {
			//对于每一组组内插入
			//即进行一般的插入即可(二分优化),每一组的第一个数为a[0]~a[gap-1]
			//比较比组内 及:a[j]比a[j+gap],故j+gap<a.length 不能越界并且每选一次,确定一个,使每组前序有序
			double temp=a[i+gap];//对a[i+gap]插排
			int low=i%gap;//该组第一个数下标
			int high=i;//该组最后一个数下标
			int mid;
			while(low<=high){//定位
				mid=i%gap+(low/gap+high/gap)/2*gap;//二分
				if(type==0){
					if(a[mid]>temp)
						high=mid-gap;
					else
						low=mid+gap;
				}else{
					if(a[mid]<temp)
						high=mid-gap;
					else
						low=mid+gap;
				}
			}
			//移动
			for (int k = i; k >= high+gap; k-=gap) {
				a[k+gap]=a[k];
			}
			//插入
			a[high+gap]=temp;
		}
		
	}

//希尔-选择

private void selectSort(double[] a, int type, int gap) {
		//gap组要选择多少次?
		//对选择来说,一次选到一数,整体为一组的话即a.length-1次,但对于分组来说,每一组要冒a.length/gap-1次
		//所以共选(a.length/gap-1)*gap次,及a.length-gap次
		for (int i = 0; i < a.length-gap; i++) {
			//对于每一组组内选择
			//即进行一般的选择即可,每一组的第一个数为a[0]~a[gap-1]
			//比较比组内 及:a[j]比a[j+gap],故j+gap<a.length 不能越界并且每选一次,确定一个,使每组前序有序且比后面都小/大
		    int h=i;
			for (int j = i; j < a.length-gap; j+=gap) {
				if(type==0){
					if(a[h]>a[j+gap]){
						h=j+gap;
					}
				}else{
					if(a[h]<a[j+gap]){
						h=j+gap;
					}
				}
			}
			if(h!=i)
				swap(a, h, i);
		}
	}

//希尔-冒泡

private void bubbleSort(double[] a, int type, int gap) {
		//gap组要冒泡多少次?
		//对冒泡来说,一次冒一泡,整体为一组的话即a.length-1次,但对于分组来说,每一组要冒a.length/gap-1次
		//所以共冒(a.length/gap-1)*gap次,及a.length-gap次
		for (int i = 0; i < a.length-gap; i++) {
			//对于每一组组内冒泡排序
			//即进行一般的冒泡即可
			//每一组的第一个数为a[0]~a[gap-1]
			//比较比组内 及:a[j]比a[j+gap],故j+gap<a.length 不能越界并且每冒一次,确定一个,即每组后序有序且比前面都小/大
			//优化gap==1时
			boolean isSwap=true;
			//只有当1时才false,因为之前若一组有序就跳出,则到gap==1时,还是较无序的,相当于普通冒泡
			if(gap==1)
				isSwap=false;
			for (int j =i%gap; j < a.length-gap-i; j+=gap) {
				if(type==0){
					if(a[j]>a[j+gap]){
						swap(a,j,j+gap);
						isSwap=true;
					}
				}else{
					if(a[j]<a[j+gap]){
						swap(a,j,j+gap);
						isSwap=true;
					}
				}
			}
			if(!isSwap)
				break;
		}
	}

下面代码只是实现重载:

package cn.hncu.sort;

public class ShellSort {
	
//	希尔排序并非是一种单纯的排序方法,而是一种对其他排序方法进行优化处理
//	对于冒泡,选择,插入三种排序方法,所用的时间复杂度都是O(n^2)
//	这对于大量数据来说太慢,希尔排序,排序方法用的是这三类,但降低了n,这使得排序速度大大加快
//	希尔是将整个数据划分成gap组,分别对这gap组进行排序
//	一次排序后,虽然整体还是无序的,但在各组是有序的,其整体相对之前较有序
//	并再对整体划分gap-组,使之整体更加有序,直到gap=1时(实际就是其他排序法)
//	但是因为数据经过几轮分组排序后,是较为有序的,而对冒泡,选择,插入来说
//	一个较为有序的序列排序起来比无序 效率要高得多,因此降低了时间
//	gap一般以二分递减
	public void shellSort(double[] a,int type){
		//希尔优化的分组次数,以gap=a.length/2开始,每次半分
		for (int gap = a.length/2; gap >= 1;gap=gap/2) {
			//开始组内排序
			
			//1冒泡排序
			//bubbleSort(a, type, gap);
			//2选择排序
			//selectSort(a, type, gap);
			//3插入排序
			insertSort(a, type, gap);
			
		}
	}
	private void insertSort(double[] a, int type, int gap) {
		//gap组要插入多少次?
		//对插入来说,一次插一数,整体为一组的话即a.length-1次,但对于分组来说,每一组要冒a.length/gap-1次
		//所以共选(a.length/gap-1)*gap次,及a.length-gap次
		for (int i = 0; i < a.length-gap; i++) {
			//对于每一组组内插入
			//即进行一般的插入即可(二分优化),每一组的第一个数为a[0]~a[gap-1]
			//比较比组内 及:a[j]比a[j+gap],故j+gap<a.length 不能越界并且每选一次,确定一个,使每组前序有序
			double temp=a[i+gap];//对a[i+gap]插排
			int low=i%gap;//该组第一个数下标
			int high=i;//该组最后一个数下标
			int mid;
			while(low<=high){//定位
				mid=i%gap+(low/gap+high/gap)/2*gap;//二分
				if(type==0){
					if(a[mid]>temp)
						high=mid-gap;
					else
						low=mid+gap;
				}else{
					if(a[mid]<temp)
						high=mid-gap;
					else
						low=mid+gap;
				}
			}
			//移动
			for (int k = i; k >= high+gap; k-=gap) {
				a[k+gap]=a[k];
			}
			//插入
			a[high+gap]=temp;
		}
		
	}
	private void selectSort(double[] a, int type, int gap) {
		//gap组要选择多少次?
		//对选择来说,一次选到一数,整体为一组的话即a.length-1次,但对于分组来说,每一组要冒a.length/gap-1次
		//所以共选(a.length/gap-1)*gap次,及a.length-gap次
		for (int i = 0; i < a.length-gap; i++) {
			//对于每一组组内选择
			//即进行一般的选择即可,每一组的第一个数为a[0]~a[gap-1]
			//比较比组内 及:a[j]比a[j+gap],故j+gap<a.length 不能越界并且每选一次,确定一个,使每组前序有序且比后面都小/大
		    int h=i;
			for (int j = i; j < a.length-gap; j+=gap) {
				if(type==0){
					if(a[h]>a[j+gap]){
						h=j+gap;
					}
				}else{
					if(a[h]<a[j+gap]){
						h=j+gap;
					}
				}
			}
			if(h!=i)
				swap(a, h, i);
		}
	}
	private void bubbleSort(double[] a, int type, int gap) {
		//gap组要冒泡多少次?
		//对冒泡来说,一次冒一泡,整体为一组的话即a.length-1次,但对于分组来说,每一组要冒a.length/gap-1次
		//所以共冒(a.length/gap-1)*gap次,及a.length-gap次
		for (int i = 0; i < a.length-gap; i++) {
			//对于每一组组内冒泡排序
			//即进行一般的冒泡即可
			//每一组的第一个数为a[0]~a[gap-1]
			//比较比组内 及:a[j]比a[j+gap],故j+gap<a.length 不能越界并且每冒一次,确定一个,即每组后序有序且比前面都小/大
			//优化gap==1时
			boolean isSwap=true;
			//只有当1时才false,因为之前若一组有序就跳出,则到gap==1时,还是较无序的,相当于普通冒泡
			if(gap==1)
				isSwap=false;
			for (int j =i%gap; j < a.length-gap-i; j+=gap) {
				if(type==0){
					if(a[j]>a[j+gap]){
						swap(a,j,j+gap);
						isSwap=true;
					}
				}else{
					if(a[j]<a[j+gap]){
						swap(a,j,j+gap);
						isSwap=true;
					}
				}
			}
			if(!isSwap)
				break;
		}
	}
	//默认从小到大排
	public void shellSort(double[] a){
		shellSort(a,0);
	}
	//对某一段排序
	public boolean shellSort(double[] a,int first,int end,int type){
		if(first<0)
			return false;
		if(end>=a.length)
			return false;
		if(first>end)
			return false;
		double[] b=new double[end-first+1];
		System.arraycopy(a, first, b, 0, b.length);
		shellSort(b, type);
		for (int i = 0; i < b.length; i++) {
			a[first+i]=b[i];
		}
		return true;
	}
	public boolean shellSort(double[] a,int first,int end){
		return shellSort(a, first, end, 0);
	}
	//float[]数组
	public void shellSort(float[] a,int type){
		double[] b=new double[a.length];
		for (int i = 0; i < b.length; i++) {
			b[i]=a[i];
		}
		shellSort(b, type);
		for (int i = 0; i < b.length; i++) {
			a[i]=(float)b[i];
		}
	}
	public void shellSort(float[] a){
		shellSort(a, 0);
	}
	public boolean shellSort(float[] a,int first,int end,int type){
		if(first<0)
			return false;
		if(end>=a.length)
			return false;
		if(first>end)
			return false;
		float[] b=new float[end-first+1];
		System.arraycopy(a, first, b, 0, b.length);//截取
		shellSort(b, type);//排序
		for (int i = 0; i < b.length; i++) {//放回
			a[first+i]=b[i];
		}
		return true;
	}
	public boolean shellSort(float[] a,int first,int end) {
		return shellSort(a, first, end, 0);
	}
	//long[]数组
	public void shellSort(long[] a,int type){
		double[] b=new double[a.length];
		for (int i = 0; i < b.length; i++) {
			b[i]=a[i];
		}
		shellSort(b, type);
		for (int i = 0; i < b.length; i++) {
			a[i]=(long)b[i];
		}
	}
	public void shellSort(long[] a){
		shellSort(a, 0);
	}
	public boolean shellSort(long[] a,int first,int end,int type){
		if(first<0)
			return false;
		if(end>=a.length)
			return false;
		if(first>end)
			return false;
		long[] b=new long[end-first+1];
		System.arraycopy(a, first, b, 0, b.length);
		shellSort(b, type);
		for (int i = 0; i < b.length; i++) {
			a[first+i]=b[i];
		}
		return true;
	}
	public boolean shellSort(long[] a,int first,int end) {
		return shellSort(a, first, end, 0);
	}
	//int[]数组
	public void shellSort(int[] a,int type){
		double[] b=new double[a.length];
		for (int i = 0; i < b.length; i++) {
			b[i]=a[i];
		}
		shellSort(b, type);
		for (int i = 0; i < b.length; i++) {
			a[i]=(int)b[i];
		}
	}
	public void shellSort(int[] a){
		shellSort(a, 0);
	}
	public boolean shellSort(int[] a,int first,int end,int type){
		if(first<0)
			return false;
		if(end>=a.length)
			return false;
		if(first>end)
			return false;
		int[] b=new int[end-first+1];
		System.arraycopy(a, first, b, 0, b.length);
		shellSort(b, type);
		for (int i = 0; i < b.length; i++) {
			a[first+i]=b[i];
		}
		return true;
	}
	public boolean shellSort(int[] a,int first,int end) {
		return shellSort(a, first, end, 0);
	}
	//short[]数组
	public void shellSort(short[] a,int type){
		double[] b=new double[a.length];
		for (int i = 0; i < b.length; i++) {
			b[i]=a[i];
		}
		shellSort(b, type);
		for (int i = 0; i < b.length; i++) {
			a[i]=(short)b[i];
		}
	}
	public void shellSort(short[] a){
		shellSort(a, 0);
	}
	public boolean shellSort(short[] a,int first,int end,int type){
		if(first<0)
			return false;
		if(end>=a.length)
			return false;
		if(first>end)
			return false;
		short[] b=new short[end-first+1];
		System.arraycopy(a, first, b, 0, b.length);
		shellSort(b, type);
		for (int i = 0; i < b.length; i++) {
			a[first+i]=b[i];
		}
		return true;
	}
	public boolean shellSort(short[] a,int first,int end) {
		return shellSort(a, first, end, 0);
	}
	//byte[]数组
	public void shellSort(byte[] a,int type){
		double[] b=new double[a.length];
		for (int i = 0; i < b.length; i++) {
			b[i]=a[i];
		}
		shellSort(b, type);
		for (int i = 0; i < b.length; i++) {
			a[i]=(byte)b[i];
		}
	}
	public void shellSort(byte[] a){
		shellSort(a, 0);
	}
	public boolean shellSort(byte[] a,int first,int end,int type){
		if(first<0)
			return false;
		if(end>=a.length)
			return false;
		if(first>end)
			return false;
		byte[] b=new byte[end-first+1];
		System.arraycopy(a, first, b, 0, b.length);
		shellSort(b, type);
		for (int i = 0; i < b.length; i++) {
			a[first+i]=b[i];
		}
		return true;
	}
	public boolean shellSort(byte[] a,int first,int end) {
		return shellSort(a, first, end, 0);
	}
	//char[]数组
	public void shellSort(char[] a,int type){
		double[] b=new double[a.length];
		for (int i = 0; i < b.length; i++) {
			b[i]=a[i];
		}
		shellSort(b, type);
		for (int i = 0; i < b.length; i++) {
			a[i]=(char)b[i];
		}
	}
	public void shellSort(char[] a){
		shellSort(a, 0);
	}
	public boolean shellSort(char[] a,int first,int end,int type){
		if(first<0)
			return false;
		if(end>=a.length)
			return false;
		if(first>end)
			return false;
		char[] b=new char[end-first+1];
		System.arraycopy(a, first, b, 0, b.length);
		shellSort(b, type);
		for (int i = 0; i < b.length; i++) {
			a[first+i]=b[i];
		}
		return true;
	}
	public boolean shellSort(char[] a,int first,int end) {
		return shellSort(a, first, end, 0);
	}
	//String[]数组
	public void shellSort(String[] a,int type){
		for (int gap = a.length/2; gap >= 1;gap=gap/2) {
			//开始组内排序
			
			//1冒泡排序
			//bubbleSort(a, type, gap);
			//2选择排序
			//selectSort(a, type, gap);
			//3插入排序
			insertSort(a, type, gap);
			
		}
	}
	private void insertSort(String[] a, int type, int gap) {
		//gap组要插入多少次?
		//对插入来说,一次插一数,整体为一组的话即a.length-1次,但对于分组来说,每一组要冒a.length/gap-1次
		//所以共选(a.length/gap-1)*gap次,及a.length-gap次
		for (int i = 0; i < a.length-gap; i++) {
			//对于每一组组内插入
			//即进行一般的插入即可(二分优化),每一组的第一个数为a[0]~a[gap-1]
			//比较比组内 及:a[j]比a[j+gap],故j+gap<a.length 不能越界并且每选一次,确定一个,使每组前序有序
			String temp=a[i+gap];//对a[i+gap]插排
			int low=i%gap;//该组第一个数下标
			int high=i;//该组最后一个数下标
			int mid;
			while(low<=high){//定位
				mid=i%gap+(low/gap+high/gap)/2*gap;//二分
				if(type==0){
					if(a[mid].compareTo(temp)>0)
						high=mid-gap;
					else
						low=mid+gap;
				}else{
					if(a[mid].compareTo(temp)<0)
						high=mid-gap;
					else
						low=mid+gap;
				}
			}
			//移动
			for (int k = i; k >= high+gap; k-=gap) {
				a[k+gap]=a[k];
			}
			//插入
			a[high+gap]=temp;
		}
		
	}
	//默认从小到大排
	public void shellSort(String[] a){
		shellSort(a, 0);
	}
	//对某一段排序
	public boolean shellSort(String[] a,int first,int end,int type){
		if(first<0)
			return false;
		if(end>=a.length)
			return false;
		if(first>end)
			return false;
		String[] b=new String[end-first+1];
		System.arraycopy(a, first, b, 0, b.length);
		shellSort(b, type);
		for (int i = 0; i < b.length; i++) {
			a[first+i]=b[i];
		}
		return true;
	}
	public boolean shellSort(String[] a,int first,int end) {
		return shellSort(a, first, end, 0);
	}
	//交换
	private void swap(double[] a, int j, int i) {
		//借助第三变量
		double temp=a[i];
		a[i]=a[j];
		a[j]=temp;
		//不借助第三变量
		//1
//				a[i]=a[i]+a[j];
//				a[j]=a[i]-a[j];
//				a[i]=a[i]-a[j];
		//2
//				a[i]=a[i]^a[j];
//				a[j]=a[i]^a[j];
//				a[i]=a[i]^a[j];
		
	}
	private void swap(String[] a, int j, int i) {
		String temp=a[i];
		a[i]=a[j];
		a[j]=temp;
	}
	//输出
	private static void print(String[] a) {
		for (String x : a) {
			System.out.print(x+" ");
		}
		System.out.println();
	}
	private static void print(double[] a) {
		for (double x : a) {
			System.out.print(x+" ");
		}
		System.out.println();
	}
	private static void print(float[] a) {
		for (float x : a) {
			System.out.print(x+" ");
		}
		System.out.println();
	}
	private static void print(long[] a) {
		for (long x : a) {
			System.out.print(x+" ");
		}
		System.out.println();
	}
	private static void print(int[] a) {
		for (int x : a) {
			System.out.print(x+" ");
		}
		System.out.println();
	}
	private static void print(short[] a) {
		for (short x : a) {
			System.out.print(x+" ");
		}
		System.out.println();
	}
	private static void print(byte[] a) {
		for (byte x : a) {
			System.out.print(x+" ");
		}
		System.out.println();
	}
	private static void print(char[] a) {
		for (char x : a) {
			System.out.print(x+" ");
		}
		System.out.println();
	}
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值