八大排序Java实现

前言

在这里插入图片描述

一、交换排序

冒泡排序

冒泡排序
重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。

public class Main {
	 public static void main(String[] args) {
		 int arr[] = {28,6,37,5,9,35,34,7,4};	 
		 for(int i=arr.length-1;i>0;i--){
			 int temp = 0;
			 for(int j=0;j<=i-1;j++){
				 if(arr[j]>arr[j+1])
				 {
					 temp = arr[j];
					 arr[j] = arr[j+1];
					 arr[j+1] = temp;
				 }
			 }
		 }
		 System.out.print(Arrays.toString(arr));
}	 
}

快速排序

1:

public class Main {
	public static void quickSort(int arr[],int low,int high){
		//如果过low>high说明全部排完,则返回
		if(low>high)
			return;
		int l = low ;
		int r = high;
		int temp = arr[low];
		while(l<r){
//注意,必须先遍历与选取分界值想反的方向。比如[7, 6, 4, 5, 9],以左为分界值,先遍历左就会出现错误		
		//先从右遍历,直到右边出现比分界值小的数
			while(arr[r]>=temp&&l<r)
				r--;
		//再从左遍历,知道左边出现比分界值大的数		
			while(arr[l]<=temp&&l<r)
				l++;
		//交换左右遍历中不符合要求的值	
			if(l<r){
				int t = arr[l];
				arr[l] = arr[r];
				arr[r] = t;
			}
		}
		//目前,l和r相同,分界值位置始终没变,将分界值与l和r指向的数交换
		//交换后l和r指向的数就是分界值,分界值左边的数都比它小,右边都比它大
		arr[low]=arr[l];
		arr[l]=temp;
		//再对分界值左边和右边的数组分别进行排序
		quickSort(arr, low, r-1);
		quickSort(arr, r+1, high);	
	}
public static void main(String[] args) {
	 int arr[] = {28,6,37,5,9,35,34,7,4};
	 //传入待排序数组,i和j。默认key(分界值为arr[0])
	 quickSort(arr,0,arr.length-1);
	 System.out.print(Arrays.toString(arr));
 }
 }

二、选择排序

简单选择排序

第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。

public class Main {
    public static void main(String[] args) {
 			int arr[] = {28,6,37,5,9,35,34,7,4};
 		
 			for(int i=0;i<arr.length;i++){
			 int temp = 0;
			 for(int j=i+1;j<arr.length;j++){
				 if(arr[i]>arr[j])
			 	{
					 temp = arr[i];
			 	 	arr[i]=arr[j];
			 	 	arr[j]=temp;
			 	} 
			 }
		 }
		 System.out.print(Arrays.toString(arr));
}	 
}

堆排序

堆排序

利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

public class Main {
	//这里的长度不一定是数组长度,第一次传数组的长度,第二次传之前,最大数已经排到最后,长度就要减1
	public static void heapSort(int x[],int temp,int length){
		//左子树下标
		int left = temp*2+1;
		//记录传入的这一非叶子节点和其左右子树的最小值
		int min = x[temp];
		while(left<length){
			//如果右子树大于左子树,则对右子树操作
			if((left+1)<length&&x[left]<x[left+1])
				left=left+1;
			//如果min 也就是非叶子节点最大,则不需要交换位置,直接返回	
			if(min>=x[left])
				break;
			//x[temp]是非叶子节点,让它等于最大值,而它本身的值已被记录在min里。因为如果刚刚没有break回去,就说明非叶子节点发生变动,而且它的左右子树可能也是非叶子节点,所以要在while中继续交换
			x[temp] = x[left];
			temp = left;
			left = left*2+1;				
		}
		//循环完后,因为while循环最后将x[temp]赋值为x[left],所以将min的值赋给x[temp]
		x[temp] = min;
	}
	
 public static void main(String[] args) {
 		 int arr[] = {28,6,37,5,9,35,34,7,4};	
 		 
 		 //最后一个非叶子结点数组下标为length-2,
 		 for(int i=(arr.length-1-1)/2;i>=0;i--)
			 heapSort(arr,i,arr.length);
		//第一次转换二叉树后,根节点是最大值,将它于最小值交换,然后继续转换二叉树,除已经被放在数组最后的最大值
		 for(int i=arr.length-1;i>=0;i--){
		 int temp = arr[i];
		 arr[i]=arr[0];
		 arr[0] = temp;
		 heapSort(arr, 0,i);
	 }
	 System.out.print(Arrays.toString(arr));
}	
}

三、插入排序

直接插入排序

直接插入排序
基本操作是将一条记录插入到已排好的有序表中,从而得到一个新的、记录数量增1的有序表。

