基础排序算法总结(代码+图片分析)

Posted 温文艾尔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基础排序算法总结(代码+图片分析)相关的知识,希望对你有一定的参考价值。

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

冒泡排序

基本介绍:

冒泡排序的基本思想就是:通过对待排序序列从前向后(从下标较小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部

因为排序的过程中,各元素不接近自己的位置,如果一趟比较下来没有进行过交换,就说明序列有序,因此要在排序过程中设置一个标志flag判断元素是否进行过交换,从而减少不必要的比较

冒泡排序图解


第一趟排序

(1) 3,9,-1,10,20 //如果相邻的元素逆序就交换

(2) 3,-1,9,10,20

(3) 3.-1,9,10,20

(4) 3,-1,9,10,20

第二趟排序

(1) -1,3,9,10,20

(2) -1,3,9,10,20

(3) -1,3,9,10,20

第三趟排序

(1) -1,3,9,10,20

(2)-1,3.9,10,20

第四趟排序

(1)-1,3,9,10,20

小结冒泡排序规则

(1)一共进行数组的大小-1次大的循环

(2)每一趟排序的次数在逐渐的减少

public static int[] method(int[] arr){
        boolean flag = true;
        for (int i=0;i<arr.length-1;i++){
            for (int j=0;j<arr.length-i-1;j++){
                if(arr[j]>arr[j+1]){
                    flag=false;
                    int temp = 0;
                    temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
            if(flag){
                return arr;
            }else flag=true;
        }
        return arr;
    }

选择排序

选择式排序也属于内部排序法,从预排序的数据中,按照指定的规则选出某一元素,再依规定交换位置后达到排序的目的

选择排序的基本思想

第一次从arr[0]-arr[n-1]中选取最小值,与arr[0]交换,第二次从arr[1]-arr[n-1]中选取最小值,与arr[1]交换,以此类推,第n-1次从arr[n-2]-arr[n-1]中选取最小值,与arr[n-2]交换,总共通过n-1次,得到一个按排序码从小到大排列的有序序列

选择排序图解


原始的数组:

101,34,119,1

第一轮排序:

1,34,119,101

第二轮排序:

1, 34,119,101

第三轮排序:

1,34,101,119

说明:

1.选择排序一共有数组大小-1轮排序

2.每1轮排序,又是一个循环,循环的规则

2.1先假定当前这个数是最小数

2.2然后和后面的每个数进行比较,如果发现有比当前数更小的数,就重新确定最小数并得到下标

2.3当遍历到数组的最后时,就得到本轮最小数和下标

2.4交换

    public static int[] xuanze(int[] arr){
        for(int i=0;i<arr.length;i++){
            for (int j=0;j<arr.length-i-1;j++){
                if(arr[j]>arr[j+1]){
                    min = j+1;
                }
            }
            int temp = 0;
            temp = arr[min];
            arr[min] = arr[i];
            arr[i] = temp;
        }
        return arr;
    }

插入排序

插入排序基本介绍

插入排序属于内部排序法,是对于预排序的匀速以插入的方式找寻该元素的适当位置,已达到排序的目的

插入排序的基本思想

把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表只包含一个元素,无序表中包含n-1个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将他插入到有序表中的适当位置,使之成为新的有序表

插入排序图解

    public static int[] charu(int[] arr){
        for (int i=1;i<arr.length;i++){
            int insertValue = arr[i];//-1
            int insertIndex = i-1;//1 0
            while(insertIndex>=0&&insertValue<arr[insertIndex]){
                arr[insertIndex+1] = arr[insertIndex];
                insertIndex-=1;
            }
            //找到了要插入的位置
            arr[insertIndex+1] = insertValue;
        }
        return arr;
    }

希尔排序

希尔排序是希尔于1959年提出的一种排序算法。希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序

希尔排序法基本思想

希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法变终止。

希尔排序示意图

交换法

    public static int[] Xier(int[] arr){
        //5,2,1  10/2/2/2
        for(int gap = arr.length/2;gap>0;gap/=2){
            for (int i=gap;i<arr.length;i++){
                for (int j=i-gap;j>=0;j-=gap){
                    if(arr[j]>arr[j+gap]){
                        int temp = 0;
                        temp = arr[j];
                        arr[j] = arr[j+gap];
                        arr[j+gap] = temp;
                    }
                }
            }
        }
        return arr;
    }

移位法

    //移位法
    public static int[] Xier3(int[] arr){
        //5,2,1  10/2/2/2
        for(int gap = arr.length/2;gap>0;gap/=2){
            for (int i=gap;i<arr.length;i++){
                //对每一组的数据进行直接插入
                int insertValue =   arr[i];//1
                int insertIndex = i-gap;//1
                while(insertIndex>=0&&insertValue<arr[insertIndex]){
                    arr[insertIndex+gap] = arr[insertIndex];
                    insertIndex-=gap;
                }
                arr[insertIndex+gap] = insertValue;
            }
        }
        return arr;
    }

快速排序

快速排序介绍

快速排序是对冒泡排序的一种改进

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

快速排序法示意图

以中间值为基准

 
private static void quicksort(int[] arr, int l, int r) {
        if(l>=r){
            return;
        }
        int x = arr[(l+r)/2];
        int i = l-1;
        int j = r+1;
        while (i<j){
            do {
                i++;
            }while (arr[i]<x);
            do {
                j--;
            }while (arr[j]>x);
            if(i<j){
                int temp = 0;
                temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
        quicksort(arr,l,j);
        quicksort(arr,j+1,r);
    }

以数组中第一位数字为基准

    //找第一个数字
    public static void quicksort2(int[] arr,int l,int r){
        if(l>=r){
            return;
        }
        int value = arr[l];
        int i = l;
        int j = r;
        while(i<j){
            while (arr[j]>=value&&i<j){
                j--;
            }
            arr[i]=arr[j];
           while (arr[i]<=value&&i<j){
               i++;
           }
            arr[j]=arr[i];
        }
        arr[i]=value;
        quicksort2(arr,l,j);
        quicksort2(arr,j+1,r);
    }

归并排序

归并排序图解


    private static void guibing(int[] arr,int start,int end) {
        if (start>=end){
            return;
        }
        int middle = (start+end)/2;//3  //0
        guibing(arr,start,middle);
        guibing(arr,middle+1,end);

        //默认已经是分好的数组
        int[] newArr = new int[end-start+1];
        int mid = middle;//4
        int i=start;
        int j = mid+1;//5
        int temp=0;
        while (i<=mid && j<=end){
            if(arr[i]<=arr[j]){
                newArr[temp] = arr[i];
                temp++;
                i++;
            } else {
                newArr[temp] = arr[j];
                temp++;
                j++;
            }
        }
        while (j<=end){
            newArr[temp] = arr[j];
            temp++;
            j++;
        }
        while (i<=mid){
            newArr[temp] = arr[i];
            temp++;
            i++;
        }
        //把临时数组中的数据重新存入原数组
        for(int k=0;k<temp;k++){
            arr[k+start] = newArr[k];
        }
    }

基数排序

  1. 基数排序属于“分配式排序”,又称桶排序,通过键值的各个位的值,将要排序的元素分配至某些“桶”中,达到排序的效果
  2. 基数排序法是属于稳定性的排序,基数排序法是效率高的稳定性排序法
  3. 基数排序是桶排序的扩展
  4. 基数排序是1887年赫尔曼.何乐礼发明的,他是这样实现的:将整数按位数切割成不同的数字,然后按每个位数分别比较

基数排序基本思想

  1. 将所有待比较数值统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位一直到最高位排序完成以后,数列就变成一个有序序列
  2. 基数排序是使用空间换时间的经典算法

基数排序的图文说明

第一轮

第二轮

第三轮

    private static void jishu(int[] arr) {
        //得到最大的位数
        int max = arr[0];
        for (int i=1;i<arr.length-1;i++){
            if(max<arr[i]){
                max=arr[i];
            }
        }
        int maxLength = (max+"").length();
        //定义十个桶,也就是一个二维数组
        int[][] bucket = new int[10][arr.length];
        //为了记录每个桶中,实际存放了多少个数据,我们定义一个一维数组来记录各个桶的每次放入的数据个数
        int[] bucketElementCounts = new int[10];
        for(int mode = 0;mode<maxLength;mode++){
            //将数据放入桶
            for (int i=0;i<arr.length;i++){
                int index = arr[i]/(int)Math.pow(10,mode)%10;//放到第几个桶
                bucket[index][bucketElementCounts[index]] = arr[i];
                bucketElementCounts[index]++;
            }
            int index = 0;
            //将数据从桶中取出来
            for(int i=0;i<bucketElementCounts.length;i++){
                //判断桶中是否有数据
                if(bucketElementCounts[i]!=0){
                    for(int j=0;j<bucketElementCounts[i];j++){
                        arr[index++] = bucket[i][j];
                    }
                }
                //第一轮处理后将bucketElementCounts[i]清0
                bucketElementCounts[i]=0;
            }
        }
    }

各算法时间复杂度统计图

以上是关于基础排序算法总结(代码+图片分析)的主要内容,如果未能解决你的问题,请参考以下文章

排序算法基础总结

排序算法基础总结

7.2堆排序的代码分析(算法基础—排序算法)

七种常见的排序算法总结

九大基础排序算法总结

TimSort算法分析