java八大排序


在这里插入图片描述

1、冒泡排序

冒泡排序原理:相邻元素两两比较,大的往后放,第一次完毕,最大值出现在了最大索引处
冒泡排序图解:
在这里插入图片描述

代码演示:

package 八大排序;

import java.util.Arrays;

public class 冒泡排序 {
    public static void main(String[] args) {
        //冒泡排序的原理:相邻元素两两比较,大的往后放,第一次完毕,最大值出现在了最大索引处
        int[] arr={4,21,5,86,74,12};
        //外层循环次数是数组长度减一,从索引0开始
        for (int i = 0; i < arr.length-1; i++) {
            //里层循环次数是数组长度减第几轮循环
            for (int j = 0; j < arr.length-1-i; j++) {
                if(arr[j]>arr[j+1]){
                    int t=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=t;
                }
            }
        }
        System.out.println(Arrays.toString(arr));
    }
}

2、选择排序

选择排序原理:从0索引开始,依次和后面元素比较,小的往前放,第一次完毕,最小值出现在了最小索引处
选择排序图解:
在这里插入图片描述
代码实现:

package 八大排序;

import java.util.Arrays;

public class 选择排序 {
    public static void main(String[] args) {
        //选择排序原理:从0索引开始,依次和后面元素比较,小的往前放,第一次完毕,最小值出现在了最小索引处
        int[] arr={4,21,5,86,74,12};
        //外层循环次数是数组长度减一,从索引0开始
        for (int i = 0; i < arr.length-1; i++) {
            //里层循环次数是数组长度减第几轮循环
            for (int j = i+1; j < arr.length; j++) {
                if(arr[i]>arr[j]){
                    int t=arr[i];
                    arr[i]=arr[j];
                    arr[j]=t;
                }
            }
        }
        System.out.println(Arrays.toString(arr));
    }
}

3、直接插入排序

直接插入排序原理:从1索引处开始,将后面的元素插入到之前的有序列表中,使之仍保持有序
直接插入排序图解:
在这里插入图片描述
代码演示:

package 八大排序;

import java.util.Arrays;

public class 直接插入排序 {
    public static void main(String[] args) {
        //直接插入排序的原理:从1索引处开始,将后面的元素插入到之前的有序列表中,使之仍保持有序
        int[] arr={4,21,5,86,74,12};
        //外层循环次数是数组长度减一,从索引1开始
        for (int i = 1; i < arr.length; i++) {
            //里层循环进行比较插入
            while (arr[i]<arr[i-1]){
                int t=arr[i];
                arr[i]=arr[i-1];
                arr[i-1]=t;
                //让i自减,可以使它继续和前面的元素进行比较,加上判断条件,是为了防止索引越界
                if(i>1){
                    i--;
                }
            }
        }
        System.out.println(Arrays.toString(arr));
    }
}

4、希尔排序

希尔排序原理:他是对插入排序的一个优化,核心的思想就是合理的选取增量,经过一轮排序后,就会让序列大致有序,然后再不断地缩小增量,进行插入排序,直到增量为 1,那整个排序结束
希尔排序图解:在这里插入图片描述
代码演示:

package 八大排序;

import java.util.Arrays;

public class 希尔排序 {
    public static void main(String[] args) {
        //希尔排序原理:他是对插入排序的一个优化,核心的思想就是合理的选取增量,经过一轮排序后,就会让序列大致有序
        //然后再不断地缩小增量,进行插入排序,直到增量为 1,那整个排序结束
        int[] arr={4,21,5,86,74,12,57,42};
        //增量的大小最好定义为数组长度的一半,然后不断减半,直至为1
        for(int h=arr.length/2;h>0;h/=2){
            //里层循环次数=数组长度 - 增量大小
            for (int i=h;i<arr.length;i++){
                //里层循环次数=j/h,保证和间隔h的数比较后,再和间隔h的数进行比较,已达到有序的目的,例如:此时h=2,j=4,索引4的数和索引2的数比较后,继续和索引0的数进行比较,已达到有序的目的
                for(int j=i;j>h-1;j-=h){
                    if(arr[j]<arr[j-h]){
                        int t=arr[j];
                        arr[j]=arr[j-h];
                        arr[j-h]=t;
                    }
                }
            }
        }
        System.out.println(Arrays.toString(arr));
    }
}

5、快速排序

