几种排序算法的Java代码实现

1.关于选择排序

概念(Selection sort)

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

平均时间复杂度: n 2 n^2 n2;
最坏时间复杂度: n 2 n^2 n2;
最好时间复杂度: n 2 n^2 n2;
空间复杂度:1;
稳定性:最不稳定;

每次选择最小的元素位置,放在起始位置

 public static void main(String[] args) {
        //生成一个随机整数数组
        Random random = new Random();
        int [] arr = new int[10];
        for (int m =0;m <10;m++){
            int anInt = random.nextInt(100);
            arr[m] = anInt;
        }
                //复制数组
        for (int i=0;i<arr.length;i++)
        brr[i] = arr[i];
        //打印排序前的数组
        System.out.println(Arrays.toString(arr));
        System.out.println(Arrays.toString(brr));
        //选择排序,遍历数组,找到最小数的坐标,然后交换位置
        for(int i = 0;i<arr.length-1;i++){
            int minpos = i;
            for (int j = i+1;j<arr.length;j++)
            //每一次遍历,找到最小元素的坐标
            minpos = arr[j]<arr[minpos]?j:minpos;
            //然后交换最小元素坐标
            int temp = arr[i];
            arr[i] = arr[minpos];
            arr[minpos] = temp;
        }
        //输出排序后的数组,与排序前数组对比
        System.out.println("....."+Arrays.toString(arr));
        System.out.println("...........");
        //与工具类排序对比
        Arrays.sort(brr);
        System.out.println("工具类排序:" +Arrays.toString(brr))
    }

运算结果:

在这里插入图片描述

每次选择最大的元素位置,放在末尾位置

    public static void main(String[] args) {
        //生成一个随机整数数组
        Random random = new Random();
        int [] arr = new int[10];
        int [] brr = new int[10];
        for (int m =0;m <10;m++){
            int anInt = random.nextInt(100);
            arr[m] = anInt;
        }
        //复制数组
        for (int i=0;i<arr.length;i++)
            brr[i] = arr[i];
        System.out.println(Arrays.toString(arr));
        System.out.println(Arrays.toString(brr));
        //选择排序,遍历数组,找到最大数的坐标,然后交换位置
        for(int i = 0;i<arr.length-1;i++){
            int maxpos = 0;
            for (int j = 0;j<arr.length-i;j++)
            maxpos = arr[j]>arr[maxpos]?j:maxpos;
            //交换最大元素的位置
            int te = arr[arr.length-1-i];
            arr[arr.length-1-i] = arr[maxpos];
            arr[maxpos] = te;
        }
        System.out.println("选择排序:"+Arrays.toString(arr));
        System.out.println("...........");
        //与工具类排序对比
        Arrays.sort(brr);
        System.out.println("工具类排序:" +Arrays.toString(brr));
    }

运算结果:

在这里插入图片描述

2.关于冒泡排序

概念(Bubble sort)

冒泡排序:是指它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果第一个比第二个大,就交换他们两个。对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较,最后就实现了排序的功能。

平均时间复杂度: n 2 n^2 n2;
最坏时间复杂度: n 2 n^2 n2;
最好时间复杂度:n;
空间复杂度:1;
稳定性:稳定;

代码实现

package com;

import java.util.Arrays;
import java.util.Random;

public class bubbleSort {
    public static void main(String[] args) {
        Random random = new Random();
        int [] arr = new int[10000];
        int [] brr = new int[10000];
        for (int m =0;m <10000;m++){
            int anInt = random.nextInt(100000);
            arr[m] = anInt;
        }
        //复制数组
        for (int i=0;i<arr.length;i++)
            brr[i] = arr[i];
        System.out.println(Arrays.toString(arr));
        System.out.println(Arrays.toString(brr));
        long startTime = System.currentTimeMillis();
        BubbleMethod(arr,brr);
        long endTiem = System.currentTimeMillis();
        System.out.println("用时:" + (endTiem-startTime));
    }

