8个常用的排序算法

Posted 77的小白

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了8个常用的排序算法相关的知识,希望对你有一定的参考价值。

8个常用的排序算法

冒泡排序

冒泡排序思路比较简单:

  1. 将序列当中的左右元素,依次比较,保证右边的元素始终大于左边的元素;
    ( 第一轮结束后,序列最后一个元素一定是当前序列的最大值;)
  2. 对序列当中剩下的n-1个元素再次执行步骤1。
  3. 对于长度为n的序列,一共需要执行n-1轮比较
    (利用while循环可以减少执行次数)
package com.xiaobai.callable;

import java.util.Arrays;

public class Test {
    public static void main(String[] args) {
        int[] arrays = {24,523,-3,1202,25,63,354,0};
        sort(arrays);
        System.out.println(Arrays.toString(arrays));
    }


    public static int[] sort(int[] arrays){
        int temp;
        for (int i = 0; i < arrays.length-1; i++) {
            boolean flag = true;
            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;
                    flag = false;
                }
            }
            if (flag){
                break;
            }
        }
        return arrays;
    }
}

插入排序

插入排序是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

算法步骤:

1)将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。

2)从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)

package com.xiaobai.callable;

import java.util.Arrays;

public class Test {
    public static void main(String[] args) {
        int[] arrays = {24,523,-3,1202,25,63,354,0};
        sort(arrays);
        System.out.println(Arrays.toString(arrays));
    }


    public static int[] sort(int[] arrays){
        for (int i = 1; i < arrays.length; i++) {
            int key = arrays[i];
            int j = i-1;
            while (j>=0&&arrays[j]>key){
                arrays[j+1]=arrays[j];
                j--;
            }
            arrays[j+1]=key;
        }
        return arrays;
    }
}

希尔排序

希尔排序的算法思想:将待排序数组按照步长gap进行分组,然后将每组的元素利用直接插入排序的方法进行排序;每次将gap折半减小,循环上述操作;当gap=1时,利用直接插入,完成排序。
同样的:从上面的描述中我们可以发现:希尔排序的总体实现应该由三个循环完成:

  1. 第一层循环:将gap依次折半,对序列进行分组,直到gap=1
  2. 第二、三层循环:也即直接插入排序所需要的两次循环。具体描述见上。
package com.xiaobai.callable;

import java.util.Arrays;

public class Test {
    public static void main(String[] args) {
        int[] arrays = {24,523,-3,1202,25,0,24,0};
        shell_sort(arrays);
        System.out.println(Arrays.toString(arrays));
    }


    public static int[] sort(int[] arrays,int grp){
        for (int i = grp; i < arrays.length; i++) {
            int key = arrays[i];
            int j = i-grp;
            while (j>=0&&arrays[j]>key){
                arrays[j+grp]=arrays[j];
                j-=grp;
            }
            arrays[j+grp]=key;
        }
        return arrays;
    }

    public static int[] shell_sort(int[] arrays){
        int grp = arrays.length/2;
        while (grp>=1){
            arrays = sort(arrays,grp);
            grp=grp/2;

        }


        return arrays;
    }
}

选择排序

原理:选择排序与冒泡排序有点像,只不过选择排序每次都是在确定了最小数的下标之后再进行交换,大大减少了交换的次数

package com.xiaobai.callable;

import java.util.Arrays;

public class Test {
    public static void main(String[] args) {
        int[] arrays = {24,523,-3,1202,25,0,24,0};
        sort(arrays);
        System.out.println(Arrays.toString(arrays));
    }


    public static int[] sort(int[] arrays){
        for (int i = 0; i < arrays.length-1; i++) {
            int min = i;
            for (int j = i; j < arrays.length; j++) {
                if (arrays[min]>arrays[j]){
                    min = j;
                }
            }
            if (i!=min){
                int key = arrays[i];
                arrays[i]=arrays[min];
                arrays[min]=key;
            }
        }
        return arrays;
    }

}

堆排序

原理:假设序列有n个元素,先将这n建成大顶堆(父节点比2个子子节点都大),然后取堆顶元素,与序列第n个元素交换,然后调整前n-1元素,使其重新成为堆,然后再取堆顶元素,与第n-1个元素交换,再调整前n-2个元素...直至整个序列有序。

详细可看:快速入门堆排序

package com.xiaobai.callable;

import java.util.Arrays;

public class Test {
    public static void main(String[] args) {
        int[] arrays = {24,523,-3,1202};
        sort(arrays);
        System.out.println(Arrays.toString(arrays));
    }


    public static int[] sort(int[] a){
        // 把无序数组构建成最大堆, 这里-2,是因为从索引0开始、另外就是叶子节点【最后一层是不需要堆化的】
        for (int i = (a.length-2)/2; i >=0 ; i--) {
            addHeap(a, i, a.length);
        }
        // 循环删除堆顶元素,并且移到集合尾部,调整堆产生新的堆顶
        for (int i = a.length-1 ; i > 0 ; i--) {
            // 交换最后一个元素与第一个元素
            int temp = a[i];
            a[i]=a[0];
            a[0]=temp;
            // 下沉调整最大堆
            addHeap(a,0,i);
        }

        return a;
    }