public class Main {
	 public static void main(String[] args) {
 			 int arr[] = {28,6,37,5,9,35,34,7,4};	
 		 
			 for(int i=0;i<arr.length-1;i++){
			 	//value代表要插入的值,从数组第二个开始,开始只有一个数,不需要比较排序
				 int value = arr[i+1];
				//j定义到外面,因为j的for循环结束后还要根据j来赋value值
				 int j;
				 for(j=i;j>=0&&value<arr[j];j--)
				 //i之前的数都是排好序的,所以从i开始向前比较,如果value即待插入值大于已经排好的数的最大值,
				 //那么就不用进for循环,直接赋值到排好的数后面,如果小于,则找到比value小的数,也就是找到value
				 //要插入已经排好序的数组的哪个位置位置,将找到的位置之后已经排好序的数整体后移
					 arr[j+1]=arr[j];
				//将value插入for循环找到的位置	 
				 arr[j+1]=value;
			 }
			 System.out.print(Arrays.toString(arr));
}	
}

希尔排序

希尔排序

public class Main {
	 public static void main(String[] args) {
 			 int arr[] = {28,6,37,5,9,35,34,7,4};	
 		 //增量gap每次小一半
			 for(int step = arr.length/2;step>0;step=step/2){
			 //因为i每次都会增加,所以从每个分组的第二个开始与同组前一个比
			 for(int i=step;i<arr.length;i++){
				 int value = arr[i];
				 int j;
				 //因为i每次加1,所以是从下标为step的数开始,对它所在的组中下标在它前面的数进行排序
				 for(j=i-step;j>=0&&value<arr[j];j=j-step){
					 arr[j+step] = arr[j];
				 }
				 arr[j+step]=value;
			 }
		 }
		 System.out.print(Arrays.toString(arr));
}	
}

四、归并排序

归并排序
算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。”

public class Main {
//该方法是先将数组分组
	public static int[] merge(int arr[]){
	//如果传来的数组长度小于2,说明只有1个数,不需要分,直接返回
			if(arr.length<2)
				return arr;
			//长度不小于2,则继续平分
			int mid  = arr.length/2;
			//继续平分直到不能再分
			int left[] = merge(Arrays.copyOfRange(arr, 0, mid));
			int right[] = merge(Arrays.copyOfRange(arr, mid, arr.length));
		return mergeSort(left,right);
		}
	public static int[] mergeSort(int left[],int right[]){
		//传入的左右俩数组都已排好序,比较这俩数组,然后排好序放到result数组
			int result[] = new int[left.length+right.length];
			for(int index = 0,i = 0,j = 0;index<result.length;index++){
				if(i>=left.length)
						result[index] = right[j++];
					else if(j>=right.length)
				result[index] = left[i++];
				else if(left[i]>right[j])
					result[index] = right[j++];
			else 
					result[index] = left[i++];
			}
			return result;
	}
 public static void main(String[] args) {
 		 int arr[] = {28,6,37,5,9,35,34,7,4};	
 		System.out.println(Arrays.toString(merge(arr)));
}	
}

四、基数排序

基数排序透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序,其时间复杂度为O (nlog®m),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的稳定性排序法。”

public class Main {
	public static void radixSort(int arr[]){
			int result[] = new int[arr.length];
			//num中存放检查数组中每个数的个或十位数出现的数的次数
			int num[] = new int[10];
			int N = 0;
			int max = arr[0];
			//找到数组中的最大值
			for(int i=1;i<arr.length;i++){
				if(arr[i]>max)
					max=arr[i];
			}
			//找到最大值有几位数
			while(max!=0){
				N++;
				max/=10;
			}
			for(int i=0;i<N;i++)
			{
				//division是求哪一位数的钥匙,比如第二次循环是求数的十位数,division就等于2,求十位数就是数/10再求余
				int division = (int)Math.pow(10, i); 
				for(int j=0;j<arr.length;j++){
					//把当前循环要求的位数(值各位个位十位)在数组中出现的次数存储下来
					num[arr[j]/division%10]++;
				}
				//下面俩个for循环是计数排序思想,自行百度,循环后就按照个人或十位的大小排序
				for(int j = 1;j<num.length;j++)
					num[j]=num[j]+num[j-1];
				for(int j = arr.length-1;j>=0;j--){
					int t = arr[j]/division%10;
					result[--num[t]]=arr[j];
				}
				//将arr数组从0到length复制给result,从result数组的0开始
					System.arraycopy(result, 0, arr, 0, arr.length);
					//将num数值归0
					Arrays.fill(num, 0);
			}
			
		}
 public static void main(String[] args) {
 		 int arr[] = {28,6,37,5,9,35,34,7,4};	
 		 radixSort(arr);
 		 System.out.print(Arrays.toString(arr));
}	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值