常见的排序算法的复习(java)

1冒泡排序

1.冒泡排序是稳定的排序之一
2.平均时间复杂度是 n²
3.空间复杂度是O(1)
4.实现
从左到右依次两两交换 找出最大或最小

5.代码

import java.util.Arrays;

public class BubbleSort {

	public static void main(String[] args) {
		int[]a=new int[] {5,15,17,10,1,4};
		for(int i=0;i<a.length;i++) {
		//J<a.length-1 是因为两两交换 最后一个没有可交换的伙伴
		//减i是因为优化算法 每一次循环都会确定最后一个数字是(最大或最小)
			for(int j=0;j<a.length-i-1;j++) {
				if(a[j]>a[j+1]) {
				//找到后两两交换
					int t=a[j+1];
					a[j+1]=a[j];
					a[j]=t;
				}
			}
		}
		System.out.println(Arrays.toString(a));
		
	}

}

2选择排序

1.选择排序是不稳定的
2.平均时间复杂度是n²
3.空间复杂度是O(1)
4.实现
每次循环都找到最大(或最小)的数放到前面
5.代码

import java.util.Arrays;

public class SelectSort {

	public static void main(String[] args) {
		int[]a=new int[] {5,15,17,10,1,4};
		for(int i=0;i<a.length;i++) {
			int min=a[i];
			int index=i;
			//这个循环用来找到最值和下标
			//j=i+1 每一次循环找到该放到第i个位置的数字
			//所以i之前的已经确定
			for(int j=i+1;j<a.length;j++) {
				if(a[j]<min) {
					min=a[j];
					index=j;
				}
			}
			//交换
			if(index!=i) {
				int t=a[i];
				a[i]=min;
				a[index]=t;
			}
		}
		System.out.println(Arrays.toString(a));
	}

}

3插入排序

1.这个算法我认为比前两个理解多了一些困难 要自己推一遍过程

2.插入排序是稳定的
3.平均时间复杂度是n²
4.空间复杂度是O(1)
5.实现
相当于把数组分为两段 前面为有序 后面无序
当数组就一个数字时 无论怎样都是有序的
当大于1时 就开始从第二个开始
找第二个插入的合适位置
以此类推…
6.代码

import java.util.Arrays;

public class InsertSort {

	public static void main(String[] args) {
		int[]a=new int[] {5,15,17,10,-1,4};
			//类似选择也是把数组分为两部分
		//一部分是排好的 一部分是没有的
		int insertIndex;
		int insertValue;
		//默认第一个是有序的 所以每次从第二个开始
		for(int i=1;i<a.length;i++) {
			//i-1的意思是  
			//当要判断第i个插在哪里时要从第i-1开始往前判断
			insertIndex=i-1;
			insertValue=a[i];
			//下标不能越界所以>=0
			//a[insertIndex]这个就是要判断的前一个值
			while(insertIndex>=0&&a[insertIndex]>insertValue) {
				
				a[insertIndex+1]=a[insertIndex];
				insertIndex--;
			}
			//加1是因为判断不是前一个吗 
			//所以当找到的时候 insertIndex是这个插入数的前一个下标
			
			if(insertIndex + 1 != i) {
				a[insertIndex + 1] = insertValue;
			}
		}
		System.out.println(Arrays.toString(a));
	}

}

4希尔排序

1.希尔排序是不稳定的
2.平均时间复杂度 nlog2n
3.空间复杂度O(1)
4.实现
希尔排序是把记录按下表的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。

0.1 交换法实现
相当于冒泡排序(速度慢)

public class ShellSort {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[]a=new int[] {5,15,0,10,1,4,3,8,18,17};//10个数据
		int temp;
		//希尔排序每次分组都是除2 
		//i=a.length/2 也是步长
		for(int i=a.length/2;i>0;i/=2) {//代表总循环次数
		//下面两个for相当于冒泡排序
			for(int j=i;j<a.length;j++) {
				//k=j-i保证每次循环从0开始
				//由于j在增加所以k也再变大一直到倒数第2个
				//为什么是倒数第二个 因为比较的时候是与他后一个比
				//这也是下面>a[k+i]的原因
				//k-i的意思 是用来找分过组之后的所有组员
				for(int k=j-i;k>=0;k=k-i) {
					
					if(a[k]>a[k+i]) {
						temp=a[k];
						a[k]=a[k+i];
						a[k+i]=temp;
					}
				}
			}
		}
		System.out.println(Arrays.toString(a));
	}

}


0.2位移法
相当于插入排序

import java.util.Arrays;

public class ShellSort {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[]a=new int[] {5,15,0,10,1,77,3,8,18,17,14};//11个数据
		
		//希尔排序每次分组都是除2 最后一组是长度是a.lenrth
		//i=a.length/2 也是步长
		for(int i=a.length/2;i>0;i/=2) {//代表总循环次数
				for(int j=i;j<a.length;j++) {
					int index=j;
					int value=a[index];
					//a[index-i]是他这组的前一个数字
					if(value<a[index-i]) {
					//插入排序思想
						while(index-i>=0&&value< a[index - i]) {
							a[index]=a[index-i];
							index-=i;
						}
						a[index]=value;
					}
					
				}
			
				}
		
