今天复习了一下排序算法,总结一下今天自己写的代码。
原理可能只是简单介绍一下,如果原理不太懂的小伙伴还是去理解一下原理,不然可能看不懂算法。
选择排序
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));
}
}
运行结果