排序算法专辑(冒泡、快速排序、选择排序)未完待续....

在这里插入图片描述

一、冒泡排序

原理:
比较两个相邻的元素,将值大的元素交换到右边。
比如:
要排序数组:[10,1,35,61,89,36,55]
第一趟排序:
第一次排序:10和1比较,10大于1,交换位置      [1,10,35,61,89,36,55]
第二趟排序:10和35比较,10小于35,不交换位置  [1,10,35,61,89,36,55]
第三趟排序:35和61比较,35小于61,不交换位置  [1,10,35,61,89,36,55]
第四趟排序:61和89比较,61小于89,不交换位置  [1,10,35,61,89,36,55]
第五趟排序:89和36比较,89大于36,交换位置   [1,10,35,61,36,89,55]
第六趟排序:89和55比较,89大于55,交换位置   [1,10,35,61,36,55,89]
第一趟总共进行了6次比较,排序结果:[1,10,35,61,36,55,89]
最大的数跑到了最后,下一趟就不用再比较这个数。
第二趟排序:
第一次排序:1和10比较,1小于10,不交换位置  1,10,35,61,36,55,89
第二次排序:10和35比较,10小于35,不交换位置 1,10,35,61,36,55,89
第三次排序:35和61比较,35小于61,不交换位置 1,10,35,61,36,55,89
第四次排序:61和36比较,61大于36,交换位置   1,10,35,36,61,55,89
第五次排序:61和55比较,61大于55,交换位置   1,10,35,36,55,61,89
第二趟总共进行了5次比较,排序结果:1,10,35,36,55,61,89
第三趟排序:
第一次排序:1和10比较,1小于10,不交换位置  1,10,35,36,55,61,89
第二次排序:10和35比较,10小于35,不交换位置 1,10,35,36,55,61,89
第三次排序:35和36比较,35小于36,不交换位置 1,10,35,36,55,61,89
第四次排序:36和61比较,36小于61,不交换位置   1,10,35,36,55,61,89
第三趟总共进行了4次比较,排序结果:1,10,35,36,55,61,89
分析:N个数字要排序,总共进行N-1趟排序,每i趟的排序次数为(N-i)次。
时间复杂度:
冒泡排序总的平均时间复杂度为:O(n2) ,时间复杂度和数据状况无关。
代码实现:

/**
     * 冒泡排序
     * @Author Feng, Ge
     */
    public static void bubbleSort(long[] arr){
    
    
        long start = System.currentTimeMillis();
        if(arr==null || arr.length < 2 ){
    
    
            return;
        }
        for(int i=0; i<arr.length-1; i++){
    
    
        	System.out.println("第" + (i+1)+"趟");
            for (int j=0; j<arr.length-i-1; j++){
    
    
                if(arr[j] > arr[j+1]){
    
    
                    long temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("冒泡排序耗时:" + (end-start));
    }
public static void main(String[] args){
    
    
        long[] arr = {
    
    81,57,34,32,6,91,19,25,36,34};
        System.out.println("排序前:");
        for (int i = 0; i < arr.length; i++) {
    
    
            System.out.print(arr[i]);
            System.out.print("、");
        }
        System.out.println("");
        bubbleSort(arr);
        System.out.println("排序后:");
        for (int i = 0; i < arr.length; i++) {
    
    
            System.out.print(arr[i]);
            System.out.print("、");
        }
        System.out.println("");
}
排序前:
81、57、34、32、6、91、19、25、36、34、
第1趟
第2趟
第3趟
第4趟
第5趟
第6趟
第7趟
第8趟
第9趟
冒泡排序耗时:1
排序后:
6、19、25、32、34、34、36、57、81、91、

上面的是最原始的冒泡排序,总共9趟才完成排序,下面是冒泡的改进版:

public static void bubbleSort(long[] arr) {
    
    
        long start = System.currentTimeMillis();
        if (arr == null || arr.length < 2) {
    
    
            return;
        }
        boolean flag = true;
        for (int i = 0; i < arr.length - 1; i++) {
    
    
            flag = true;
            System.out.println("第" + (i+1)+"趟");
            for (int j = 0; j < arr.length - i - 1; j++) {
    
    
                if (arr[j] > arr[j + 1]) {
    
    
                    long temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    flag = false;
                }
            }
            if(flag){
    
    
                break;
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("冒泡排序耗时:" + (end - start));
    }
排序前:
81、57、34、32、6、91、19、25、36、34、
第1趟
第2趟
第3趟
第4趟
第5趟
第6趟
冒泡排序耗时:0
排序后:
6、19、25、32、34、34、36、57、81、91、

增加flag可以使得原本就有序的趟不用在执行,能有效减少不必要的比较,这里改进后只执行了6趟。

二、快速排序

快速排序是冒泡排序的改进版,比冒泡算法快很多(为啥快这么多,一会讲讲完原理和代码就会明白)。
原理:
快速排序首先在这个序列中随便找一个数作为基准,然后把小于这个基准的数放在基准的左边,大于基准的放在右边,然后分别在左右两边选择新的基准,重复上面的过程(对应代码里面的递归)。
比如:{5,7,6,1,9,10,4,2,3,8}这个数组
先在这个数组选择一个数作为基准,一般选择第一个,就选5作为基准。
采用双向指针的形式,定义分别指向数组的最开始和最尾端的位置:
在这里插入图片描述
首先将j向左移,直到j指向的数小于5;
在这里插入图片描述
再将i向右移,直到i指向的数大于5。最终i指向7,j指向3。
在这里插入图片描述
将3和7交换,数组变为{5,3,2,1,9,10,4,6,7,8}。第一次交换结束。
在这里插入图片描述
接下来继续探测、交换,探测、交换…
第二次交换结束后数组变为{5,3,2,1,4,10,9,6,7,8}。
在这里插入图片描述
j指向9的位置,i指向4的位置,j继续向左移动,直到i的位置才找到小于5的值。
此时i=j,我们只需将基准数落在这个位置:将5和4的值交换。数组变为{4,3,2,1,5,10,9,6,7,8}。
在这里插入图片描述
在这里插入图片描述
至此,第一轮交换结束。
数组被划分为两个区,基准数5左边是小于5的{4,3,2,1},基准右边是大于5的{10,9,6,7,8}。
再分别对这两个区进行第二轮交换。整个过程如下:
在这里插入图片描述
再比如上面冒泡排序中的数组,快速排序过程如下(圈起来的为所选的基准数):
在这里插入图片描述
时间复杂度:
快速排序最优的情况下时间复杂度为:O( nlogn );
快速排序的平均时间复杂度也是:O(nlogn);
快速排序最差的情况下时间复杂度为:O( n^2 )

代码实现:

    public static void quickSort(long[] arr,int low,int high){
    
    
        int i,j;
        long temp;
        long t;
        if(low>high){
    
    
            return;
        }
        i=low;
        j=high;
        //temp就是基准位
        temp = arr[low];

        while (i<j) {
    
    
            //先看右边,依次往左递减
            while (temp<=arr[j]&&i<j) {
    
    
                j--;
            }
            //再看左边,依次往右递增
            while (temp>=arr[i]&&i<j) {
    
    
                i++;
            }
            //如果满足条件则交换
            if (i<j) {
    
    
                t = arr[j];
                arr[j] = arr[i];
                arr[i] = t;
            }
        }
        //最后将基准为与i和j相等位置的数字交换
        arr[low] = arr[i];
        arr[i] = temp;
        //递归调用左半数组
        quickSort(arr, low, j-1);
        //递归调用右半数组
        quickSort(arr, j+1, high);
    }
    public static long[] createArray(int len, int max) {
    
    
        long[] arr = new long[len];
        for (int i = 0; i < arr.length; i++) {
    
    
            arr[i] = (long) (Math.random() * max);
        }
        return arr;
    }
    public static void main(String[] args){
    
    
        long []arr=createArray(10, 100);
        System.out.println("排序前:");
        for (int i = 0; i < arr.length; i++) {
    
    
            System.out.print(arr[i]);
            System.out.print("、");
        }
        System.out.println("");
        quickSort(arr,0, arr.length-1);
        System.out.println("排序后:");
        for (int i = 0; i < arr.length; i++) {
    
    
            System.out.print(arr[i]);
            System.out.print("、");
        }
        System.out.println("");
    }
排序前:
8、24、3、80、11、72、30、65、71、43、
排序后:
3、8、11、24、30、43、65、71、72、80、

三、选择排序

原理:
先找到数组中最小的元素,然后将它和数组的第一个元素交换位置(如果这个元素其实就是自己本身的话,那么就和自己本身进行交换)。然后在剩下的元素中找到最小的元素,将它与数组的第二个元素交换位置,以此循环下去,整个排序过程只需要遍历 n-1 趟。
在这里插入图片描述
时间复杂度:
java选择排序算法是一种不稳定的算法,它的时间复杂度为 O(n2),空间复杂度为 O(1)
代码实现:

public class SelectSortDemo {
    
    
    public static long[] createArray(int len, int max) {
    
    
        long[] arr = new long[len];
        for (int i = 0; i < arr.length; i++) {
    
    
            arr[i] = (long) (Math.random() * max);
        }
        return arr;
    }

    public static void main(String[] args) {
    
    
        long[] arr = createArray(10, 100);
        System.out.println("排序前:");
        for (int i = 0; i < arr.length; i++) {
    
    
            System.out.print(arr[i]);
            System.out.print("、");
        }
        System.out.println("");
        selectSort(arr);
        System.out.println("排序后:");
        for (int i = 0; i < arr.length; i++) {
    
    
            System.out.print(arr[i]);
            System.out.print("、");
        }
        System.out.println("");
    }

    public static long[] selectSort(long[] data) {
    
    
        if (data.length == 0 || data.length == 1) {
    
    
            return data;
        }
        for (int i = 0; i < data.length - 1; i++) {
    
    
            // 假设最开始时,i位置的数最小
            int min = i;
            for (int j = i + 1; j < data.length; j++) {
    
    
                if (data[min] > data[j]) {
    
    
                    // 此时最小的位置移动到j,最小的数即data[j]
                    min = j;
                }
            }
            // 调换min位置和i位置的值(若一轮比较下来都没有变更最小值的索引,即min==i,则无需调换顺序)
            if (min != i) {
    
    
                long temp = data[min];
                data[min] = data[i];
                data[i] = temp;
            }
        }
        return data;
    }
}
排序前:
70、77、52、24、81、45、69、78、45、69、
排序后:
24、45、45、52、69、69、70、77、78、81、

猜你喜欢

转载自blog.csdn.net/weixin_41231928/article/details/107525709
今日推荐