快速排序原理:分治法:比大小,再分区
实现步骤:
1.从数组中取出一个数,作为基准数
2.分区:将比这个数大的数放在它的右边,比它小的数放在它的左边(挖坑填数的思想)
挖坑填数思想:
(1):用基准数挖出形成第一个坑
(2):由后向前找比它小的数,找到后挖出此数填到前一个坑中
(3):由前向后找比它大或等于它的数,找到后挖出此数填到前一个坑中
3.再对左右区间重复第二步,直到各区间只有一个数(用递归方法实现)
快速排序图解:
在这里插入图片描述
代码演示:

package 八大排序;

import java.util.Arrays;

public class 快速排序 {
    public static void main(String[] args) {
        int[] arr = {4,21,5,86,74,12,57,42};
        quickSort(arr, 0, arr.length - 1);
        System.out.println(Arrays.toString(arr));
    }

    public static void quickSort(int[] arr, int start, int end) {
        if (start < end) {
            //获取分区索引
            int index = getIndex(arr, start, end);
            //对左右两个分区 再进行同样的步骤 ,即是递归调用
            quickSort(arr, start, index - 1);//左半部分
            quickSort(arr, index + 1, end);//右半部分
        }
    }

    private static int getIndex(int[] arr, int start, int end) {
        int i = start;
        int j = end;
        //定义基准数
        int x = arr[i];
        //循环
        while (i < j) {
            //从右往左比较,找出比基准数小的数
            while (i < j && arr[j] >= x) {
               j--;
            }
            //从右往左找到比基准数小的数了后,填坑
            if (i < j) {
                // 找比基准数小的数,填到基准数的坑位上
                arr[i] = arr[j];
                //让 i++,准备从左找比基准数大的数
                i++;
            }

            //从左往右找,找比基准数大的数
            while (i < j && arr[i] < x) {
                i++;
            }
            // 找比基准数大的数,找到后填到上一个坑
            if (i < j){     
               arr[j] = arr[i];
                //让 j--,准备下一次循环
               j--;
            }
        }
        //当上面的循环结束后把基准数填到最后一个坑位,也就以基准数为界,分成了左右两部分
        arr[i] = x; //把基准数填进去
        return i; //返回基准数所在位置的索引
    }
}
//基准数的左边没有数,不用进行再分区,基准数的右边进行再分区,

6、归并排序

归并排序原理:假设初始序列有N个记录,则可以看成是N个有序的子序列(拆分思想,递归实现),每个子序列的长度是1,然后两两归并,得到N/2个长度为2或1的有序子序列,再两两归并…如此重复,直到一个长度为N的有序子序列为止
归并排序图解:
在这里插入图片描述
代码演示:

package 八大排序;

import java.util.Arrays;

public class 归并排序 {
    public static void main(String[] args) {
        int[] arr = {4,21,5,86,74,12,57,42};
        chaiFen(arr,0,arr.length-1);
        System.out.println(Arrays.toString(arr));
    }

    private static void chaiFen(int[] arr, int start, int end) {
        if(start<end){
            int center=(start+end)/2;
            chaiFen(arr,start,center);
            chaiFen(arr,center+1,end);
            heBing(arr,start,center,end);
        }

    }

    private static void heBing(int[] arr, int start, int center, int end) {
        //定义一个临时数组
        int[] arr2 = new int[end - start + 1];
        //定义左边数组的起始索引
        int i=start;
        //定义右边数组的起始索引
        int j=center+1;
        //定义临时数组的起始索引
        int index=0;
        //比较左右两个数组的元素大小,往临时数组里加
        while (i<=center&&j<=end){
            //左小右大,临时数组加左边的数,同时左边数组索引自增一下,让左边下一个数继续和右边的数进行比较
            if(arr[i]<=arr[j]){
                arr2[index]=arr[i];
                i++;
            }else {  //反之,左大右小,临时数组加右边的数,同时右边索引自增一下,让右边下一个数继续和左边的数进行比较
                arr2[index]=arr[j];
                j++;
            }
            //让临时数组的索引也进行自增,保证临时数组每个索引都有值
            index++;
        }
        //处理左边剩余元素
        while (i<=center){
            arr2[index]=arr[i];
            i++;
            index++;
        }
        //处理右边剩余元素
        while (j<=end){
            arr2[index]=arr[j];
            j++;
            index++;
        }
        //将临时数组的元素装到原数组中
        for (int i1 = 0; i1 < arr2.length; i1++) {
            arr[i1+start]=arr2[i1];
        }
    }
}

7、基数排序

