简单排序2

1.希尔排序

 原理:1.选定一个增长量h,按照增长量h作为数据分组的依据,对数据进行分组;

            2.对分好组的每一组数据完成插入排序;

            3.减小增长量,最小减为1,重复第二步操作

           

 代码实现:

public class Shell {

	public static void sort(Comparable[] a) {
		int h=1;
//		确定增常量的最大值
		while(h<a.length/2) {
			h=h*2+1;
		}
		while(h>=1) {
			for(int i=h;i<a.length;i++) {
				for(int j=i;j>=h;j-=h) {
					if(greater(a[j-h],a[j])) {
						exch(a,j-h,j);
					}
					else {
						break;
					}
				}
			}
			h=h/2;
		}
	}
	public static boolean greater(Comparable v,Comparable w) {
		return v.compareTo(w)>0;
	}
	public static void exch(Comparable[] a,int i,int j) {
		Comparable tem;
		tem=a[i];
		a[i]=a[j];
		a[j]=tem;
	}
希尔排序的时间复杂度为O(n*log2n)

2.归并排序

原理:

1.尽可能的一组数据拆分成两个元素相等的子组,并对每一个子组继续拆分,直到拆分后的每个子组的元素个数是 1为止。

2.将相邻的两个子组进行合并成一个有序的大组;

3.不断的重复步骤2,直到最终只有一个组为止。

代码实现:

public class Merge {
	private static Comparable[] assist;
	
	
	public static boolean less(Comparable v,Comparable w) {
		return v.compareTo(w)<0;
	}
	public static void exch(Comparable[] a,int i,int j) {
		Comparable tem=a[i];
		a[i]=a[j];
		a[j]=tem;
	}
	public static void sort(Comparable[] a) {
		assist=new Comparable[a.length];//临时数组,用来储存按指定要求排好后的次序的数组
		int lo=0;
		int hi=a.length-1;
		sort(a,lo,hi);
	}
	public static void sort(Comparable[] a,int lo,int hi) {
		if(hi<=lo) {
			return;
		}
		int mid=lo+(hi-lo)/2;
//		递归调用
		sort(a,lo,mid);
		sort(a,mid+1,hi);
		merge(a,lo,mid,hi);
	}
	public static void merge(Comparable[] a,int lo,int mid,int hi) {
		int i=lo;
		int p1=lo;//左指针:用来记录左半数组遍历的位置
		int p2=mid+1;//右指针:用来记录右半数组遍历的位置
		while(p1<=mid&&p2<=hi) {
			if(less(a[p1],a[p2])) {
				assist[i++]=a[p1++];
			}else {
				assist[i++]=a[p2++];
			}
		}
//		当p2走完右半部分时,将左半部分的剩余的值,直接放到临时数组里面
		while(p1<=mid) {
			assist[i++]=a[p1++];
		}
//		当p1走完左半部分时,将右半部分的剩余的值,直接放到临时数组里面
		while(p2<=hi) {
			assist[i++]=a[p2++];
		}
		for(int index=lo;index<=hi;index++) {
			a[index]=assist[index];
		}
		
	}

 归并排序的时间复杂度为O(n*log2n)

3.快速排序

原理:

1.首先设定一个分界值,通过该分界值将数组分成左右两部分;

2.将大于或等于分界值的数据放到到数组右边,小于分界值的数据放到数组的左边。此时左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值;

3. 然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两 部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
4. 重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当 左侧和右侧两个部分的数据排完序后,整个数组的排序也就完成了。

代码实现:

public class Quick {
	private static boolean less(Comparable v,Comparable w) {
		return v.compareTo(w)<0;
	}
	public static void exch(Comparable[] a,int i,int j) {
		Comparable tem=a[i];
		a[i]=a[j];
		a[j]=tem;
	} 
	public static void sort(Comparable[] a) {
		int lo=0;
		int hi=a.length-1;
		sort(a,lo,hi);
	}
	public static void sort(Comparable[] a,int lo,int hi) {
		if(hi<=lo) {
			return;
		}
		int partition=paratition(a, lo,hi);
		sort(a,lo,partition-1);
		sort(a,partition+1,hi);
	}
	public static int paratition(Comparable[] a,int lo,int hi) {
		Comparable key=a[lo];
		int left=lo;
		int right=hi+1;
		while(true) {
			//先从右往左扫描,找到一个比基准值小的元素
			while(less(key,a[--right])) {
				if(right==lo) {
					break;
				}
			}
			//先从左往右扫描,找到一个比基准值大的元素
			while(less(a[++left],key)) {
				if(left==hi) {
					break;
				}
			}
//			扫描完所有的元素,结束循环
			if(left>=right) {
				break;
			}else {
				exch(a,left,right);
			}
		}
		//交换最后rigth索引处和基准值所在的索引处的值
		exch(a,lo,right);
		return right;//right就是切分的界限
	}
}

快速排序平均情况的时间复杂度为O(n*longn) ,最差的时间复杂度为O(n^2)。

基数排序:

注意:基数排序和其它排序有所不同,它只能对数字(整数)进行排序

public class RadixSort {
    //交换元素
    private static void swap(int[] arr,int i,int j){
        int tem=arr[i];
        arr[i]=arr[j];
        arr[j]=tem;
    }
    //向数组中添加元素
    private static int []arrAppend(int[] arr,int x){
        arr= Arrays.copyOf(arr,arr.length+1);
        arr[arr.length-1]=x;
        return arr;
    }
//复制一个新数组
   private static int[] copy(int[] arr){
        int[] tmp=new int[arr.length];
        System.arraycopy(arr,0,tmp,0,arr.length);
        return tmp;
    }
//得到数组中最大值的长度
   private static int getMaxDigit(int[] arr){
        int max=0;
        for (int i = 0; i < arr.length; i++) {
            max=Math.max(max,arr[i]);
        }
        int x=max;
        int ans=0;
        if(x==0){
            return ans;
        }
        while(x>0){
            ans++;
            x=x/10;
        }
        return ans;
    }
    //排序
    public static void sort(int[] arr){
        int maxDigit=getMaxDigit(arr);
        int mod=10;
        int div=1;
        for(int i=0;i<maxDigit;++i,mod*=10,div*=10){
            int[][] tmp=new int[10][0];
            for (int j = 0; j < arr.length; j++) {
                int bucket=arr[j]%mod/div;
                tmp[bucket]=arrAppend(tmp[bucket],arr[j]);
            }
            int index=0;
            for(int[] k:tmp){
                for(int value:k){
                    arr[index++]=value;
                }
            }
        }
    }
}

基数排序时间复杂度:O(n)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Luck&Strive

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值