    private static void BubbleMethod(int[] arr, int[] brr) {
        for (int i =0 ;i < arr.length-1; i++){
            for (int j = 0; j< arr.length-1-i;j++){
               if (arr[j] > arr[j+1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
               }
            }
        }
        System.out.println("Bubble排序:"+Arrays.toString(arr));

        System.out.println("...........");
        Arrays.sort(brr);
        System.out.println("工具类排序:" +Arrays.toString(brr));
    }

}

运算结果

在这里插入图片描述

3.关于插入排序

概念

插入排序(Insertionsort),它的基本思想是将一个元素插入到已经排好序的有序表中,从而一个新的、元素数增1的有序表。在其实现过程使用双层循环,外层循环对除了第一个元素之外的所有元素,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动。插入排序在样本小且基本有序的时候效率比较高。

平均时间复杂度: n 2 n^2 n2;
最坏时间复杂度: n 2 n^2 n2;
最好时间复杂度:n;
空间复杂度:1;
稳定性:稳定;

代码实现

package com;

import java.util.Arrays;
import java.util.Random;

/**
 * @author shixiaodong
 * @creat 2021-06-01
 */
public class insertionSort {
    public static void main(String[] args) {
        //生成一个随机整数数组
        Random random = new Random();
        int[] arr = new int[10000];
        int[] brr = new int[10000];
        for (int m = 0; m < 10000; m++) {
            int anInt = random.nextInt(100000);
            arr[m] = anInt;
        }
        //复制数组
        for (int i = 0; i < arr.length; i++)
            brr[i] = arr[i];
        System.out.println(Arrays.toString(arr));
        System.out.println(Arrays.toString(brr));
        long startTime = System.currentTimeMillis();
        shellMethod(arr, brr);
        long endTiem = System.currentTimeMillis();
        System.out.println("用时:" + (endTiem - startTime));
    }

    private static void shellMethod(int[] arr, int[] brr) {
        //次外层循环,控制间隔与间隔之间交换
        for (int i = 1; i < arr.length; i++) {
            //内层循环,控制间隔内交换
            for (int j = i; j > 0 && arr[j] < arr[j - 1]; j--) {
                //交换
                int temp = arr[j];
                arr[j] = arr[j - 1];
                arr[j - 1] = temp;
            }
        }
        System.out.println("Insertion排序:" + Arrays.toString(arr));
        System.out.println("...........");
        Arrays.sort(brr);
        System.out.println("工具类排序:" + Arrays.toString(brr));
    }
}

运行结果

在这里插入图片描述

4.希尔排序

概念

希尔排序(Shellsort),也叫缩减增量排序比普通插入排序效率高,但是不稳定。希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至 1 时,整个文件恰被分成一组,算法便终止。所以最后的增量一定要是1。

平均时间复杂度: n 1 . 3 n^1.3 n1.3;
最坏时间复杂度: n 2 n^2 n2;
最好时间复杂度:n;
空间复杂度:1;
稳定性:不稳定;

代码实现

package com;

import java.util.Arrays;
import java.util.Random;

public class shellSort {
    public static void main(String[] args) {
        //生成一个随机整数数组
        Random random = new Random();
        int [] arr = new int[10000];
        int [] brr = new int[10000];
        for (int m =0;m <10000;m++){
            int anInt = random.nextInt(100000);
            arr[m] = anInt;
        }
        //复制数组
        for (int i=0;i<arr.length;i++)
            brr[i] = arr[i];
        System.out.println(Arrays.toString(arr));
        System.out.println(Arrays.toString(brr));
        long startTime = System.currentTimeMillis();
        shellMethod(arr,brr);
        long endTiem = System.currentTimeMillis();
        System.out.println("用时:" + (endTiem-startTime));
    }

    private static void shellMethod(int[] arr,int[] brr) {
        //knuth 序列,效率最高
        int h =1;
        while(h<=arr.length/3) h=h*3+1;
        //最外层循环,控制间隔
        for(int gap = h;gap>0;gap=(gap-1)/3){
            //次外层循环,控制间隔与间隔之间交换
            for(int i=gap;i<arr.length;i++){
                //内层循环,控制间隔内交换
                for(int j=i;j>gap-1 && arr[j]<arr[j-gap];j -= gap){
                    //交换
                    int temp = arr[j];
                    arr[j] = arr[j-gap];
                    arr[j-gap] = temp;
                }
            }

        }
        System.out.println("shell排序:"+Arrays.toString(arr));

        System.out.println("...........");
        Arrays.sort(brr);
        System.out.println("工具类排序:" +Arrays.toString(brr));
    }
}

运行结果

在这里插入图片描述

插入排序和希尔排序的区别

