Java九大排序通俗易懂

本篇内容参考百度经验得到相关概念,为了帮助更多有需要的人。代码也都有注解齐全通俗易懂

1.选择排序(selection Sort)

算法描述:
Step1:将待排序数组分为有序和无序两组(初始情况下有序组为空)

Step2:从左向右扫描无序组,找出最小的元素,将其放置在无序组的第一个位置。至此有序组++,无序组–;

Step3:重复Step2,直至无序组只剩下一个元素。算法结束。

public class 选择排序 {
    public static void main(String[] args) {
        int [] arr=new int[]{12,354,65,8,23,656,89};
        paixu(arr);
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+"\t");
        }
    }
    /**
     * 由大到小排序
     */
/*    static void paixu(int []number){
        int len = number.length;
        int temp=0;
        for (int i = 0; i < len; i++) {
            for(int j=i;j<len;j++){
                if(number[j]>number[i]){
                    temp=number[j];
                    number[j]=number[i];
                    number[i]=temp;
                }
            }
        }
    }*/
    /**
     * 由小到大排序
     */
    static void paixu(int []number){
        int len = number.length;
        int temp=0;
        for (int i = 0; i < len; i++) {
            for(int j=i;j<len;j++){
                if(number[j]<number[i]){
                    temp=number[j];
                    number[j]=number[i];
                    number[i]=temp;
                }
            }
        }
    }
}

2.冒泡排序(Bubble Sort)

算法描述:
Step1:比较相邻的元素。如果第一个比第二个大,就交换他们两个

Step2:对每一对元素均进行此操作,经过一轮后最大的元素应位于最后一位

Step3:从第一个元素重复进行前两步,每一轮最后一个元素都不参与比较,进行n轮算法结束。


public class 冒泡排序 {
    public static void main(String[] args) {
        int [] arr=new int[]{12,354,65,8,23,656,89};
        paixu(arr);
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+"\t");
        }
    }
    /**
     *由小到大排序
     */

  /*  static void paixu(int[] numbers){
        int len = numbers.length;
        int temp=0;
        for(int j=0;j<len;j++) {
            for (int i = 0; i < len - 1 - j; i++) {
                if (numbers[i + 1] < numbers[i]) {
                    temp = numbers[i + 1];
                    numbers[i + 1] = numbers[i];
                    numbers[i] = temp;
                }
            }
        }
    }*/
    /**
     *由大到小排序,使用双层循环就能解决每次循环得到最大值或最小值之后最后一位应该不计入下次循环的问题
     */

    static void paixu(int[] numbers){
        int len = numbers.length;
        int temp=0;
        for(int j=0;j<len;j++) {
            for (int i = 0; i < len - 1 - j; i++) {
                if (numbers[i + 1] > numbers[i]) {
                    temp = numbers[i + 1];
                    numbers[i + 1] = numbers[i];
                    numbers[i] = temp;
                }
            }
        }
    }

}

3.希尔排序(Shell Sort)—插入排序的优化

算法描述:
Step1:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序。

Step2:依次缩减增量再进行排序。

Step3:待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。算法结束。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序相较于前几种方法有较大的提升。

package 排序;

public class 希尔排序 {
    public static void main(String[] args) {
        int [] arr=new int[]{12,354,65,8,23,656,89};
        sort(arr);
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+"\t");
        }
    }

    /**
     * 希尔排序,快速排序的进阶,按增量分成组,再逐渐减小增量
     * 没看太明白,有机会再看吧
     *
     * 懂了:
     *     快排的进阶,按增量分成组,逐渐减小增量,从增量的位置开始 ,依次和相差一个增级别的数据进行比较,
     *     将像个同一增量的的所有数据两两比较进行排序,再减小增量重复上述操作,直到所有的数据全部处理完成。
     * @param ins
     */

    public static void sort(int[] ins){
        int n = ins.length;
        int step = n/2;
        while(step > 0){
            for(int j = step; j < n; j++){
                int i=j;
                int temp=0;
                while(i >= step && ins[i- step] > ins[i]){
                    // 交换ins[i-step]和ins[i]的值
                    temp=ins[i-step];
                    ins[i-step]=ins[i];
                    ins[i]=temp;
                    i-=step;
                }
            }
            step = step /2;
        }
    }
}

4.快速排序(Quick Sort)

算法描述:
Step1:在待排序列中选取一个轴点(pivot),通常选取中间点

Step2:将轴点与其他元素进行比较,将比轴点小的元素放在轴点之前,比轴点大的元素放在轴点之后。至此,pivot已被排好序

Step3:对0-(pivot-1)和(pivot+1)-n分别递归进行上述两步。算法结束。

package 排序;