		System.out.println(Arrays.toString(a));
		
				
			}
			
		}
		
	

5快速排序

1.快速排序是不稳定的
2.平均时间复杂度 nlog2n
3. 空间复杂度O(logn)
4. 最佳情况:T(n) = O(nlogn) 最差情况:T(n) = O(n2) 平均情况:T(n) = O(nlogn)
5. 实现
6.大佬的描述更好 点击访问
7.具体原理看一下上面的链接

 
import java.util.Arrays;

public class QuickSort {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[]a=new int[] {6,1,2,7,9 ,3,4,5,10,8};
	sort(a,0,a.length-1);
	System.out.println(Arrays.toString(a));
	}
	public static void sort(int[]a,int left,int right) {
		int l=left;
		int r=right;
		/一定要先判断 这是递归终止的条件
		if(r<l) {
			return;
		}
		int v=a[left];
		//此处设置基准为最左边的数
		//所以要最右边先开始扫描
		while(l<r) {
			//必须从右边先开始
			//必须加上l<r
			//***解释:  例如 1 2 3 4 数组
			//当先从左开始时 l会在0处挺 r会在3处  所以一交换就错了
			//而先从右边开始 r会在0处  l也在0  所以不一影响***   
			while(a[r]>=v&&l<r) {
				r--;
			}
			while(a[l]<=v&&l<r) {
				l++;
			}
			//交换
			if(l<r) {
				int temp=a[r];
				a[r]=a[l];
				a[l]=temp;
			}
		}
		//最后把基准和中间交换
		//上面while退出条件为l=r
		a[left]=a[l];
		a[l]=v;
		//分别向左向右递归
		sort(a, left, r-1);
		sort(a,l+1,right);
		
		
	}
}

6归并排序

1.快速排序是稳定的
2.平均时间复杂度 nlog2n
3.空间复杂度O(logn)
4.归并排序 实现
把长度为n的输入序列分成两个长度为n/2的子序列;
对这两个子序列分别采用归并排序;
将两个排序好的子序列合并成一个最终的排序序列
5.代码

import java.util.Arrays;

public class MergetSort {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int a[] = { 8, 4, 5, 7, 1, 3, 6, 2 };
		int[] temp=new int[a.length];
		sort(a, 0, a.length-1, temp);
		System.out.println(Arrays.toString(a));
		
	}
   //第二步写分+和
	public static void sort(int[]a,int start,int end,int[]temp) {
		if(start<end) {
			int mid=(start+end)/2;
			sort(a, start, mid, temp);
			sort(a, mid+1, end, temp);
			fen(a, start, mid, end, temp);
		}
		
	}
	
	//先写归并排序的和
	public static void fen(int[]a,int start,int mid,int end,int[]temp) {
		int i=start;
		int j=mid+1;
		//t是temp数组的下标
		int t=0;
		while(i<=mid&&j<=end) {
			if(a[i]<=a[j]) {
				temp[t]=a[i];
				i++;
				t++;
			}else {
				temp[t]=a[j];
				t++;
				j++;
			}
		}
		//当while循环退出时可能有一边有剩余
		while(i<=mid) {
			temp[t]=a[i];
			t++;
			i++;
		}
		while(j<=end) {
			temp[t]=a[j];
			j++;
			t++;
		}
		//讲temp中拷贝到原数组中
		//注意此时temp的长度不是整个     而是分的长度
		//这个长度是 start到end
		t=0;
		int tempt=start;
		while(tempt<=end) {
			a[tempt]=temp[t];
			t++;
			tempt++;
		}
		
	}
	
}

7基数排序

1.基数排序是稳定的
2.平均时间复杂度是nk
3.空间复杂度是n
k
4.实现
取得数组中的最大数,并取得位数;
arr为原始数组,从最低位开始取每个位组成radix数组;
对radix进行计数排序(利用计数排序适用于小范围数的特点)
5.代码
6.此排序虽然比较好理解 但是有很多的不足之处

import java.util.Arrays;

public class RadixSort {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int a[] = { 53, 3, 542, 748, 14, 214};
		radixSort(a);
		System.out.println(Arrays.toString(a));
	}
	public static void radixSort(int[]a) {
		//先求出最大数的位数
		int max=a[0];
		for(int i=1;i<a.length;i++) {
			max=Math.max(max,a[i]);
		}
		int wei=(max+"").length();
		//a.length也是基数排序消耗额外空间的原因
		int[][]bucket=new int[10][a.length];
		//每个桶的下标
		int[]bucketwei=new int[10];
		//最大位数也是大循环的次数
		int t=1;
		//aa是原数组的下标;
		
		for(int i=0;i<wei;i++) {
			int aa=0;
			for(int j=0;j<a.length;j++) {
				int zy=(a[j]/t)%10;
				bucket[zy][bucketwei[zy]]=a[j];
				bucketwei[zy]++;
			}
			//把桶中数据放回
			for(int j=0;j<10;j++) {
				if(bucketwei[j]!=0) {
					for(int k=0;k<bucketwei[j];k++) {
						a[aa]=bucket[j][k];
						aa++;
					}
				}
				bucketwei[j]=0;
			}
			
			//此处不要忘了t*10
			t=t*10;
			
		}
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值