  1. 希尔排序是在插入排序基础上的升级,效率比较高;
  2. 在稳定性方面,插入排序稳定,希尔排序不稳定;
  3. 希尔排序相比于插入排序在代码上多一层循环,这多出来的一层循环是用来控制插入间隔的逐渐缩小。

5.归并排序

概念

归并排序,是创建在归并操作上的一种有效的排序算法。算法是采用分治法(Divide and Conquer)的一个非常典型的应用,且各层分治递归可以同时进行。归并排序思路简单,速度仅次于快速排序,为稳定排序算法,一般用于对总体无序,但是各子项相对有序的数列。

归并排序是用分治思想,分治模式在每一层递归上有三个步骤:
1.分解(Divide):将n个元素分成个含n/2个元素的子序列。
2.解决(Conquer):用合并排序法对两个子序列递归的排序。
3.合并(Combine):合并两个已排序的子序列已得到排序结果。

平均时间复杂度: n l o g 2 N nlog_2{N} nlog2N;
最坏时间复杂度: n l o g 2 N nlog_2{N} nlog2N;
最好时间复杂度: n l o g 2 N nlog_2{N} nlog2N;
空间复杂度:1;
稳定性:稳定;

代码实现

package com;

import com.sun.scenario.effect.Merge;

import java.util.Arrays;
import java.util.Random;

public class mergeSort {
    public static void main(String[] args) {
        Random random = new Random();
        int [] arr = new int[10000];
        int [] brr = new int[10000];
        for (int m =0;m <10000;m++){
            int anInt = random.nextInt(100000);
            arr[m] = anInt;
        }
        //复制数组
        for (int i=0;i<arr.length;i++)brr[i] = arr[i];
        System.out.println(Arrays.toString(arr));
        System.out.println(Arrays.toString(brr));
        long startTime = System.currentTimeMillis();
        mergeSort(arr,brr);
        long endTiem = System.currentTimeMillis();
        System.out.println("用时:" + (endTiem-startTime));
    }

    private static void mergeSort(int[] arr, int[] brr) {
        Sort(arr,0,arr.length-1);
        System.out.println("merge排序:"+Arrays.toString(arr));
        System.out.println("...........");
        Arrays.sort(brr);
        System.out.println("工具类排序:" +Arrays.toString(brr));
    }

    /**
     * 将数组通过递归一直二分,然后将最小二分的数组排好序后合并
     */
    private static void Sort(int[] arr, int left, int right) {
        if (left == right) return;
        int mid = left +(right-left)/2;
        Sort(arr,left,mid);
        Sort(arr,mid+1,right);
        merge(arr,left,mid,right);
    }

    private static void merge(int[] arr, int left, int mid, int right) {
        //创建一个长度和arr相同的空数组
        int[] temp = new int[right-left+1];
        int i = left;
        int j = mid+1;
        int k = 0;
        //将两个二分数组从做小坐标开始比较,将最小值一次交给temp数组
        while (i<=mid && j<=right) temp[k++]=arr[i]<arr[j]?arr[i++]:arr[j++];
        while (i<=mid) temp[k++]=arr[i++];
        while (j<=right) temp[k++]=arr[j++];
        //将排好序的temp交给arr数组
        for (int m=0;m<temp.length;m++) arr[left+m]=temp[m];
    }
}

运行结果

在这里插入图片描述

6.快速排序

概念

快速排序,通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

快速排序算法通过多次比较和交换来实现:

  1. 首先设定一个分界值,通过该分界值将数组分成左右两部分。
  2. 将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值。
  3. 然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
  4. 重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。

平均时间复杂度: n l o g 2 N nlog_2{N} nlog2N;
最坏时间复杂度: n 2 n^2 n2;
最好时间复杂度: n l o g 2 N nlog_2{N} nlog2N;
空间复杂度: l o g 2 N log_2{N} log2N
稳定性:不稳定;

代码实现

package com;

import java.util.Arrays;
import java.util.Random;

public class quickSort {
    public static void main(String[] args) {
        Random random = new Random();
        int[] arr = new int[10000];
        int[] brr = new int[10000];
        //生成随机数组
        for (int m = 0; m < 10000; m++) {
            int anInt = random.nextInt(100000);
            arr[m] = anInt;
        }
        //复制数组
        for (int i = 0; i < arr.length; i++)
            brr[i] = arr[i];
        System.out.println(Arrays.toString(arr));
        System.out.println(Arrays.toString(brr));
        long startTime = System.currentTimeMillis();
        //实现排序
        quickMethod(arr, brr);
        long endTiem = System.currentTimeMillis();
        System.out.println("用时:" + (endTiem - startTime));
    }

