常见的排序方法(Java)

1.冒泡排序(BubbleSort 稳定 算法复杂度最好O(n) 最坏是O(n2) )

冒泡排序 通过相邻两个数的比较,交换位置,从后往前排

public class BubbleSort {

//对相邻的数进行对比,符合条件就交换位置
	public static int[] BubbleSort( int[] arr) {
		
		for (int i = 0; i <arr.length; i++)
		{
			for (int j = 0; j<arr.length-i-1; j++)
			{	
				if (arr[j] > arr[j + 1])
				{
					int temp;
					temp = arr[j + 1];
					arr[j + 1] = arr[j];
					arr[j] = temp;
				}
			}
		}
		return arr;
	      
	      
	}
	
	public static void printArr(int [] arr){
		for(int num:arr){
			System.out.print(num+"  ");
		}
		
	}
		
	
	       public static void main(String[] args) {
	    	  int [] arr={1,8,6,2,5,4,9,3,7};
	    	  
	    	  printArr(BubbleSort(arr));
	       }
	     }
	     

代码执行过程比较简单。就是重复的交换相邻的数,每轮都有最大的一个数被排在最后,直到排序完成

2.插入排序(InsertSort 稳定 算法复杂度 最好O(n) 最坏O(n2) )

插入排序 在排好序的n个数的数组中,将第n+1个数插入到指定位置,使其变成排好序的n+1个数组,
选取元素插入到指定位置

public class InsertSort {
	public static int [] InsertSort(int [] arr){
		for(int i=1;i<arr.length;i++){
			int j=0;
			//判断是否插入,和插入数值的位置
			if(arr[i]<arr[i - 1]){
				//保留当前数
				int temp=arr[i];  
				//判别之前的数是否比当前值小如果是,将比当前小的数都向后移一个位置,将temp值插入所有比它大的数前面,
				for(j = i - 1 ; j >= 0 && temp < arr[j] ; j--)
				{    //将位置后移一位
					arr[j+1]=arr[j];
					
				}
				//将当前数插入到指定位置
				arr[j+1]=temp;
			}
		}
		return arr;
		
	}
	public static void printArr(int [] arr){
		for(int num:arr){
			System.out.print(num+"  ");
		}
		
	}
	public static void main(String[] args) {
		int [] arr={2,5,6,7,1,4,3,8,9};
		
		printArr(InsertSort(arr));
		
		
	}

}

得到的结果是
代码执行过程
判断1 比前一个小
记录1的值 ,将2,5,6,7后移 arr={2,2,5,6,7,4,3,8,9},再将1插入到2前面 arr={1,2,5,6.7,4,3,8,9}
后面以此类推

3.选择排序(SelectionSort 不稳定 算法复杂度 O(n2))

选择排序 ,将一列数组从中选择最大或最小的数放到起始位置,再从未排序的数中选择最大或最小的排在上个数之后。

public class SelectionSort {
	public static int [] SelectionSort(int [] arr){
		for(int i = 0;i<arr.length;i++){
		//先记录当前位置
			int minIndex=i;
			//比较未排好的数,如果小于记录的值,就记录下位置,如果之后位置的值小于当前位置就交换两者的值,
			for(int j=i;j<arr.length;j++)
			{
				if(arr[j]<arr[minIndex])
				{   
				//每次循环结束都有一个最小的数,
					minIndex=j;
					
				}
			}
			//交换值
			int temp=arr[i]; 
			arr[i]=arr[minIndex];
			arr[minIndex]=temp;
			
		}
		return arr;
		
	}
	public static void printArr(int [] arr){
		for(int num :arr){
			System.out.print(num + " ");
		}
		
	}
	public static void main(String[] args) {
		int [] arr={2,5,6,7,1,4,3,8,9};
		printArr(SelectionSort(arr));
		
	}
}

执行过程
判断1是最小的数 记录1 的索引位置,直接与第一个交换位置
arr={1,5,6,7,2,4,3,8,9}
后面以此类推

4.快速排序(QuickSort 不稳定 算法复杂度O(nlogn) )

//算法复杂度   O(nlogn)
//把所有数值根据基准数分为左右两个部分,左边小于基准数,右边大于基准数,再把左边和右边的部分各自从内部取一个基准数再次排序,以此类推,直到左右两边只有一个数为止即left=right
public class QuickSort2 {