基数排序原理:基数排序属于分配式排序,又称桶子法,通过分配再收集的方法进行排序,属于稳定式排序。
基数排序图解:
在这里插入图片描述
代码演示:

package 八大排序;

import java.util.Arrays;

public class 基数排序 {
    public static void main(String[] args) {
        //基数排序:通过分配再收集的方法进行排序
        int[] arr = {4,21,5,86,74,12,57,42};
        //用来装数的桶
        int[][] arr2 = new int[10][arr.length];
        //定义统计数组
        int[] arr3 = new int[10];
        int max=0;
        for (int i : arr) {
            max=max>i?max:i;
        }
        //求出最大数是几位数,并将最大数传给排序方法
        int len = String.valueOf(max).length();
        //参一:原始数组  参二:用来装数的桶(二维数组) 参三:统计数组  参四:原始数组中最大的数的位数
        sort(arr, arr2, arr3, len);
        System.out.println(Arrays.toString(arr));
    }

    private static void sort(int[] arr, int[][] arr2, int[] arr3, int len) {
        //最大数是几位数,外层装桶几次
        for (int i = 0,n=1; i < len; i++,n*=10) {
            for (int j = 0; j < arr.length; j++) {
                int ys=arr[j]/n%10;
                //给对应的桶中装数
                arr2[ys][arr3[ys]++]=arr[j];
            }
            //将桶中的数拿出来
            int index=0;
            for (int h = 0; h < arr3.length; h++) {
                //统计数组的元素不为零,再将桶中的数拿出来
                if(arr3[h]!=0){
                    //统计数组中元素的大小是多少,则遍历几次,将对应桶中的元素全部拿出来
                    for (int k = 0; k < arr3[h]; k++) {
                        arr[index]=arr2[h][k];
                        index++;
                    }
                    //将统计数组清零,准备下一次装桶
                    arr3[h]=0;
                }
            }
        }
    }
}

8、堆排序

堆排序原理:堆排序是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
堆排序图解:
在这里插入图片描述
代码演示:

package 八大排序;

import java.util.Arrays;

public class 堆排序 {
    public static void main(String[] args) {
        //堆排序原理:堆排序是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
        //大顶堆:arr[i]>=arr[i*2+1]&&arr[i]>=arr[i*2+2]
        //小顶堆:arr[i]<=arr[i*2+1]&&arr[i]<=arr[i*2+2]
        int[] arr = {4,21,5,86,74,12,57,42};
        //求出最大的非叶子节点的索引
        int startIndex=(arr.length-1)/2;
        //循环开始调,最大的非叶子节点多大,则循环几次,从最大的非叶子节点开始调
        for (int i = startIndex; i >=0; i--) {
            toMaxheap(arr,arr.length,i);
        }
        //以上的运行结果已经达到大顶堆的效果,此时只需将根节点的元素与最后一个叶子节点的元素互换就行,并递归将剩余元素继续转化成大顶堆
        for (int i = arr.length-1; i > 0; i--) {
            int t=arr[i];
            arr[i]=arr[0];
            arr[0]=t;
            //将剩余元素继续转化为大顶堆结构
            toMaxheap(arr,i,0);
        }
        System.out.println(Arrays.toString(arr));
    }

    /**
     *
     * @param arr   //要进行排序的数组
     * @param size  //要排序的范围
     * @param startIndex  //起始的索引位置
     */
    private static void toMaxheap(int[] arr, int size, int startIndex) {
        //求出左右节点的索引
        int leftNodeIndex=startIndex*2+1;
        int rightNodeIndex=startIndex*2+2;
        //假设刚开始最大数的索引就是起始索引
        int maxIndex=startIndex;
        //求出最大节点所对应的索引
        if(leftNodeIndex<size&&arr[leftNodeIndex]>arr[maxIndex]){
            maxIndex=leftNodeIndex;
        }
        if(rightNodeIndex<size&&arr[rightNodeIndex]>arr[maxIndex]){
            maxIndex=rightNodeIndex;
        }
        //调换位置,将最大节点放在大顶堆的根节点处
        if(maxIndex!=startIndex){
            int t=arr[startIndex];
            arr[startIndex]=arr[maxIndex];
            arr[maxIndex]=t;
            //互换完之后可能会影响最大节点以下的大顶堆结构,所以这里需要递归调用方法,保证每个子树都是大顶堆结构
            toMaxheap(arr,size,maxIndex);
        }
    }
}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值