public class 快速排序 {
    public static void main(String[] args) {
        int[] arr = {10,7,2,4,7,62,3,4,2,1,8,9,19};
        quickSort(arr, 0, arr.length-1);
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+"\t");
        }
    }
    public static void quickSort(int []arr,int low ,int high){

        // 1.选基准数
        // 2.讲述组分成两组,左半边和右半边,但是没有严格界限,左边放的值都比基准值小,右边都比基准值大
        // 3.将基准数与左半边依次相比较,寻找比其大的值,将基准值与右半边依次相比较,寻找比基准值小的值,交换这两个的值,i++,j--,直到i=j,循环截至
        // 4.将基准值与i=j时所对应的值进行交换。这一步没想明白原因
        // 5.左右半边重复上述操作
        if(low>high){
            return;
        }
        int i=low,j=high,t;
        int 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[i];
                arr[i]=arr[j];
                arr[j]=t;
//                t = arr[j];
//                arr[j] = arr[i];
//                arr[i] = t;
            }
        }
        arr[low]=arr[i];
        arr[i]=temp;

        quickSort(arr,low,j-1);
        quickSort(arr,j+1,high);
    }
}


5.归并排序(Merge Sort)

算法描述:
Step1:把待排序的列表划分为分成近似相等的两部分

Step2:分别将两个子列表排序(递归进行)

Step3:然后再合并成一个完整的列表算法结束。

package 排序;

public class 归并排序 {
    public static void main(String[] args) {
        int [] arr=new int[]{12,354,65,8,23,656,89,66};
        sort(arr,0,7);
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+"\t");
        }
    }
    public static void sort(int[] a,int low,int high){
        int mid = (low+high)/2;
        if(low<high){
            sort(a,low,mid);
            sort(a,mid+1,high);
            //左右归并
            merge(a,low,mid,high);
        }
    }
    public static void merge(int[] a, int low, int mid, int high) {
        int[] temp = new int[high-low+1];
        int i= low;
        int j = mid+1;
        int k=0;
        // 把较小的数先移到新数组中
        while(i<=mid && j<=high){
            if(a[i]<a[j]){
                temp[k++] = a[i++];
            }else{
                temp[k++] = a[j++];
            }
        }
        // 把左边剩余的数移入数组
        while(i<=mid){
            temp[k++] = a[i++];
        }
        // 把右边边剩余的数移入数组
        while(j<=high){
            temp[k++] = a[j++];
        }
        // 把新数组中的数覆盖nums数组
        /**
         * 这部分没看懂
         *
         * 看懂了,x=low指的是从0+low位置为起始位置开始赋值,因为原数组已经被分为若干个小的数组
         */
        for(int x=0;x<temp.length;x++){
            a[x+low] = temp[x];
        }
    }
}

6.堆排序(Heap Sort)

算法描述: 堆的定义:堆是一棵完全二叉树或者是近似完全二叉树。根结点(亦称为堆顶)的关键字是堆里所有结点关键字中最小者的堆称为小根堆,又称最小堆。根结点(亦称为堆顶)的关键字是堆里所有结点关键字中最大者,称为大根堆,又称最大堆。

Step1:建堆,序列分成无序和有序两组(初始有序为0)

Step2:取出堆顶最大的元素,与待排序列的最后一个元素作交换,至此,无序组–,有序组++,并对无序组进行堆调整

Step3:重复上述步骤,直至无序组仅剩一个元素算法结束。

package 排序;

/**
 * 堆排序演示
 *
 * @author Lvan
 */
public class 堆排序 {
    public static void main(String[] args) {
//        int[] arr = {5, 1, 7, 3, 1, 6, 9, 4};
        int[] arr = {16, 7, 3, 20, 17, 8};

        heapSort(arr);

        for (int i : arr) {
            System.out.print(i + " ");
        }
    }


    /**
     * 创建堆,
     * @param arr 待排序列
     */
    private static void heapSort(int[] arr) {
        //创建堆
        for (int i = (arr.length - 1) / 2; i >= 0; i--) {
            //从第一个非叶子结点从下至上,从右至左调整结构
            adjustHeap(arr, i, arr.length);
        }

        //调整堆结构+交换堆顶元素与末尾元素
        for (int i = arr.length - 1; i > 0; i--) {
            //将堆顶元素与末尾元素进行交换
            int temp = arr[i];
            arr[i] = arr[0];
            arr[0] = temp;

            //重新对堆进行调整
            adjustHeap(arr, 0, i);
        }
    }