	public static void quickSort(int arr[]){
		//如果数组为0,或者len为0就直接退出
		//定义的长度的量
		int len ;
		if(0==arr.length || 0==(len=arr.length)|| 1==len ){
			return;
		}
		sort(arr,0,len-1);
	}
	private static void sort(int[] arr, int left, int right) {
	//如果开始位置大于结束位置就退出
		if(left>right){
			return;
			
		}
		//定义基准数,最左和最右两个位置
		int base =arr[left];
		int i=left,j=right;
		//left!=right就继续
		while(i!=j){
		//从最右边开始,如果大于基准数,且left<j,获取大于基准数的索引位置
			while(arr[j]>=base&&i<j)
				j--;
				
			}
			//从最左边开始,如果小于基准数,且right>i;获取小于基准数的索引位置
			while(arr[i]<=base&&i<j){
				i++;
			}
			//根据索引位置交换
			if(i<j){
				int temp=arr[i];
				arr[i]=arr[j];
				arr[j]=temp;
			}
		}
		//将基准数插入
		arr[left]=arr[i];
		arr[i]=base;
		//分为两个部分对左右都开始进行快排
		//左边从left开始到基准数索引位置-1结束
		//右边从基准数索引位置+1结束
		sort(arr, left, i-1);
		sort(arr, i+1, right);
		
	}
	public static void printArr(int arr[]){
		for(int num :arr){
			System.out.print(num+" ");
		}
	}
	public static void main(String[] args) {
		int [] arr ={5,2,6,9,1,3,4,8,7};
		quickSort(arr);
		printArr(arr);
	}

}


{5,2,6,9,1,3,4,8,7}
第一次以5为基准 进行交换6,4位置 {5,2,4,9,1,3,6,8,7}
第二次 交换 3,9 位置 {5,2,4,3,1,9,6,8,7}
第三次 将基准数放到中间 交换 1,5位置 {1,2,4,3,5,9,6,8,7}
第四次 将数组分成基准数中间分成左右两个部分,
左边取基准数1,2 都没变化 ,取4 交换 3,4 位置 {1,2,3,4,5,9,6,8,7}

右边 取基数9 交换 7,9 位置 {1,2,3,4,5,7,6,8,9}
取基准数 7 交换 7,6 位置 {1,2,3,4,5,6,7,8,9}
取基准数 8 没变化
取基准数 9 没变化

5.归并排序(MergeSort 稳定 算法复杂度O(nlogn))

先将数组分成两个部分 再将数组分成n个部分再将n个部分进行排序,再将i个部分合并成j个进行排序,最后j个排序后的结果进行比较判别填入数组

public class MergeSort {
	
	private  static void MergeSort(int[] arr, int start , int end) {
		if(start<end){
			int mid = (start+end)/2;
//			start表示从子序列的哪个索引开始,  mid表示子序列中间的位置,  end表示子序列结束的位置
			//将数组分成左右两边进行归并排序
			MergeSort(arr,start,mid);   
			MergeSort(arr,mid+1,end);
			Merge(arr,start,mid,end);
		}
	}
	

		private static void Merge(int[] arr, int start, int mid, int end) {
			int L = mid-start+1;      //左边的长度
			int R = end-mid;			//右边的长度 
			int left [] = new int[L];   //左边的数组
			int right [] = new int[R];  //右边的数组
//			k用来表示当前遍历的数组arr的索引
			int i=0,j=0,k=0;
//			分别给left和right赋值    
//			从左边开始
			for(i=0,k=start; i<n1; i++,k++){
				left [i] = arr[k];
			}
//			从右边开始
			for(j=0,k=mid+1; j<n2; j++,k++){
				right [j] = arr [k];
			}
//			比较大小,从小到大排列
			for(i=0,j=0,k=start ; i<L&&j<R; k++){
				if(left [i] > right [j]){
					arr[k] = right [j];
					j++;
//					逐个比较left和right的大小,如果left[i]的数比right 大就往right下一个查找直到找到大于left[i]的数或right结束为止
//					对比得到最小的值填入arr数组
				}else{
//					将对比得到的小的值填入arr数组
					arr[k] = left [i]; 
					i++;
				}
			}
		
//			将两个数组中剩下的数放到a中
			if(i<L){
				for(j=i; j<n1; j++,k++){
					arr[k] = left [j];
				}
			}
			if(j<R){
				for(i=j; i<n2; i++,k++){
					arr[k] = right [i];
				}
			}
		}
		