    public static int[] addHeap(int[] a ,int parentIndex,int length){
        // temp保存父节点的值,用于最后赋值
        int temp = a[parentIndex];
        int chirldIndex = parentIndex*2+1;
        while (chirldIndex<length){
            // 如果有右孩子,且右孩子大于左孩子的值,则定位到右孩子
            // 这里其实是比较左、右子树的大小,选择更大的
            if(chirldIndex+1<length&&a[chirldIndex+1]>a[chirldIndex]){
                chirldIndex++;
            }
            // 如果父节点大于任何一个孩子得值,则直接跳出
            if (temp>a[chirldIndex]){
                break;
            }
            // 当左、右子树比父节点更大,进行交换
            a[parentIndex]=a[chirldIndex];
            //子节点变为父节点,循环判断
            parentIndex = chirldIndex;
            chirldIndex = parentIndex*2+1;
        }
        //将原始父节点插入空出来的父节点
        a[parentIndex]=temp;


        return  a;
    }
}

快速排序

原理:
通过一趟排序将序列分成左右两部分,其中左半部分的的值均比右半部分的值小,
然后再分别对左右部分的记录进行排序,直到整个序列有序。

详细讲解:快速排序详解

package com.xiaobai.callable;

import java.util.Arrays;

public class Test {
    public static void main(String[] args) {
        int[] arrays = {24,523,-3,1202,52,0,24,585,102};
        sort(arrays,0, arrays.length-1);
        System.out.println(Arrays.toString(arrays));
    }


    public static int[] sort(int[] a,int low,int high){
        if (low<high){
            // 找寻基准数据的正确索引
            int index = getIndex(a, low, high);
            // 进行迭代对index之前和之后的数组进行相同的操作使整个数组变成有序
            sort(a,low,index-1);
            sort(a,index+1, high);
        }


        return a;
    }

    public static int getIndex(int[]a,int low,int high){
        // 基准数据
        int temp = a[low];
        while (low<high){
            // 当队尾的元素大于等于基准数据时,向前挪动high指针
            while (low<high&&a[high]>=temp){
                high--;
            }
            // 如果队尾元素小于tmp了,需要将其赋值给low
            a[low]=a[high];
            // 当队首元素小于等于tmp时,向前挪动low指针
            while (low<high&&a[low]<=temp){
                low++;
            }
            // 当队首元素大于tmp时,需要将其赋值给high
            a[high]=a[low];
        }
        // 跳出循环时low和high相等,此时的low或high就是tmp的正确索引位置
        // 由原理部分可以很清楚的知道low位置的值并不是tmp,所以需要将tmp赋值给arr[low]
        a[low]=temp;
        return low;// 返回tmp的正确位置
    }
}

归并排序

归并详细讲解

package com.xiaobai.callable;

import java.util.Arrays;

public class Test {
    public static void main(String[] args) {
        int[] arrays = {24,523,-3,1202,52,0,24,585,102};
        sort(arrays);
        System.out.println(Arrays.toString(arrays));
    }


    public static void sort(int []arr){
        int []temp = new int[arr.length];//在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间
        sort(arr,0,arr.length-1,temp);
    }
    private static void sort(int[] arr,int left,int right,int []temp){
        if(left<right){
            int mid = (left+right)/2;
            sort(arr,left,mid,temp);//左边归并排序,使得左子序列有序
            sort(arr,mid+1,right,temp);//右边归并排序,使得右子序列有序
            merge(arr,left,mid,right,temp);//将两个有序子数组合并操作
        }
    }
    private static void merge(int[] arr,int left,int mid,int right,int[] temp){
        int i = left;//左序列指针
        int j = mid+1;//右序列指针
        int t = 0;//临时数组指针
        while (i<=mid && j<=right){
            if(arr[i]<=arr[j]){
                temp[t++] = arr[i++];
            }else {
                temp[t++] = arr[j++];
            }
        }
        while(i<=mid){//将左边剩余元素填充进temp中
            temp[t++] = arr[i++];
        }
        while(j<=right){//将右序列剩余元素填充进temp中
            temp[t++] = arr[j++];
        }
        t = 0;
        //将temp中的元素全部拷贝到原数组中
        while(left <= right){
            arr[left++] = temp[t++];
        }
    }
}

基数排序

菜鸟教程:基数排序

以上是关于8个常用的排序算法的主要内容,如果未能解决你的问题,请参考以下文章

图解程序员必须掌握的Java常用8大排序算法

排序算法1-选择排序

Java 常用排序算法/程序员必须掌握的 8大排序算法

Java常用排序算法/程序员必须掌握的8大排序算法

Java常用的八种排序算法与代码实现

Java排序算法 - 堆排序的代码