常见排序算法及Java实现及相关比较

一:冒泡排序

1. 算法

  1. 比较相邻的元素,如果前一个比后一个大,就把它们两个调换位置。
    对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
  2. 针对所有的元素重复以上的步骤,除了最后一个。
  3. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

2.特点

平均情况:O(n^2)
最好情况:O(n)
最坏情况:O(n^2)

辅助空间:O(1)

稳定性:稳定

3.代码

package Sort;

import java.util.Arrays;

public class BubbleSort {

    public static void bubbleSort(int[] arr){
        if(arr == null || arr.length < 2){
            return;
        }
        for(int i = arr.length-1 ; i > 0 ;i--){
            for(int j = 0; j < i ;j++){
                if(arr[j] > arr[j+1]){
                    swap(arr,j,j+1);
                }
            }
        }
    }
    private static void swap(int[] arr,int i ,int j){
    //异或运算:1.X^X = 0;2.X^0 = X
        arr[i] = arr[i] ^ arr[j];
        arr[j] = arr[i] ^ arr[j];
        arr[i] = arr[i] ^ arr[j];
    }

    //for test
    private static void comparator(int[] arr){
        Arrays.sort(arr);
    }
    private static int[] generateRandomArr(int maxLength,int maxValue){
        int[] arr = new int[(int)(Math.random() * (maxLength+1))];//[0,maxLength]长度的数组
        for(int i = 0; i < arr.length ;i++){
            arr[i] = (int)(Math.random() * (maxValue+1)) - (int)(Math.random() * maxValue);
        }
        return arr;
    }
    private static int[] copyArr(int[] arr){
        if(arr == null){
            return null;
        }
        int[] newArr = new int[arr.length];
        for(int i = 0; i < arr.length ;i++){
            newArr[i] = arr[i];
        }
        return newArr;
    }
    private static boolean isEqual(int[] arr1,int[] arr2){
        if(arr1 == null && arr2 == null){
            return true;
        }
        if(arr1 == null || arr2 == null){
            return false;
        }
        if(arr1.length != arr2.length){
            return false;
        }
        for(int i = 0; i < arr1.length ;i++){
            if(arr1[i] != arr2[i]){
                return false;
            }
        }
        return true;
    }
    private static void printArr(int[] arr){
        if(arr == null){
            System.out.println("数组为空");
        }
        System.out.println("数组为:");
        for(int i = 0; i < arr.length ;i++){
            if(i == arr.length-1){
                System.out.print(arr[i]);
                break;
            }
            System.out.print(arr[i] + ",");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        int maxLength = 100;
        int maxValue = 100;
        int testTime = 500000;
        boolean equal = true;
        for(int i = 0; i < testTime ;i++){
            int[] arr1 = generateRandomArr(maxLength, maxValue);
            int[] arr2 = copyArr(arr1);
            bubbleSort(arr1);
            comparator(arr2);
            equal = isEqual(arr1,arr2);
            if(equal){
                continue;
            }else{
                printArr(arr1);
                printArr(arr2);
                System.out.println("Error");
                break;
            }
        }
        System.out.println(equal ? "没问题" : "出错了");

    }
}



4.改进:鸡尾酒排序/定向冒泡排序

先从前往后把最大的放在最后,然后从后往前把最小的放在最前面

    public static void bubbleSortPro(int[] arr){
        if(arr == null || arr.length < 2){
            return;
        }
        int n = arr.length;
        int left = 0;
        int right = n-1;
        while(left < right){
            for(int i = left; i < right; i++){
                if(arr[i] > arr[i+1]){
                    swap(arr,i,i+1);
                }
            }
            right--;
            for(int i = right; i > left; i--){
                if(arr[i] < arr[i-1]){
                    swap(arr,i-1,i);
                }
            }
            left++;
        }
    }