    /**
     * 调整堆
     * @param arr 待排序列
     * @param parent 父节点
     * @param length 待排序列尾元素索引
     */
    private static void adjustHeap(int[] arr, int parent, int length) {
        //将temp作为父节点
        int temp = arr[parent];
        //左孩子
        int lChild = 2 * parent + 1;

        while (lChild < length) {
            //右孩子
            int rChild = lChild + 1;
            // 如果有右孩子结点,并且右孩子结点的值大于左孩子结点,则选取右孩子结点
            if (rChild < length && arr[lChild] < arr[rChild]) {
                lChild++;
            }

            // 如果父结点的值已经大于孩子结点的值,则直接结束
            if (temp >= arr[lChild]) {
                break;
            }

            // 把孩子结点的值赋给父结点
            arr[parent] = arr[lChild];

            //选取孩子结点的左孩子结点,继续向下筛选
            parent = lChild;
            lChild = 2 * lChild + 1;
        }
        arr[parent] = temp;
    }
}

7.基数排序(Radix Sort)

算法描述:
LSD:
Step1:将待排序的元素按照最后一位进行分桶操作(桶按照最后一位排序从大到小)

Step2:按顺序将各个桶中的数据连接起来,形成新的序列

Step3:依次对新序列的倒数第二位至第一位进行上述两步操作算法结束

MSD:
Step1:将待排序的元素按照最高位进行分桶操作

Step2:对每个桶的按照第二位进行再次分桶(递归进行)

Step3:进行至最后一位分桶操作完成后,对每个桶进行合并操作,得到有序序列算法结束

package 排序;

import java.util.Arrays;

public class 基数排序 {
    public static void main(String[] args) {
        int[] arr = {63, 157, 189, 51, 101, 47, 141, 121, 157, 156,
                194, 117, 98, 139, 67, 133, 181, 12, 28, 0, 109};

        radixSort(arr);

        System.out.println(Arrays.toString(arr));
    }

    /**
     * 高位优先法
     *
     *
     *
     * @param arr 待排序列,必须为自然数
     */
    private static void radixSort(int[] arr) {
        //待排序列最大值
        int max = arr[0];
        int exp;//指数

        //计算最大值
        for (int anArr : arr) {
            if (anArr > max) {
                max = anArr;
            }
        }

        //从个位开始,对数组进行排序
        for (exp = 1; max / exp > 0; exp *= 10) {
            //存储待排元素的临时数组
            int[] temp = new int[arr.length];
            //分桶个数
            int[] buckets = new int[10];

            //将数据出现的次数存储在buckets中
            for (int value : arr) {
                //(value / exp) % 10 :value的最底位(个位)
                buckets[(value / exp) % 10]++;
            }

            //更改buckets[i],
            for (int i = 1; i < 10; i++) {
                buckets[i] += buckets[i - 1];
            }

            //将数据存储到临时数组temp中
            for (int i = arr.length - 1; i >= 0; i--) {
                temp[buckets[(arr[i] / exp) % 10] - 1] = arr[i];
                buckets[(arr[i] / exp) % 10]--;
            }

            //将有序元素temp赋给arr
            System.arraycopy(temp, 0, arr, 0, arr.length);
        }

    }
}

8.桶排序(Tree Sort)

桶排序 (Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。桶排序是鸽巢排序的一种归纳结果。当要被排序的数组内的数值是均匀分配的时候,桶排序使用线性时间(Θ(n))。但桶排序并不是 比较排序,他不受到 O(n log n) 下限的影响。

9.插入排序(Insert Sort)

算法描述:
Step1:将待排序数组分为有序和无序两组(初始情况下有序组为第一个元素)

Step2:取出无序组第一个元素(First_unsorted)放入临时空间,将first_unsorted与有序组从最后一个元素开始进行比较,如果比有序组小,则将有序组中的该元素向后移一位,直到找到第一个比first_unsorted小的时候,将first_unsorted放入。至此,有序组++,无序组–。

Step3:重复step2,直到无序组数量为0.算法结束。

package 排序;

public class 插入排序 {
    public static void main(String[] args) {
        int [] arr=new int[]{12,354,65,8,23,656,89};
        paixu(arr);
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+"\t");
        }
    }
    static void paixu(int[] numbers){
        int len = numbers.length;
        int temp=0;
        for(int j=0;j<len;j++) {
            for (int i = j; i > 0; i--) {
                // 从当前位置向前面挨个比较,将最小或最大放在前面
                // 将未排序数组依次在已排序数组中进行比较插入
                /**
                 * 由大到小排序
                 */
               /* if (numbers[i] > numbers[i-1]) {
                    temp = numbers[i];
                    numbers[i] = numbers[i-1];
                    numbers[i-1] = temp;
                }*/
                /**
                 * 由小到大排序
                 */
                if (numbers[i] < numbers[i-1]) {
                    temp = numbers[i];
                    numbers[i] = numbers[i-1];
                    numbers[i-1] = temp;
                }
            }
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值