七大基本排序算法图文详解

文章目录

    • 冒泡排序
      • 算法描述
    • 选择排序
      • 算法描述
    • 插入排序
      • 算法描述
    • 希尔排序
      • 算法描述
    • 快速排序
      • 算法描述
    • 归并排序
      • 算法描述
    • 基数排序(桶排序
      • 算法描述
      • 思路

冒泡排序

算法描述

1.i从0开始,i与i+1比较,如果i>i+1,那么就互换。
2.i不断增加,直到最后一个元素,一趟比较下来,最大的元素就放到了数组最后。
3.接着开始第二趟,第二趟完后倒数第二位也是第二大的数。
4.以此类推,5个数的数组就需要4趟比较,然后第⼀趟需要⽐较4次,第⼆趟需要⽐较3次,第三趟需要⽐较2次,第四躺需要⽐较1次。
5.我们在比较过程中可能第二趟就排好序了,之后的比较也是多余的,所以我们可以设置一个变量,在比较数据过程里如果发生置换该变量为1,最后每趟结束之前查看该变量,得知该趟是否发生置换,不发生置换就可以结束循环,说明已经排好序了。

代码实现:

public class Main {

    public static void sort(int []arrays){
    //装载临时变量
    int temp;
    //记录是否发⽣了置换, 0 表示没有发⽣置换、 1 表示发⽣了置换
    int isChange;
//外层循环是排序的趟数
for (int i = 0; i < arrays.length - 1; i++) {
        //每⽐较⼀趟就重新初始化为0
        isChange = 0;
        //内层循环是当前趟数需要⽐较的次数
        for (int j = 0; j < arrays.length - i - 1; j++) {
            //前⼀位与后⼀位与前⼀位⽐较,如果前⼀位⽐后⼀位要⼤,那么交换
            if (arrays[j] > arrays[j + 1]) {
                temp = arrays[j];
                arrays[j] = arrays[j + 1];
                arrays[j + 1] = temp;
                //如果进到这⾥⾯了,说明发⽣置换了
                isChange = 1;
            }
        }
        //如果⽐较完⼀趟没有发⽣置换,那么说明已经排好序了,不需要再执⾏下去了
        if (isChange == 0) {
            break;
        }
    }
}
    public static void main(String[] args) {
	int [] arr=new int[]{1,44,3,66,7,578,34,88,98};
	sort(arr);
	for (int a:arr){
	    System.out.println(a);
    }
    }
}

选择排序

算法描述

它的⼯作原理是每⼀次从待排序的数据元素中选出最⼩(或最⼤)的⼀个元素,存放在序列的起始(末尾)位置,直到全部待排序的数据元素排完。

我们这里选出最小的一个元素放在数组的起始位置,我们可以设置一个minIndex标志最小元素下标,初始时让下标为i,然后后面比较,如果有比这个小的,交换下标,之后再判断minIndex不为i,就交换真实数据,把最小的放在最前面,接着再开启第二轮,以此循环直到所有排序完成。

public class Main {

    public  static  void sort(int []array){//选择排序
        int minindex;//最小值的下标
        for (int i=0;i<array.length;i++){
            minindex=i;//假设最小值索引为i,
            for (int j=i+1;j<array.length;j++) {
                if (array[j] < array[minindex]) {
                    minindex = j;//从i+1开始,往后一个个比较,找出最小的那个
                }
                if (minindex != i) {//minIndex为i,不需要交换
                    int temp = array[i];
                    array[i] = array[minindex];//然后交换,把最小的放在前面
                    array[minindex] = temp;
                }
            }
        }
    }
    public static void main(String[] args) {
        int [] a=new int[]{7,40,64,64,88,99,36};
      sort(a);
      for (int arr:a){
          System.out.println(arr);
      }
    }
}

插入排序

算法描述

插⼊排序的基本操作就是将⼀个数据插⼊到已经排好序的有序数据中,从⽽得到⼀个新的、个数加⼀的有序数据,算法适⽤于少量数据的排序,时间复杂度为O(n^2)。是稳定的排序⽅法。

我们这里每插入一个数据,就反向遍历,从后往前,比较前一个元素与后一个元素大小,前一个元素大则交换,循环此方法直到插入所有数据

public class Main {

    public static  void sort(int []array){
        for (int i=0;i<array.length;i++){//插入排序法,元素一个一个加进去
            for (int j=i-1;j>=0;j--){//每插入一个元素,进行一次反向遍历,从后往前,看前一个元素是否大于后一个元素,若大于,则交换,最后得到的可就是从小到大的顺序数组
                if (array[j]>array[j+1]){
                    int temp=array[j];
                    array[j]=array[j+1];
                    array[j+1]=temp;
                }
            }
        }
    }
    public static void main(String[] args) {
	int [] arr=new int[]{8,33,88,94,65,64,63};
	sort(arr);
	for (int a:arr){
	    System.out.println(a);
	           }
    }
}

希尔排序

算法描述

希尔排序是插入排序的高级版本,我们这里把希尔排序分组,不停的使用插入排序,最后的插入排序就无需过多的移位或交换,我们这里的增量序列可以表示为:{n/2,(n/2)/2…1} ,每次都 /2。
七大基本排序算法图文详解_第1张图片
七大基本排序算法图文详解_第2张图片

public class Main {

    public  static void sort(int [] array){
        int gap=array.length/2;//划分的组数,
        int current;//定义个当前元素值
        while (gap>0){

            for (int j=gap;j<array.length;j++){
                current=array[j];
                int preIndex=j-gap;//同一个组中的前一个元素

                //进行插入排序
                while (preIndex>=0 && current<array[preIndex]){//当前元素小于组内前一个元素
                    array[preIndex+gap]=array[preIndex];//交换当前元素为组内前一个元素
                    preIndex=preIndex-gap;//preIndex=preIndex-gap,找到组内前一个元素的前一个元素下标
                     array[preIndex+gap]=current;//交换前一个元素值为当前元素值
                }
            }
            gap=gap/2;//数组循环
        }
    }
    public static void main(String[] args) {

        int [] a=new int[]{1,2,8,99,33,47,58,76,28,94,37};
        sort(a);
        for (int arr:a){
            System.out.println(arr);
        }
    }
}

快速排序

算法描述

基本思想:通过⼀趟排序将要排序的数据分割成独⽴的两部分,其中⼀部分的所有数据都⽐另外⼀部分的所有数据都要⼩,然后再按此⽅法对这两部分数据分别进⾏快速排序,整个排序过程可以递归进⾏,以此达到整个数据变成有序序列。
七大基本排序算法图文详解_第3张图片
快速排序的过程大致如上:
1.先定义一个基准数字,一般初始化:左边起始位置元素为基准数字,接着从右边往左边遍历,找到比基准数字小的元素,左边也往右遍历找比基准数字大的元素,然后再交换两个元素。
2.循环以上步骤,直到左边的i等于右边的j,跳出循环后,把基准数字与i位置的值互换,这样基准数字的左边都比它小,右边都比它大。
3.递归实现左边数字二次分类和右边二次分类

public class Main {

    public static void sort(int [] arr,int left,int right){
        if (left>right){//设置排序结束的条件,left表示左边起始位置,right表示右边起始位置
            return;
        }
        int base=arr[left];//基准数字,刚开始设置为左边起始位置
        int i=left;int j=right;
        while (i!=j){
            while (j>i&&arr[j]>=base){//从右边往左边遍历,直到找到一个比基准数字小的值
                j--;
            }
            while (i<j&&arr[i]<=base){//从左边往右边遍历,直到找到比基准数字大的值
                i++;
            }
            if (i<j){//交换两个值
                int temp=arr[i];
                arr[i]=arr[j];
                arr[j]=temp;
            }
        }
        //跳出循环后,基准数字和i位置的值要交换,这样基准数字的左边数字全比它小,右边的数字全比它大
        arr[left]=arr[i];
        arr[i]=base;
        //左侧数字二次分类
        sort(arr, left, i-1);
        //右侧数字二次分类
        sort(arr,i+1,right);


    }
    public static void sort(int [] array){
        sort(array,0,array.length-1);
    }
    public static void main(String[] args) {
        int [] a=new int[]{12,23,45,65,76,87,34,566,4545,65,2,3,847,589};
        sort(a);
        for (int b:a){
            System.out.println(b);
        }

    }
}

归并排序

算法描述

1.演算归并排序过程
如,我们现在已经有两个排好顺序的数组 ,int [ ]arr1={1,3,5}和int [ ] arr2={2,4,6},然后还有一个大数组装载int [ ] arr=new int [6];

首先我们先将两个数组的值比较,谁小谁就放进大数组里,
先拿出arr1[0]和arr2[0]进行比较,显然arr1[0]小,放入数组中,且arr1指针往后跳一格,则arr={1};
接着再拿arr1[1]和arr2[0]进行比较,则arr2[0]小,放入数组中,且arr2指针往后跳一格,arr={1,2};
以此类推,直到两个数组的所有元素放入大数组中,这就是归并排序。

以上是归并排序的核心算法,但是我们拿到的数组都是杂乱无章的一个数组,我们需要用分治法,得到两个排好序的数组,所以步骤就是先拆分再合并;

public class Main {
    public static void mergeSort(int[] arrays, int L, int R) {//L指最左边元素,R指最右边元素
        //如果只有⼀个元素,那就不⽤排序了
        if (L == R) {
            return;
        } else {
            //取中间的数,进⾏拆分
            int M = (L + R) / 2;
            //左边的数不断进⾏拆分
            mergeSort(arrays, L, M);
            //右边的数不断进⾏拆分
            mergeSort(arrays, M + 1, R);
            //合并
            merge(arrays, L, M + 1, R);
        }
    }
    /**
     * 合并数组
     *
     * @param arrays
     * @param L 指向数组第⼀个元素
     * @param M 指向数组分隔的元素
     * @param R 指向数组最后的元素
     */
    public static void merge(int[] arrays, int L, int M, int R) {
        //左边的数组的⼤⼩
        int[] leftArray = new int[M - L];
        //右边的数组⼤⼩
        int[] rightArray = new int[R - M + 1];
        //往这两个数组填充数据
        for (int i = L; i < M; i++) {
            leftArray[i - L] = arrays[i];
        }
        for (int i = M; i <= R; i++) {
            rightArray[i - M] = arrays[i];
        }
        int i = 0, j = 0;
        // arrays数组的第⼀个元素
        int k = L;
        //⽐较这两个数组的值,哪个⼩,就往数组上放
        while (i < leftArray.length && j < rightArray.length) {
            //谁⽐较⼩,谁将元素放⼊⼤数组中,移动指针,继续⽐较下⼀个
            if (leftArray[i] < rightArray[j]) {
                arrays[k] = leftArray[i];
                i++;
                k++;
            } else {
                arrays[k] = rightArray[j];
                j++;
                k++;
            }
        }
        //如果左边的数组还没⽐较完,右边的数都已经完了,那么将左边的数抄到⼤数组中(剩下的都是大数字

        while (i < leftArray.length) {
            arrays[k] = leftArray[i];
            i++;
            k++;
        }
        //如果右边的数组还没⽐较完,左边的数都已经完了,那么将右边的数抄到⼤数组中(剩下的都是大数字

        while (j < rightArray.length) {
            arrays[k] = rightArray[j];
            k++;
            j++;
        }
    }
    public static void main(String[] args) {

        int [] arr=new int[]{33,434,5,3,26,7,6,76,34,98,45};
        mergeSort(arr,0,arr.length-1);
        for (int a:arr){
            System.out.println(a);
        }
    }
}

基数排序(桶排序

算法描述

首先我们有一个数组

int[] arrays = {6, 4322, 432, 344, 55 };

然后我们有10个桶子,每个桶子能装下array.length个数字

int[][] buckets = new int[arrays.length][10];

第一次分配与回收
将数组的每个元素的个位数分配到桶子里面
七大基本排序算法图文详解_第4张图片
按顺序回收,得到的结果为:{4322,432,344,55,6}
第二次分配与回收
将数组的每个元素的十位数分配到不同的桶子里(这里的6补0做十位)
七大基本排序算法图文详解_第5张图片
按顺序回收,得到的结果为:{6,4322,432,344,55}
第三次分配与回收
将数组的每个元素的百位数分配到不同的桶子里

七大基本排序算法图文详解_第6张图片
按顺序回收,得到的结果为:{6,55,4322,344,432}
第四次回收与分配
将数组的每个元素的千位数分配到不同的桶子里

七大基本排序算法图文详解_第7张图片
最后得到排序结果:{6,55,344,432,4322}

思路

我们的基数排序是按照个,十,百,千,万进行存放的,我们一般不理会数组元素内的值,那我们怎么去获得他们的位数呢,这里可以这样做:
先求出数组最大值,然后不断除以10,只要它大于0,说明位数还有
所以我们要先求出数组的最大值(这里我用FOR循环,也可以递归):

public static int findMax(int [] arr,int L,int R){
        if (L==R){
            return arr[L];
        }
        int max=arr[L];
        for (int i=L+1;i<=R;i++){
            if (max<arr[i]){
                max=arr[i];
            }

        }
        return max;
    }

代码实现:

public static void sort(int []array){
        int max=findMax(array,0,array.length-1);

        //需要遍历的次数由数组最⼤值的位数来决定
        for (int i=1;max/i>0;i=i*10){
            int [][]buckets=new int[array.length][10];
            for (int j=0;j<array.length;j++){//获取每⼀位数字(个、⼗、百、千位...分配到桶⼦⾥)
                int num=(array[j]/i)%10;
                buckets[j][num]=array[j];
            }
            //回收桶⼦⾥的元素
            int k=0;
            for (int j=0;j<10;j++){
            //对每个桶⼦⾥的元素进⾏回收
                for (int m=0;m<array.length;m++){
                    if (buckets[m][j]!=0){//如果桶⼦⾥⾯有元素就回收
                        array[k++]=buckets[m][j];
                    }
                }
            }
        }
    }
     public static void main(String[] args) {

        int []arr=new int[]{1,6,4,8,3,0,8,4,45,76,87};
        sort(arr);
        for (int a:arr){
            System.out.println(a);
        }
    }

你可能感兴趣的:(算法)