    private static void quickMethod(int[] arr, int[] brr) {
        Sort(arr, 0, arr.length - 1);
        //与工具类方法对比
        System.out.println("quick排序:" + Arrays.toString(arr));
        System.out.println("...........");
        Arrays.sort(brr);
        System.out.println("工具类排序:" + Arrays.toString(brr));
    }

    private static void Sort(int[] arr, int left, int right) {
        if (left >= right) return;
        int mid = partition(arr, left, right);
        //方法递归
        Sort(arr, left, mid - 1);
        Sort(arr, mid + 1, right);
    }

    private static int partition(int[] arr, int left, int right) {
        //选择数组最有边界的值作为轴
        int pivot = arr[right];
        int i = left;
        int j = right - 1;
        while (i <= j) {
            while (i <= j && arr[i] <= pivot) i++;
            while (i <= j && arr[j] > pivot) j--;
            if (i < j) Swap(arr, i, j);
        }
        Swap(arr, i, right);
        return i;
    }

    /**元素交换*/
    private static void Swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

运行结果

在这里插入图片描述

7.计数排序

概念

计数排序,其思想是对于给定的输入序列中的每一个元素x,确定该序列中值小于x的元素的个数(此处并非比较各元素的大小,而是通过对元素值的计数和计数值的累加来确定)。一旦有了这个信息,就可以将x直接存放到最终的输出序列的正确位置上。

计数排序是一个非基于比较的排序算法,它的优势在于在对一定范围内的整数排序时,快于任何比较排序算法,适合量大但是范围小的情况,对源数有要求。

平均时间复杂度: n + k n+k n+k;
最坏时间复杂度: n + k n+k n+k;
最好时间复杂度: n + k n+k n+k;
空间复杂度: n + k n+k n+k
稳定性:稳定;

代码实现

package com;

import java.util.Arrays;
import java.util.Random;

/**
 * @author shixiaodong
 * @creat 2021-06-09
 */
public class countSort {
    public static void main(String[] args) {
        //生成一个随机整数数组
        Random random = new Random();
        int[] arr = new int[1000];
        int[] brr = new int[1000];
        for (int m = 0; m < 1000; m++) {
            int anInt = random.nextInt(100);
            arr[m] = anInt;
        }
        //复制数组
        for (int i = 0; i < arr.length; i++) brr[i] = arr[i];
        System.out.println(Arrays.toString(arr));
        System.out.println(Arrays.toString(brr));
        long startTime = System.currentTimeMillis();
        countMethod(arr, brr);
        long endTiem = System.currentTimeMillis();
        System.out.println("用时:" + (endTiem - startTime));
    }

    private static void countMethod(int[] arr, int[] brr) {
        int[] result = Sort(arr);
        System.out.println("计数排序:" + Arrays.toString(result));
        System.out.println("...........");
        Arrays.sort(brr);
        System.out.println("工具类排序:" + Arrays.toString(brr));
    }

    private static int[] Sort(int[] arr) {
        int[] result = new int[arr.length];
        //count数组的个数与arr数组元素的取值范围相同,这里取值范围从为[0,10)
        int[] count = new int[100];
        for (int i=0;i<arr.length;i++){
            count[arr[i]]++;
        }
        //累加数组
        for (int i = 1;i<count.length;i++){
            count[i]=count[i]+count[i-1];
        }
        //从后往前遍历,相同元素的顺序没有改变:不稳定 -> 稳定
        for (int i=arr.length-1;i>=0;i--){
            result[--count[arr[i]]]=arr[i];
        }
        return result;
    }
}

运行结果

在这里插入图片描述

参考:B站马士兵

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值