JAVA基础--6种常用排序算法

各种排序的时间、空间复杂度:


稳定性是指排序中相同的数在排序前后,他们的相对位置不会发生改变。

1.直接插入排序


经常碰到这样一类排序问题:把新的数据插入到已经排好的数据列中。


  1. 将第一个数和第二个数排序,然后构成一个有序序列

  2. 将第三个数插入进去,构成一个新的有序序列。

  3. 对第四个数、第五个数……直到最后一个数,重复第二步。



如何写成代码:


  1. 首先设定插入次数,即循环次数,for(int i=1;i<length;i++),1个数的那次不用插入。

  2. 设定插入数和得到已经排好序列的最后一个数的位数。insertNum和j=i-1。

  3. 从最后一个数开始向前循环,如果插入数小于当前数,就将当前数向后移动一位。

  4. 将当前数放置到空着的位置,即j+1。


代码实现如下:


public class Test {	
	public static void main(String[] args) {
		int[] c = {1,3,5,7,9,8,6,4,2,0};	
		for(int i=1;i<c.length;i++){
			int position = i;
			int current = c[i];
			for(int j=i-1;j>=0;j--){
				//先让一段有序,再依次往后遍历,依次插入。
				if(c[j] > current){
					c[j+1]=c[j];
					position--;
				}
			}
			c[position] = current;
		}		
		//打印排好序列 
		for(int q=0;q<c.length;q++){
			System.out.print(c[q]+" ");
		}
	}	
}

2.希尔排序


对于直接插入排序问题,数据量巨大时。


  1. 将数的个数设为n,取奇数k=n/2,将下标差值为k的书分为一组,构成有序序列。

  2. 再取k=k/2 ,将下标差值为k的书分为一组,构成有序序列。

  3. 重复第二步,直到k=1执行简单插入排序。



如何写成代码:


  1. 首先确定分的组数。

  2. 然后对组中元素进行插入排序。

  3. 然后将length/2,重复1,2步,直到length=0为止。

代码实现如下:
public class Test {	
	public static void main(String[] args) {
		int[] c = {1,3,5,7,9,8,6,4,2,0};
		
		ShellSort(c);
		
		//打印排好序列 
		for(int q=0;q<c.length;q++){
			System.out.print(c[q]+" ");
		}
	}
	
	public static void ShellSort(int[] a){		
		int d = a.length;		
		while(d>0){
			d=d/2;
			for(int x=0;x<d;x++){
				for(int i=x+d;i<a.length;i+=d){
					int j=i-d;
					int current = a[i];
//					while(j>=0 ){
//						if(a[j] > current){
//							a[j+d] = a[j];
//						}
//						j-=d;
//					}
					//此处有两个判断条件,当都满足是才执行。不要写成上面的错误方式。
					for(;j>=0&¤t < a[j];j-=d){
						a[j+d]=a[j];
					}
					a[j+d] = current;
				}
			}
		}
	}	
}

3.简单选择排序


常用于取序列中最大最小的几个数时。


(如果每次比较都交换,那么就是交换排序;如果每次比较完一个循环再交换,就是简单选择排序。)


  1. 遍历整个序列,将最小的数放在最前面。

  2. 遍历剩下的序列,将最小的数放在最前面。

  3. 重复第二步,直到只剩下一个数。




如何写成代码:


  1. 首先确定循环次数,并且记住当前数字和当前位置。

  2. 将当前位置后面所有的数与当前数字进行对比,小数赋值给key,并记住小数的位置。

  3. 比对完成后,将最小的值与第一个数的值交换。

  4. 重复2、3步。


代码实现如下:

public class Test {	
	public static void main(String[] args) {
		int[] c = {1,3,5,7,9,8,6,4,2,0,10};
		int i,j,k;
		//选择排序
		for(i=0;i<c.length-1;i++){
			k=i;
			for(j=i+1;j<c.length;j++){
				if(c[k] > c[j]){
					k=j;
				}
			}
			{int temp = c[i];c[i]= c[k];c[k]=temp;}
		}
		
		for(int q=0;q<c.length;q++){
			System.out.print(c[q]+" ");
		}
	}	
}

