选择、插入、冒泡、归并、快速排序

今天复习了一下排序算法,总结一下今天自己写的代码。
原理可能只是简单介绍一下,如果原理不太懂的小伙伴还是去理解一下原理,不然可能看不懂算法。

选择排序

package com.chenli.sort;

import java.util.Arrays;

/**
 * 选择排序
 * 首先,找到数组中最小的那个元素,其次,将它和数组的第一个元素交换位置(如果第一个元素就是最小元素那么它就和自己交换)。
 * 其次,在剩下的元素中找到最小的元素,将它与数组的第二个元素交换位置。如此往复,直到将整个数组排序
 * 
 * 时间复杂度:O(n的平方) 
 * @author chenli
 *
 */
public class SelectSort {
	
	public static int[] selectSort(int[]arr){
		if(arr == null || arr.length < 2){
			return arr;
		}
		int n = arr.length;
		//从无序区间挑选最小的数,挑选n-1次,最后一个元素不用挑
		for(int i=0;i<n-1;i++){
			int min = i;
			//i下标左边是已经排好序的,i下标右边还是无序,所以从i+1开始
			for(int j=i+1;j<n;j++){
				if(arr[j]<arr[min]){
					min = j;
				}
			}
			int temp = arr[i];
			arr[i] = arr[min];
			arr[min]= temp;
		}
		return arr;
	}

	public static void main(String[] args) {
		
		int[]arr = {4,5,9,7,6,3,2,1,8};
		System.out.println(Arrays.toString(arr));
		arr = selectSort(arr);
		System.out.println(Arrays.toString(arr));

	}

}

运行结果
选择排序
插入排序

package com.chenli.sort;

import java.util.Arrays;

/**
 * 插入排序
 * 1、从数组第2个元素开始抽取元素。
 * 2、把它与左边第一个元素比较,如果左边第一个元素比它大,则继续与左边第二个元素比较下去,直到遇到不比它大的元素,然后插到这个元素的右边。
 * 3、继续选取第3,4,….n个元素,重复步骤 2 ,选择适当的位置插入。
 * 
 * 时间复杂度:O(n的平方)
 * 
 * 适用场景:小规模数据数据或者基本有序
 * @author chenli
 *
 */
public class InsertSort {

	public static int[] insertSort(int[]arr){
		if(arr==null||arr.length<2){
			return arr;
		}
		int n = arr.length;
		//默认第一元素(下标为0)排好序,所下标从1开始
		for(int i=1;i<n;i++){
			//定义一个临时变量把待插入元素存储起来
			int temp = arr[i];
			//待插入元素和左边第一个开始比较
			int k = i-1;
			//如果k>=0并且arr[k]的值大于待插入的值,说明此处不是他插入的位置,
			//待插入值将继续和左边的值比较
			while(k>=0 && arr[k]>temp){
				k--;
			}
			//运行到此步说明找到了待插入元素的位置,需要为它腾出插入空间
			for(int j=i;j>k+1;j--){
				arr[j] = arr[j-1];
			}
			//arr[k]是小于待插入值的,所以待插入值放在它的右边
			arr[k+1] = temp;
		}
		return arr;
	}
	
	public static void main(String[] args) {
		
		int[]arr = {4,5,9,7,6,3,2,1,8};
		System.out.println(Arrays.toString(arr));
		arr = insertSort(arr);
		System.out.println(Arrays.toString(arr));
	}

}

运行结果
插入排序
冒泡排序

package com.chenli.sort;

import java.util.Arrays;
/**
 * 冒泡排序
 * 
 * 把第一个元素与第二个元素比较,如果第一个比第二个大,则交换他们的位置。
 * 接着继续比较第二个与第三个元素,如果第二个比第三个大,则交换他们的位置….
 * 我们对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样一趟比较交换下来之后,
 * 排在最右的元素就会是最大的数。除去最右的元素,我们对剩余的元素做同样的工作,如此重复下去,直到排序完成。
 * 
 * 时间复杂度:O(n的平方)
 * @author chenli
 *
 */
public class BubbleSort {

	public static int[] bubbleSort(int[]arr){
		
		if(arr == null || arr.length<2){
			return arr;
		}
		int n = arr.length;
		//比较n-1趟,最后一个不用比较
		for(int i=0;i<n-1;i++){
			for(int j=0;j<n-i-1;j++){//第i+1趟时,一共比较多少趟
				if(arr[j]>arr[j+1]){
					int temp = arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = temp;
				}
			}
		}
		
		return arr;
	}
	
	public static void main(String[] args) {
		
		int[]arr = {4,5,9,7,6,3,2,1,8};
		System.out.println(Arrays.toString(arr));
		arr = bubbleSort(arr);
		System.out.println(Arrays.toString(arr));
	}

}

运行结果
冒泡排序
归并排序

package com.chenli.sort;