    private static void swap(int[] arr,int i ,int j){
        arr[i] = arr[i] ^ arr[j];
        arr[j] = arr[i] ^ arr[j];
        arr[i] = arr[i] ^ arr[j];
    }

二:选择排序

1.算法

找到数组中最小元素,和数组第一个元素交换位置。
然后在剩下的元素中找到最小元素,和数组第二个元素交换位置。
如此往复,直到数组有序。

2.特点

分类 -------------- 内部比较排序

最差时间复杂度 ---- O(n^2)
最优时间复杂度 ---- O(n^2)
平均时间复杂度 ---- O(n^2)

所需辅助空间 ------ O(1)

稳定性 ------------ 不稳定

3.代码

package test;

import java.util.Arrays;

public class SelectionSort {

    public static void selectSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        for (int i = 0; i < arr.length - 1; i++) {
            int minIndex = i;
            for (int j = i + 1; j < arr.length; j++) {
                minIndex = arr[j] < arr[minIndex] ? j : minIndex;
            }
            swap(arr, i, minIndex);
        }
    }

    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
        /*这里若按照如下方式交换arr[i] 和 arr[j] 的值会报错
        原因在于:我们选择排序的时候选的是从i到arr.length-1中的最小的一个和i位置上的元素进行交换
       若i位置上的元素就是最小元素:
       那么在做arr[i] = arr[i] ^ arr[j] 的时候,arr[i]和arr[j] 是同一个元素会出现 a ^ a = 0的情形,
       使得arr[i]变成了0.
     	arr[i] = arr[i] ^ arr[j];
        arr[j] = arr[i] ^ arr[j];
        arr[i] = arr[i] ^ arr[j];*/

    }


    // for test
    public static void comparator(int[] arr) {
        Arrays.sort(arr);
    }

    // for test
    public static int[] generateRandomArray(int maxSize, int maxValue) {
        int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
        }
        return arr;
    }

    // for test
    public static int[] copyArray(int[] arr) {
        if (arr == null) {
            return null;
        }
        int[] res = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            res[i] = arr[i];
        }
        return res;
    }

    // for test
    public static boolean isEqual(int[] arr1, int[] arr2) {
        if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
            return false;
        }
        if (arr1 == null && arr2 == null) {
            return true;
        }
        if (arr1.length != arr2.length) {
            return false;
        }
        for (int i = 0; i < arr1.length; i++) {
            if (arr1[i] != arr2[i]) {
                return false;
            }
        }
        return true;
    }

    // for test
    public static void printArray(int[] arr) {
        if (arr == null) {
            return;
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }

    // for test
    public static void main(String[] args) {
        int testTime = 500000;
        int maxSize = 100;
        int maxValue = 100;
        boolean succeed = true;
        for (int i = 0; i < testTime; i++) {
            int[] arr1 = generateRandomArray(maxSize, maxValue);
            int[] arr2 = copyArray(arr1);
            selectSort(arr1);
            comparator(arr2);
            if (!isEqual(arr1, arr2)) {
                succeed = false;
                printArray(arr1);
                printArray(arr2);
                break;
            }
        }
        System.out.println(succeed ? "Nice!" : "Fucking fucked!");

        int[] arr = generateRandomArray(maxSize, maxValue);
        printArray(arr);
        selectSort(arr);
        printArray(arr);
    }
}

三:插入排序

1.算法

当前索引左边的所有元素是有序的,把当前索引和之前的元素进行比较

  • 如果当前索引上的数小,就把之前的数往右移动
  • 如果当前索引上的数大,结束

2. 特点

插入排序所需要的的时间取决于输入中元素的初始顺序

3. 代码

import java.util.Arrays;

public class InsertionSort {

