主要排序算法

排序算法

基本概念:
时间复杂度:对数据操作次数的数量级
空间复杂度:算法所需额外空间的数量级
稳定性:将数据进行排序之后,相同数据的相对位置不发生改变

分类:比较类排序和非比较类排序

比较类算法:通过元素间的两两比较进行排序的算法
  1. 冒泡排序
    最简单的排序算法,进行n轮重复遍历,每一轮进行n次比较选出元素的一个最大/最小值,将剩下元素继续排序,直到剩下一个元素。

    时间复杂度最差情况:O(n2) 最好情况:O(n)
    空间复杂度:O(1),算法稳定性:稳定
    代码:

	public static void bubble(int[] arr){
 		int l = arr.length;
 		for(int i = 0 ; i < l  - 1 ; i++){
 			for(int j = 0 ; j < l - 1 ; j++;){
 				if(a[j] > a[j] + 1){
 					//相邻元素当顺序发生错误时,互换
 					int temp = a[j];
 					a[j] = a[j + 1];
 					a[j + 1] = temp;
 				}
 			}
 		} 
 	} 
  1. 选择排序
    在未排序的元素中选出最小/最大的元素,放在以排序序列的起始/末尾,循环操作直至所有元素已排序

    时间复杂度最差情况:O(n2) 最好情况:O(n2)
    空间复杂度:O(1),算法稳定性:不稳定
    代码:

public static void selectSort(int[] arr) {
    	int l = arr.length;
    	int min;
    	for(int i = 0 ; i < l - 1 ; i++) {
    		min = i;
    		for(int j = i + 1 ; j < l ; j++) {
    			if(arr[j] < arr[min]) {
    				min = j;
    			}
    		}
    		int temp = arr[min];
    		arr[min] = arr[i];
    		arr[i] = temp;
    	}
    }
  1. 插入排序
    在未排序的数组里依次选择一个元素,从后往前,找到已排序数组的对应位置并插入

    时间复杂度最差情况:O(n2) 最好情况:O(n)
    空间复杂度:O(1) 算法稳定性:稳定
    代码:

public static void insertSort(int[] arr) {
		int l = arr.length;
		for(int i = 1 ; i < l ; i++) {
			int j = i - 1 ;
			int p = a[i];
			while(j >= 0 && arr[j] > p) {
				arr[j + 1] = arr[j];
				j--;
			}
			a[j + 1] = p;
		}
	}
  1. 希尔排序
    是插入排序的改进版,先定义一个增量,再按照增量划分子序列,对每一个子序列分别进行插入排序,排完序后再缩小增量值,划分子序列进行重复操作,直至增量为1 ,此时,数组基本有序,然后进行最后一次排序得到有序序列,也叫减小增量排序

    时间复杂度最差情况:O(n2) 最好情况:O(n)
    空间复杂度:O(1) 算法稳定性:不稳定
    代码

public static void shell(int[] arr) {
		int l = arr.length;
		for(int i = l / 2 ; i > 0 ;i = i / 2) {
			for(int j = i ; j < l ; j++) {
				int k = j;
				int p = arr[j];
				while(k - i >= 0 && p < arr[k - i]) {
					arr[k] = arr[k - i];
					k = k - i;
				}
				arr[k] = p;
			}
		}
	}
  1. 快排
    快速排序,顾名思义,就是非常快的排序,也就是时间复杂度会很低,主要思想就是递归,先找到一个基准,将比基准小的都放在基准左边,大的放在右边,再对两边分别进行排序,循环下去,便可达到快速排序的效果
    时间复杂度最差情况:O(n2) 最好情况:O(nlog2n)
    空间复杂度:O(nlog2n) 算法稳定性:不稳定
    代码:
public static void quick(int[] arr , int l , int r) {
		int i = l;
		int j = r;
		int p = arr[i];
		if(l >= r) {
			return;
		}
		while(i < j) {
			while(j > i && arr[j] >= p) {
				j--;
			}
			while(j > i && arr[i] <= p) {
				i++;
			}
			if(i < j) {
				int temp = arr[i];
				arr[i] = arr[j];
				arr[j] = temp;
			}
			
		}
		arr[l] = arr[i];
		arr[i] = p;
		quick(arr , l , i - 1);
		quick(arr , i + 1 , r);
	}
  1. 归并排序
    该排序采用分治的思想,设计的一种排序算法,基本步骤是将子序列排序,然后合并使总的成为一个有序序列
    时间复杂度:最好最差都是:O(nlog2n)
    空间复杂度:O(n) 用ArrayList做辅助空间
    算法稳定性:稳定
    代码