4.冒泡排序


一般不用。


  1. 将序列中所有元素两两比较,将最大的放在最后面。

  2. 将剩余序列中所有元素两两比较,将最大的放在最后面。

  3. 重复第二步,直到只剩下一个数。



如何写成代码:


  1. 设置循环次数。

  2. 设置开始比较的位数,和结束的位数。

  3. 两两比较,将最小的放到前面去。

  4. 重复2、3步,直到循环次数完毕。


代码实现如下:

public class Test {
	
	public static void main(String[] args) {
		int[] c = {1,3,5,7,9,8,6,4,2,0,10};
		int i,j;
		//冒泡排序
		for(i=0;i<c.length-1;i++){
			for(j=0;j<c.length-i-1;j++){
				if(c[j]>c[j+1]){
					int temp = c[j];
					c[j] = c[j+1];
					c[j+1] = temp;
				}
			}
		}
		
		for(int q=0;q<c.length;q++){
			System.out.print(c[q]+" ");
		}
	}	
}

5.快速排序


要求时间最快时。


  1. 选择第一个数为p,小于p的数放在左边,大于p的数放在右边。

  2. 递归的将p左边和右边的数都按照第一步进行,直到不能递归。



代码实现如下:
public class Test {
	
	public static void main(String[] args) {
		int[] c = {1,3,5,7,9,8,6,4,2,0};
		QuickSort(c, 0, c.length-1);
		//打印排好序列 
		for(int q=0;q<c.length;q++){
			System.out.print(c[q]+" ");
		}
	}
	
	public static void QuickSort(int[] a,int start,int end){
		if(start < end ){
			int base = a[start];
			int i= start,j=end;
			do{
				while(i < end && a[i] < base)i++;
				while(j > start && a[j] > base)j--;
				if(i<=j){
					int temp = a[i];
					a[i] = a[j];
					a[j] = temp;
					i++;j--;
				}
			}while(i<=j);
			
			if(i< end)
				QuickSort(a,i,end);
			if(j > start)
				QuickSort(a,start,j);
			
		}
	}	
}

6.归并排序


速度仅次于快排,内存少的时候使用,可以进行并行计算的时候使用。


  1. 选择相邻两个数组成一个有序序列。

  2. 选择相邻的两个有序序列组成一个有序序列。

  3. 重复第二步,直到全部组成一个有序序列。




代码实现如下:

public class Test {	
	public static void main(String[] args) {
		int[] c = {1,3,5,7,9,8,6,4,2,0};
		//调用归并排序操作。
		mergeSort2(c, 0, c.length-1);
		//打印排好序列 
		for(int q=0;q<c.length;q++){
			System.out.print(c[q]+" ");
		}
	}	
	public static void mergeSort2(int[] numbers,int start,int end){
		
		if(start < end){
			int mid = (start + end)/2;
			mergeSort2(numbers,start,mid);
			mergeSort2(numbers,mid+1,end);
			merge2(numbers,start,end,mid);
		}
	}
	private static void merge2(int[] numbers, int start, int end, int mid) {
		int i = start,j=mid+1,k=0;
		int[] temp = new int[end+1];
		//两路归并操作。
		while(i<=mid && j<=end){
			if(numbers[i]<=numbers[j]){
				temp[k++]=numbers[i++];
			}else{
				temp[k++]=numbers[j++];
			}
		}
		//如果两个路的长度不一样,将长了的粘在缓存后面。
		while(i<=mid){
			temp[k++] = numbers[i++];
		}
		while(j<=end){
			temp[k++] = numbers[j++];
		}
		//将排好的新数组赋值回原来的数组
		for(i = 0;i<k;i++){
			numbers[start+i]=temp[i];
		}
	}
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值