    public static void insertionSort(int[] arr){
        if(arr == null || arr.length < 2){
            return ;
        }
        insertionSort(arr,0,arr.length-1);
    }
    private static void insertionSort(int[] arr,int l,int r){
        for(int i = 1; i < arr.length ;i++){
            int num = arr[i];
            for(int j = i-1; j >= 0; j--){
                if(num < arr[j]){
                    swap(arr,j,j+1);
                }
            }
        }
    }
    private static void swap(int[] arr,int i ,int j){
        arr[i] = arr[i] ^ arr[j];
        arr[j] = arr[i] ^ arr[j];
        arr[i] = arr[i] ^ arr[j];
    }

    //for test
    private static void comparator(int[] arr){
        Arrays.sort(arr);
    }
    private static int[] generateRandomArr(int maxLength,int maxValue){
        int[] arr = new int[(int)(Math.random() * (maxLength+1))];//[0,maxLength]长度的数组
        for(int i = 0; i < arr.length ;i++){
            arr[i] = (int)(Math.random() * (maxValue+1)) - (int)(Math.random() * maxValue);
        }
        return arr;
    }
    private static int[] copyArr(int[] arr){
        if(arr == null){
            return null;
        }
        int[] newArr = new int[arr.length];
        for(int i = 0; i < arr.length ;i++){
            newArr[i] = arr[i];
        }
        return newArr;
    }
    private static boolean isEqual(int[] arr1,int[] arr2){
        if(arr1 == null && arr2 == null){
            return true;
        }
        if(arr1 == null || arr2 == null){
            return false;
        }
        if(arr1.length != arr2.length){
            return false;
        }
        for(int i = 0; i < arr1.length ;i++){
            if(arr1[i] != arr2[i]){
                return false;
            }
        }
        return true;
    }
    private static void printArr(int[] arr){
        if(arr == null){
            System.out.println("数组为空");
        }
        System.out.println("数组为:");
        for(int i = 0; i < arr.length ;i++){
            if(i == arr.length-1){
                System.out.print(arr[i]);
                break;
            }
            System.out.print(arr[i] + ",");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        int maxLength = 100;
        int maxValue = 100;
        int testTime = 500000;
        boolean equal = true;
        for(int i = 0; i < testTime ;i++){
            int[] arr1 = generateRandomArr(maxLength, maxValue);
            int[] arr2 = copyArr(arr1);
            insertionSort(arr1);
            comparator(arr2);
            equal = isEqual(arr1,arr2);
            if(equal){
                continue;
            }else{
                printArr(arr1);
                printArr(arr2);
                System.out.println("Error");
                break;
            }
        }
        System.out.println(equal ? "没问题" : "出错了");

    }
}


四:希尔排序

1.算法

一种基于 插入排序 的排序算法

  • 插入排序:对于大规模、乱序数组的速度会很慢,因为它只交换相邻元素
  • 希尔排序:交换不相邻的元素

希尔排序的思想是使数组中任意间隔 h 的元素都是有序的。这样的数组成为 h 有序数组。
对于任意以 1 结尾的 h 序列,我们都能将数组排序。

2. 特点

3.代码

import java.util.Arrays;

public class ShellSort {

    public static void shellSort(int[] arr){
        if(arr == null || arr.length < 2){
            return ;
        }
        int h = 1;
        while(h < arr.length / 3){
            h = h*3+1;
        }
        while(h >= 1){
            for(int i = h; i < arr.length ;i++){
                for(int j = i; j >= h && arr[j-h] > arr[j]; j -= h){
                    swap(arr,j-h,j);
                }
            }
            h /= 3;
        }
    }
    private static void swap(int[] arr,int i ,int j){
        arr[i] = arr[i] ^ arr[j];
        arr[j] = arr[i] ^ arr[j];
        arr[i] = arr[i] ^ arr[j];
    }