public static int[] sort(int[] arr) {
		int len = arr.length;
		if(len < 2) {
			return arr;
		}
		int mid = len / 2;
		int[] l = Arrays.copyOfRange(arr, 0, mid);
		int[] r = Arrays.copyOfRange(arr, mid, len);
		return merge(sort(l) , sort(r));
	}
	public static int[] merge(int[] l , int[] r) {
		int llen = l.length;
		int rlen = r.length;
		int lnum = 0 ;
		int rnum = 0 ;
		List<Integer> list = new ArrayList<Integer>();
		while(lnum < llen && rnum < rlen) {
			if(l[lnum] < r[rnum]) {
				list.add(l[lnum]);
				lnum++;
			}else {
				list.add(r[rnum]);
				rnum++;
			}
		}
		if(lnum >= llen) {
			for(int i = rnum ; i < rlen ; i++) {
				list.add(r[i]);
			}
		}
		if(rnum >= rlen) {
			for(int i = lnum ; i < llen ; i++) {
				list.add(l[i]);
			}
		}
		int[] result = new int[llen + rlen];
		for(int i = 0 ; i < list.size() ; i++) {
			result[i] = list.get(i);
		}
		return result;
	}
==说明一下:我们经常会用到Arrays.sort方法,该方法在jdk1.7之前底层使用的就是归并算法,而在jdk1.7之后用的是timsort算法,是一种结合了快排,归并和插入的算法==
非比较类算法:不用通过比较进行排序的算法。
  1. 基数排序
    该算法是根据数组元素的各位上的值进行排序的一种算法,需要先取得最大数的位数作为最大位数,然后从每个数字取出最低位,次低位直至最高位,最后对每一位上的数字进行排序
    时间复杂度:最差最好都是O(n * k)
    空间复杂度:O(n + k) 算法稳定性:稳定
    代码:
public static int max(int[] arr) {
		int max = arr[0];
		for(int i : arr) {
			if(max < i) {
				max = i;
			}
		}
		return max;
	}
	public static void radix(int[] arr) {
		int max = max(arr);
		int maxDigit = 0;
		do {
			maxDigit++;
			max /= 10;
		}while(max > 0);
		int n = 1;
		int[][] temp = new int[10][arr.length];
		int[] count = new int[10];
		for(int i = 0 ; i < maxDigit ; i++) {
			for(int j = 0 ; j < arr.length ; j++) {
				int mod = arr[j] / n % 10;
				temp[mod][count[mod]] = arr[j];
				count[mod]++;
			}
			int index = 0;
			for(int k = 0 ; k < 10 ; k++) {
				if(count[k] != 0) {
					for(int l = 0 ; l < count[k] ; l++) {
						arr[index] = temp[k][l];
						index++;
					}
					count[k] = 0;
				}
			}
			n *= 10;
		}
	}
  1. 桶排序
    桶排序是在了解所有元素的一个范围之后,准备和对应数量的桶,使元素在桶中的分布尽量均匀,再将元素按顺序输出,是一种典型的空间换时间方法
    时间复杂度:最差为O(n2),最好是O(n)
    空间复杂度为O(n+k) 算法稳定性:稳定
    代码:
public static int max(int[] arr) {
		int max = arr[0];
		for(int i : arr) {
			if(max < i) {
				max = i;
			}
		}
		return max;
	}
	public static int min(int[] arr) {
		int min = arr[0];
		for(int i : arr) {
			if(min > i) {
				min = i;
			}
		}
		return min;
	}
	public static void bucket(int[] arr) {
		int max = max(arr);
		int min = min(arr);
		int[] buck = new int[max - min + 1];
		for(int i = 0 ; i < arr.length ; i++) {
			buck[arr[i] - min]++;
		}
		int index = 0;
		for(int i = 0 ; i < max - min + 1 ; i++) {
			if(buck[i] != 0) {
				for(int j = 0 ; j < buck[i] ; j++) {
					arr[index] = i + min;
					index++;
				}
			}
		}
	}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值