import java.util.Arrays;

/**
 * 归并排序
 * 将一个大的无序数组有序,我们可以把大的数组分成两个,然后对这两个数组分别进行排序,之后在把这两个数组合并成一个有序的数组。
 * 由于两个小的数组都是有序的,所以在合并的时候是很快的。
 * 通过递归的方式将大的数组一直分割,直到数组的大小为 1,此时只有一个元素,那么该数组就是有序的了,
 * 之后再把两个数组大小为1的合并成一个大小为2的,再把两个大小为2的合并成4的 ….. 
 * 直到全部小的数组合并起来。
 * 
 * 时间复杂度:O(nlogn)
 * @author chenli
 *
 */
public class MergeSort {

	public static int[] mergeSort(int[]arr,int left,int right){
		//当left==right时,递归结束
		if(left<right){
			int mid = (left+right)/2;
			//对左边排序
			mergeSort(arr,left,mid);
			//对右边排序
			mergeSort(arr,mid+1,right);
			//将左右两边合并
			merge(arr,left,mid,right);
		}
		
		return arr;
	}
	
	private static void merge(int[] arr, int left, int mid, int right) {
		//定义一个辅助数组,存储有序的数组
		int[]temp = new int[right-left+1];
		//左边有序数组的第一个下标
		int i = left;
		//右边有序数组的第一个下标
		int j = mid+1;
		//辅助数组的第一个下标
		int k = 0;
		while(i<=mid && j<=right){
			//如果左边数组的数比右边的小,则把它存放到有序数组中
			if(arr[i]<arr[j]){
				temp[k++] = arr[i++];
			}else{
				temp[k++] = arr[j++];
			}
		}
		//如果右边的都放进去辅助数组里了,而左边的没有,则直接将左边的数放进去。
		//左边的数已经排好序了
		while(i<=mid){
			temp[k++] = arr[i++];
		}
		//如果左边的都放进去辅助数组里了,而右边的没有,则直接将右边的数放进去。
		//右边的数已经排好序了
		while(j<=right){
			temp[k++] = arr[j++];
		}
		//将排好序的辅助数组拷贝到数组中
		for(int i1=0;i1<k;i1++){
			arr[left++] = temp[i1];
		}		
	}

	public static void main(String[] args) {
		
		int[]arr = {4,5,33,58,67,9,7,6,23,12,71,8,45,68,};
		System.out.println(Arrays.toString(arr));
		arr = mergeSort(arr, 0, arr.length-1);
		System.out.println(Arrays.toString(arr));
	}

}

运行结果
归并排序
快速排序

package com.chenli.sort;

import java.util.Arrays;
/**
 * 我们从数组中选择一个元素,我们把这个元素称之为中轴元素吧,然后把数组中所有小于中轴元素的元素放在其左边,
 * 所有大于或等于中轴元素的元素放在其右边,显然,此时中轴元素所处的位置的是有序的。
 * 也就是说,我们无需再移动中轴元素的位置。
 * 从中轴元素那里开始把大的数组切割成两个小的数组(两个数组都不包含中轴元素),
 * 接着我们通过递归的方式,让中轴元素左边的数组和右边的数组也重复同样的操作,
 * 直到数组的大小为1,此时每个元素都处于有序的位置。
 * 
 * 时间复杂度:O(nlogn)
 * @author chenli
 *
 */
public class QuickSort {

	public static void quickSort(int[]arr,int left,int right){
		if(left<right){
		//获取中间的元素的下标
		int mid = parttition(arr,left,right);
		//对左边的进行快速排序
		quickSort(arr,left,mid-1);
		//对右边的进行快速排序
		quickSort(arr,mid+1,right);
		}
		
	}
	private static int parttition(int[] arr, int left, int right) {
		//选取中轴元素,假设选取数组第一个元素
		int middle = arr[left];
		int i = left+1;
		int j = right;
		while(true){
			//i从左向右扫,若碰到大于等于middle的值则停下来
			while(i<=j&&arr[i]<=middle){
				i++;
			}
			//j从右向左扫,若碰到小于等于middle的值则停下来
			while(i<=j&&arr[j]>=middle){
				j--;
			}
			//跳出循环的条件
			if(i>=j){
				break;
			}
			//交换左边大于中间值和右边小于中间值的位置
			int temp = arr[i];
			arr[i] = arr[j];
			arr[j] = temp;
			
		}
		//最后把中轴元素和j下标的位置交换
		arr[left] = arr[j];
		arr[j] = middle;
		
		return j;
	}
	public static void main(String[] args) {
		
		int[]arr = {4,5,33,58,67,9,7,4,23,12,71,8,45,68,};
		System.out.println(Arrays.toString(arr));
		quickSort(arr, 0, arr.length-1);
		System.out.println(Arrays.toString(arr));

	}

}

运行结果
归并排序

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值