    //for test
    private static void comparator(int[] arr){
        Arrays.sort(arr);
    }
    private static int[] generateRandomArr(int maxLength,int maxValue){
        int[] arr = new int[(int)(Math.random() * (maxLength+1))];//[0,maxLength]长度的数组
        for(int i = 0; i < arr.length ;i++){
            arr[i] = (int)(Math.random() * (maxValue+1)) - (int)(Math.random() * maxValue);
        }
        return arr;
    }
    private static int[] copyArr(int[] arr){
        if(arr == null){
            return null;
        }
        int[] newArr = new int[arr.length];
        for(int i = 0; i < arr.length ;i++){
            newArr[i] = arr[i];
        }
        return newArr;
    }
    private static boolean isEqual(int[] arr1,int[] arr2){
        if(arr1 == null && arr2 == null){
            return true;
        }
        if(arr1 == null || arr2 == null){
            return false;
        }
        if(arr1.length != arr2.length){
            return false;
        }
        for(int i = 0; i < arr1.length ;i++){
            if(arr1[i] != arr2[i]){
                return false;
            }
        }
        return true;
    }
    private static void printArr(int[] arr){
        if(arr == null){
            System.out.println("数组为空");
        }
        System.out.println("数组为:");
        for(int i = 0; i < arr.length ;i++){
            if(i == arr.length-1){
                System.out.print(arr[i]);
                break;
            }
            System.out.print(arr[i] + ",");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        int maxLength = 100;
        int maxValue = 100;
        int testTime = 500000;
        boolean equal = true;
        for(int i = 0; i < testTime ;i++){
            int[] arr1 = generateRandomArr(maxLength, maxValue);
            int[] arr2 = copyArr(arr1);
            shellSort(arr1);
            comparator(arr2);
            equal = isEqual(arr1,arr2);
            if(equal){
                continue;
            }else{
                printArr(arr1);
                printArr(arr2);
                System.out.println("Error");
                break;
            }
        }
        System.out.println(equal ? "没问题" : "出错了");

    }
}


五、快排

1.算法

2.特点

有一个partition过程,作用是以最后一个元素为基准,把小于这个元素的都放在左边,大于的都放在右边,等于的都放在中间。

3.代码

class Solution {
    public int[] sortArray(int[] nums) {
        //快排
        if(nums == null || nums.length < 2){
            return nums;
        }
        sortArray(nums,0,nums.length-1);
        return nums;
    }
    private void sortArray(int[] nums,int l,int r){
        if(l < r){
            int[] p = partition(nums,l,r);
            sortArray(nums,l,p[0]);
            sortArray(nums,p[1],r);
        }
    }
    private int[] partition(int[] nums,int l,int r){
        int less = l-1;
        int more = r;
        while(l < more){
            if(nums[l] < nums[r]){
                swap(nums,++less,l++);
            }else if(nums[l] > nums[r]){
                swap(nums,--more,l);
            }else{
                l++;
            }
        }
        swap(nums,r,l);
        return new int[]{less,l+1};
    }
    private void swap(int[] nums,int i ,int j){
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

六、归并排序

1. 算法

2. 特点

3.代码

class Solution {
    public int[] sortArray(int[] nums) {
        //归并排序
        if(nums == null || nums.length == 0){
            return nums;
        }
        mergeSort(nums,0,nums.length-1);
        return nums;
    }
    private void mergeSort(int[] nums,int l,int r){
        if(l == r){
            return ;
        }
        int m = l + ((r-l)>>1);
        mergeSort(nums,l,m);
        mergeSort(nums,m+1,r);
        merge(nums,l,m,r);
    }
    
    private void merge(int[] nums,int l,int m ,int r){
        int[] help = new int[r-l+1];
        int index = 0;
        int p1 = l;
        int p2 = m+1;
        while(p1 <= m || p2 <= r){
            if(p1 > m ){
                help[index++] = nums[p2++];
                continue;
            }
            if(p2 > r ){
                help[index++] = nums[p1++];
                continue;
            }
            help[index++] = nums[p1] > nums[p2] ? nums[p2++] : nums[p1++];
        }
        for(int i = 0; i < help.length ;i++){
            nums[l+i] = help[i];
        }

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值