	public static void printArr(int [] arr){
		for(int num :arr){
			System.out.print(num+" ");
		}
	}

	public static void main(String[] args) {
		int[]  arr ={5,6,2,3,1,8,9,7,4};
		MergeSort(arr, 0, arr.length-1);
		printArr(arr);
	}
}

代码执行过程:
如下面代码我给出的数组是5,6,2,3,1,8,9,7,4 因为总共9个数字,所以mid=4 左边5个 右边四个,并根据依次往下拆分
第一次 将5 放入left,6 放入right,再将left和right 进行比较 排序,arr={5,6,2,3,1,8,9,7,4}
第二次 将5,6放入 left ,2放入right ,进行比较大小,填入arr= { 2,5,6,3,1,8,9,7,4 }
第三次 将 3放入 left ,1 放入 right ,进行排序 ,arr={ 2,5,6,1,3,8,9,7,4 }
第四次 将 2,5,6 填入left ,1,3 填入right ,比较大小,填入arr= {1,2,3,5,6,8,9,7,4}
第五次 将 8放入 left ,9 放入 right ,比较排序 ,填入arr={1,2,3,5,6,8,9,7,4}
第六次 将 7放入 left ,4放入right,比较排序 ,填入 arr={1,2,3,5,6,8,9,4,7}
第七次 将 8,9 放入 left ,4,7 放入 right ,比较排序 填入 arr={1,2,3,5,6,4,7,8,9}
第八次 将 1,2,3,5,6放入left ,将4,7,8,9放入 right 比较排序填入 arr={1,2,3,4,5,6,7,8,9 }

6.希尔排序(ShellSort 不稳定 升级版的冒泡排序 算法复杂度 O((n)3/2))

没有快速排序快,但是最坏和最好的算法复杂度相差不是很多,跟O(n2)比起来又快了不少

//插入排序的加强版   通过不同的步长,来进行排序  步长为1就是插入排序
//例如 有 7,8,3,9,11,6   六个数   步长为  2  分为7,3,11   8,9,6  
//步长为3  分为  7,9  8,11  3,6  
//根据步长 来调整
public class ShellSort {
	public  static int []  ShellSort(int [] arr){		
		shell(arr, getIncreatment(arr));
		return arr;
	}
	private static void shell(int [] arr ,int ic){
		int i,j,k;
		int len=arr.length;
		for(i=0;i<len;i++ ){
		//分配步长数组
			for(j=i+ic;j<len;j+=ic){
				if(arr[j]<arr[j-ic]){
					int temp =arr[j];
					for(k=j-ic ; k>=0 && temp<arr[k] ; k-=ic){
					//在对应步长内的数组进行插入排序   先将值后移一位,再将记录的值插入
						arr[k+ic]=arr[k];
						
					}
					//插入记录的值
					arr[k+ic]=temp;
					}
				
			}
		}
		
		
	}
	//确定增量increatement   ,可以自己添加 
	public  static int getIncreatment(int arr []){
		int increate=arr.length;
		
		if(increate%2!=0){
			increate=1;
		}else if (0==increate%2) {
			increate=2;
			
		}
		System.out.println("increatement : "+increate);
		return  increate;
	}

	public  static void printArr(int arr[]){
		int count =0;
		for(int num: arr){
			
			System.out.print(num+" ");
			
		}
	}
	
	public static void main(String[] args) {
		int [] arr={2,5,6,7,1,4,3,8,9,10};
		System.out.println("arr.length : "+arr.length);
		printArr(ShellSort(arr));
		
	}
}

当步长是1 的时候相当于插入排序
在这里插入图片描述
当步长是2的时候,分成两个数组 2,6,1,3,9 和5,7,4,8,10 排序后的结果是
1,2,3,6,9 4,5,7,8,10 合并成数组就是 1,4,2,5,3,7,6,8,9,10
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值